Skip to content

Several misc. fixes, cleanups, features#21

Merged
ericaltendorf merged 7 commits into
developmentfrom
misc
Feb 8, 2021
Merged

Several misc. fixes, cleanups, features#21
ericaltendorf merged 7 commits into
developmentfrom
misc

Conversation

@ericaltendorf

Copy link
Copy Markdown
Owner
  • Fix logic for identifying plotting processes
  • Update sample config file to be valid and better commented
  • Add a job-progress histogram to the interactive display
  • Various minor fixes and cleanups

@altendky altendky left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, but I didn't get to a whole lot of review of correctness. Something I need to work on and also something that follows from 1) me being new to this code and 2) us being new to each other's 'style' preferences so that stuff jumps out etc. Hopefully the explanations are either things you don't know or aspects you hadn't considered.

Compound PRs addressing multiple things generally end up being way harder to review since the reviewer has to dissect which bit goes with what. Also, it means you are pretty likely to have several things held up from getting merged over some discussion related to just one little bit of the PR.

class Log:
    entries = []
    cur_pos = 0

I personally use https://attrs.org for pretty much all of my classes. But, to this approach... Those aren't defining attributes of the class instances, but attributes of the class itself. Effectively globals that are just accessed via the class. If you self.cur_pos = 3 then you are adding an instance attribute shadowing the class attribute. If you self.entries.append(3) you are mutating the single class attribute, not an instance specific list. So, all instances will see that new value on the end of the list. This is related to the common mutable function parameter default confusion.

FYI about GitHub reviews and suggestions. If you like a suggestion exactly as is you can either commit it individually or group it together with others and commit them in a batch by clicking the corresponding buttons. It can be convenient for you and, in cases where you care, it lists the suggester as an author on the commit as well. (I don't care for my contributions but would for other people's)

image

You've got tests now. Add CI next. :]

Comment thread interactive.py
Comment on lines +108 to +113
# TODO: handle resizing. Need to (1) figure out how to reliably get
# the terminal size -- the recommended method doesn't seem to work
# (n_rows, n_cols) = map(int, stdscr.getmaxyx()) ...doesn't work
# ...map(int, os.popen('stty size', 'r').read().split() ...may work
# and then (2) implement the logic to resize all the subwindows as above

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tend to not use map/filter and instead just use comprehensions such as [int(v) for v in stdscr.getmaxyx()]. It is more flexible, doesn't require a function (or lambda) definition and call to do things, combines both map and filter functionality, and more. But sure, some people like the 'functional' feel of map etc.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed here; will keep in mind in the future as well, thanks.

Comment thread interactive.py Outdated
Comment on lines 119 to 120
full_refresh = False
if (elapsed < refresh_period):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
full_refresh = False
if (elapsed < refresh_period):
full_refresh = elapsed >= refresh_period
if not full_refresh:

Maybe even rename it do_full_refresh or refresh_needed or...

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense.

Comment thread interactive.py Outdated
jobs = Job.get_running_jobs_w_cache(dir_cfg['log'], jobs)

else:
full_refresh = True

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
full_refresh = True

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack.

Comment thread interactive.py Outdated
Comment on lines +167 to +169
timestamp = datetime.datetime.now().strftime("%H:%M:%S")
refresh_msg = "now" if full_refresh else ('%ds/%ds' % (elapsed, refresh_period))
header_win.addnstr(' %s (refresh %s)' % (timestamp, refresh_msg), linecap)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would personally reach for Pendulum pretty quickly when I hit time stuff. Maybe not for these lines but... pretty quickly.

Suggested change
timestamp = datetime.datetime.now().strftime("%H:%M:%S")
refresh_msg = "now" if full_refresh else ('%ds/%ds' % (elapsed, refresh_period))
header_win.addnstr(' %s (refresh %s)' % (timestamp, refresh_msg), linecap)
timestamp = datetime.datetime.now().strftime("%H:%M:%S")
refresh_msg = "now" if full_refresh else f"{elapsed}s/{refresh_period}s"
header_win.addnstr(f" {timestamp} (refresh {refresh_msg})", linecap)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice.

