-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor warning/error parsing #800
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's very late here so don't take my comments seriously. I just added some pointers here. I should go to bed.
msg_parse = msg_spl[2:] | ||
if year not in parsed[action]: | ||
parsed[action][year] = {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use a defaultdict
here instead, i.e.
from collections import defaultdict # at the top
...
parsed = {'errors': defaultdict(dict), 'warnings': defaultdict(dict)}
Then you can get rid of the year not in
check. This is a common build pattern which is why defaultdict
was added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh nice. defaultdict
is pretty nifty. I wish I'd known about defaultdict
earlier.
webapp/apps/taxbrain/views.py
Outdated
@@ -151,6 +151,36 @@ def normalize(x): | |||
return ans | |||
|
|||
|
|||
def append_ew_file_input(error_list, msg, *args): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems redundant, since you only use this function once... Probably a cleaner way to do this would be to make the third argument of append_errors_warnings
be a method with two arguments, msg
and param
# line 619
append_errors_warnings(
errors_warnings,
errors,
lambda msg, _: errors.append(msg))
# line 500
append_errors_warnings(
errors_warnings,
personal_inputs,
lambda msg, param: personal_inputs.add_error(param, msg))
Then the append_errors_warnings
function would be
def append_errors_warnings(errors_warnings, append_obj, append_func):
...
append_func(msg, param)
Admittedly lambdas are frowned upon by some people but I think it makes for less redundant code here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have any aversion to lambdas. I think this looks a little cleaner.
Out of curiosity, why do some people frown upon lambda functions?
@@ -3,7 +3,10 @@ | |||
import taxcalc | |||
import numpy as np | |||
|
|||
from ..taxbrain.views import read_json_reform, parse_errors_warnings | |||
from ..taxbrain.views import (read_json_reform, parse_errors_warnings, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One handy software engineering tool you might be interested in is "blame". Basically, it's a tool that shows the last person to make changes to each line of code. GitHub has a more thorough explanation here. This isn't a review comment per se, but one thing to keep in mind when using that tool is writing code in a way that "preserves blame", in other words, so that you don't make changes to lines that you don't edit. In this case, the best way to "preserve blame" would be to write each import on a new line, so that if you add your own import, it doesn't update the blame on someone else's import, so you know the last person who thought that import was important to change. i.e.
from ..taxbrain.views import (
read_json_reform,
parse_errors_warnings,
...
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hadn't thought about preserving "blame" before. That makes a lot of sense. Thanks for the pointer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check out the blame tool, it is useful for figuring out who wrote something if you're trying to figure out why it was done that way (i.e. poorly documented code)
'2025': 'WARNING: _STD_3 value 168.81 < min value 11154.96 for 2025', | ||
'2026': 'WARNING: _STD_3 value 172.83 < min value 11422.83 for 2026', | ||
'2027': 'WARNING: _STD_3 value 176.98 < min value 11699.38 for 2027' | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One software engineering practice you might want to consider is separating "code" from "data". In this case the "data" is these warnings, which could be saved as like a separate JSON file somewhere and loaded into Python (using the default import json
library). The main goal is to abstract away this kind stuff from the core code logic, which makes your code much more readable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I see. I'll open a follow up PR to clean up test_reform.py
. There are plenty of data there that need to be moved into JSON files.
@codekansas Thanks for the review. Let me know what you think of the changes. |
@hdoupe LGTM |
Thanks for the review @codekansas |
This PR refactors the warning/error parsing logic. This reduces duplicated code and puts the warning/error parsing logic under test.
cc @codekansas