Python style enforced with pre-commit hook#185
Conversation
Added flake8-bugbear, pre-commit and black. Contributing.py will have to be updated to reflect new command to install the deps: `pipenv install -d --pre`
This is so that team members can use the same Flake8 configuration with their editor, before trying to commit. Setting up their editor to lint with Flake8 should save on some headaches when trying to commit.
This is the file that sets up the pre-commit formatting and linting. To install, team members will have to run `pre-commit install` once.
Some of the __init__.py files are used for imports. Flake8 raises an unused import error for these and also complains if the import was a * import. The unused import error can be resolved by putting the name of the class or function being imported into __all__, but there will still be an error if a * import is used. Since we are still actively creating fixtures and other tests that might be imported through these __init__ files, I think we should leave the files be for now and just have Flake8 skip over them during the pre-commit check.
I had to refactor these functions because we were improperly assigning default values to function calls and mutable data structs. Below are the excellent flake8-bugbear warnings that I had to resolve: (for tenant and property fixtures) B006 Do not use mutable data structures for argument defaults. They are created during function definition time. All calls to the function reuse this one instance of that data structure, persisting changes between them. (for lease, contact_number, ticket and notes fixtures) B008 Do not perform function calls in argument defaults. The call is performed only once at function definition time. All calls to your function will reuse the result of that definition-time function call. If this is intended, assign the function call to a module-level variable and use that variable as a default value.
In these tests: - `test_pm_is_authorized_to_get_all` - `test_staff_are_authorized_to_get_all` - `test_admin_is_authorized_to_get_all` creat_lease() was assigned to the variable `lease`, but the variable was never used. I couldn't tell if this function call was needed (the tests still passed when the line was removed), but the variable name definitely wasn't. I just changed the line to a bare function call instead of a variable assignment in order to avoid an unused variable warning.
Added instructions for initial installation of dependencies and the pre-commit hook. Added instructions for the use of pre-commit hook. Still need to add instructions for setting up/using Flake8 and Black on editors/command line
(aka cleaning house) Very little actual code was changed. The majority of changes in this commit were: - reformatting - removing unused imports - removing unused variables - occasionally changing `if not "string" in foo` to `if "string" not in foo` - occasionally changing == to is or != to is not
|
You might notice that in Also, the Flake8 pre-commit is currently configured to ignore |
|
Also, documentation should probably be made on how to set up Flake8 and Black for use on editors and the command line (e.g., format on save and auto-linting). When used properly in your workflow, you won't have to change much at commit time because most of it will already pass the pre-commit checks. This could maybe be a separate issue? |
NickSchimek
left a comment
There was a problem hiding this comment.
Thanks for doing all of this work! I have a few suggestions, but nothing that would stop this from being merged.
|
|
||
| def test_pm_is_authorized_to_get_all(self, pm_header, create_lease): | ||
| lease = create_lease() | ||
| create_lease() |
There was a problem hiding this comment.
yeah, we don't need this line. These are testing auths, and it shouldn't matter if there is data or not.
There was a problem hiding this comment.
Cool, I thought so, but wasn't sure. I'll delete that line from the three tests.
| emergency_contact = create_emergency_contact() | ||
|
|
||
| def _create_contact_number(emergency_contact=emergency_contact): |
There was a problem hiding this comment.
this keeps the current behavior intact. However, since these are fixtures, it would be better if each call to the fixture is completely dynamic.
Perhaps we can do something like this instead: It is ugly, but I believe this is the only way to do, what I intended to do, in Python.
def _create_contact_number(emergency_contact=None):
if not emergency_contact:
emergency_contact = create_emergency_contact()
There was a problem hiding this comment.
Okay, I'll do that for the four fixtures that were changed like this one.
| - Note: It is not necessary to install python before installing pipenv. | ||
| - Please install pipenv according to their docs for your OS. | ||
| 3. Install dependencies `pipenv install -d` | ||
| 3. Install dependencies `pipenv install -d --pre` |
There was a problem hiding this comment.
This is getting to be annoying. I wish pipenv would install everything by default
There was a problem hiding this comment.
I agree. One thing we could do is add a new custom script in the [scripts] section of the pipfile.
For example, we could add this line:
get_deps = "pipenv install -d --pre"
Then when we want to install and update dependencies, we would run:
pipenv run get_deps
There was a problem hiding this comment.
That would be great! Perhaps naming it pipenv run dev-install
| - The pre-commit hook will check your code every time you try to commit. If your code needs re-formatting, that will happen automatically. If you have non-formatting errors in your code, these will be printed to the terminal with the error, filename and line number. You will need to resolve these yourself. | ||
| - After your code has been reformatted and/or you have resolved other errors, you will need to add and commit those files again (because they have been modified). | ||
| - Successful commits can then be pushed to your remote branch like normal. | ||
|
|
There was a problem hiding this comment.
Looks good! Thank you for updating the docs!
| # if this tenant has a lease | ||
| if ( | ||
| "dateTimeEnd" in leaseData | ||
| and "dateTimeStart" in leaseData | ||
| and "propertyID" in leaseData | ||
| ): |
There was a problem hiding this comment.
We should probably create an issue to refactor this or do it now. I'd like to remove this completely, but that might not be possible without changing the frontend.
There are two issues here that make it hard to read.
- The comment
- the multi-line if statement
I would suggest changing it to something like this instead:
if _lease():
...
...
def _lease():
return (
"dateTimeEnd" in leaseData
and "dateTimeStart" in leaseData
and "propertyID" in leaseData
)
There was a problem hiding this comment.
That makes sense. I've refactored it and got it working. If it still bothers us down the line, we can always refactor again 😆
| @@ -1 +1 @@ | |||
| python-3.8.2 No newline at end of file | |||
| python-3.8.2 | |||
There was a problem hiding this comment.
I don't see any difference. What changed here? 🤔
There was a problem hiding this comment.
It added a newline. I'm not sure why GitHub makes it difficult to see whitespace changes sometimes.
Yes, separate issue is fine. This would be great information to have, but I imagine this info is editor dependent and we can't support docs for every editor. I think it would be best if we could redirect to some external documentation. |
As per @NickSchimek's request, removed unneeded calls to `create_lease()` in `integration/test_leases` and refactored the following factory fixtures: - contact_number - lease - ticket - notes
Now you can run `pipenv run dev-install` instead of `pipenv install -d --pre`
|
@NickSchimek thanks for taking the time to review this massive PR! I made the changes you suggested. Let me know if you see anything else that needs cleaning up. |
NickSchimek
left a comment
There was a problem hiding this comment.
This looks great! Thank you!
What issue is this solving?
Closes codeforpdx/dwellingly-app/issues/348
This PR adds Flake8-bugbear, Black and Pre-commit dependencies in order to enforce clean and uniform python style throughout the backend.
Once installed, the pre-commit hook will automatically perform the following actions when you try to make a commit:
If the hook re-formatted any of your code or if you had to fix something to resolve a Flake8 error, you will need to add and commit those files again in git because they have been further modified.
A few files had some specific code changed in order to comply with the new, stricter linting, but most of the changes are formatting.
I tried to keep all important changes in their own commits, with the most recent commit reserved for the non-critical formatting changes.
Any helpful knowledge/context for the reviewer?
Is a re-seeding of the database necessary? I don't think so.
Any new dependencies to install? YES
Any special requirements to test? YES
New instructions for dependency install
Because Black still hasn't released an official version 1.0.0, you have to allow for pre-release packages when installing with pipenv:
pipenv install -d --preAlso, once you install the dependencies, you will need to install the pre-commit hook for it to work (only once, though we might need to do this again if the pre-commit config gets changed in the future):
pipenv run pre-commit installPlease make sure you've attempted to meet the following coding standards