Comment thread job.py Outdated
Comment on lines +61 to +65
return (len(cmdline) >= 4 and
'python' in cmdline[0] and
'venv/bin/chia' in cmdline[1] and
'plots' == cmdline[2] and
'create' == cmdline[3])

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return (len(cmdline) >= 4 and
'python' in cmdline[0] and
'venv/bin/chia' in cmdline[1] and
'plots' == cmdline[2] and
'create' == cmdline[3])
return (
len(cmdline) >= 4
and "python" in cmdline[0]
and "venv/bin/chia" in cmdline[1]
and "plots" == cmdline[2]
and "create" == cmdline[3]
)

Per both my preference and black's. Locating the delimiting bit at the beginning of the line makes it stand out better. Putting all lines inside the parentheses makes them all a bit more equally treated.

This is also basically an @staticmethod. May as well just be a function outside the class.

https://mail.python.org/pipermail/python-ideas/2016-July/041189.html

Honestly, staticmethod was something of a mistake -- I was trying to
do something like Java class methods but once it was released I found
what was really needed was classmethod. But it was too late to get rid
of staticmethod.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, I'm learning a lot.

Comment thread reporting.py Outdated


def n_at_ph(jobs, ph):
return len([j for j in jobs if j.progress() == ph])

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dunno, perhaps this is 'tricky'. But, creating an actual list to count stuff isn't pretty either.

Suggested change
return len([j for j in jobs if j.progress() == ph])
return sum(1 for j in jobs if j.progress() == ph)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's clever. I was looking for something like "count()" that would take a bool-returning function, kind of like map, but couldn't find one. This works.

Comment thread reporting.py
Comment on lines +33 to +45
def n_to_char(n):
if n == 0:
return ' '
elif n == 1:
return '.'
elif n == 2:
return ':'
elif n == 3:
return ';'
elif n >= 4:
return '!'
else:
return 'X' # Should never be negative

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def n_to_char(n):
if n == 0:
return ' '
elif n == 1:
return '.'
elif n == 2:
return ':'
elif n == 3:
return ';'
elif n >= 4:
return '!'
else:
return 'X' # Should never be negative
n_to_char_mapping = dict(enumerate(" .:;"))
def n_to_char(n):
if n < 0:
return 'X' # Should never be negative
return n_to_char_mapping.get(n, "!")

Might also like mapping to braille dots. I feel a little inappropriate misusing those characters, but they do work nicely for 'modern' spinners and such.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. I took a slightly different approach to this to make the "!" treated more like the other chars.

Braille dots is an interesting option I hadn't thought of. I did figure there would be some extended charset characters I could use but wasn't sure if I wanted to step out of ASCII.

Comment thread reporting_test.py
@@ -0,0 +1,61 @@
#!/usr/bin/python3

from unittest.mock import patch

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I very rarely mock.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As in, you rarely need to, or there's another mechanism you prefer, or you structure your code so you don't need mock-style mechanisms?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I try to avoid the need. I see tests as a second use of your code. If it's hard to test, it can mean your code isn't as flexible as it ought to be. So yeah, different code structure often. Lots of details to discuss in each actual case.

Comment thread reporting_test.py

import os
import pyfakefs
import unittest

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I always use pytest.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, OK, added an issue to consider switching to pytest.

Comment thread reporting.py Outdated
Comment on lines +25 to +27
return (' '.join(['%d:%d' % pair for pair in phases[:n_first]]) +
" [+%d] " % n_elided +
' '.join(['%d:%d' % pair for pair in phases[n_first + n_elided:]]))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More variables, less one-liner here. :]

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK :)

@altendky

altendky commented Feb 7, 2021

Copy link
Copy Markdown
Collaborator

If you want to be picky about your commit messages... GitHub suggests a length limit of 50.

image

If you want focused granular commits, also and and etc are hints you aren't achieving the goal.

As far as granular PRs... at various points I've made compound PRs because there's a lot of stuff mixing together. When I'm being good, I go back and break off auxiliary PRs. As each of the pieces gets merged and you catch up the original branch, it'll get more and more focused.

@ericaltendorf

Copy link
Copy Markdown
Owner Author

Thanks for all the comments. Addressed most, will leave some larger ones (consider use of attrs, pytest) to later.

@ericaltendorf ericaltendorf linked an issue Feb 7, 2021 that may be closed by this pull request
@ericaltendorf ericaltendorf merged commit e9c32a2 into development Feb 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Check in a current and canonicalized config.yaml

2 participants