Skip to content
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

linting (automatic and manual) + pre-commit #2

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

mathematicalmichael
Copy link

@mathematicalmichael mathematicalmichael commented Jul 29, 2021

pip install pre-commit black flake8 and you're off to the races. no commits will ever contain unlinted code again. just set this up on cafelytics yesterday and wanted to practice on another project so I wouldn't forget the process of setting it up... figured I'd multitask and explore your api while doing so.

set up process (after installing the three packages above):
create the pre-commit yaml config file, pieced together for python relevant stuff but not too intrusive, just the basics.
pre-commit install
pre-commit run --all
then manual linting + checking with flake8 after auto-formatting with black.

didn't go so far as to define development dependencies because I didn't want to add a setup.cfg/py file at this stage. think you only need to run pre-commit install once in your local dev environment.

Comment on lines -37 to -52

# TODO: Build out additional endpoints

# /regulations

# /instruments

# /analytes

# /instruments

# /lab_results

# Optional: Find a way to generalize
# path("v1/<slug:endpoint>/", views.get_labs, name="endpoint"),

Choose a reason for hiding this comment

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

ah that's a shame. if you want these back in, I can add comments on the blank lines for placeholders.

@keeganskeate
Copy link
Member

Awesome for jumping right in @mathematicalmichael, linting is definitely needed. I will review this today.

Just a heads up, I've consolidated the API code (for now) into the main Cannlytics platform. As it's simply a Django app, it can be decoupled and run in a separate container if needed. Simply to speed up development I condensed the code base into 1 repository.

The API is functional for development in this repository, but you may want to work in the main repository for the time being. This repository may be updated in the future to contain a standalone implementation of the API.

Thank you again,
Keegan

@mathematicalmichael
Copy link
Author

Word! Would you be interested in this kind of PR on the other repo?

I did notice it was more active but didn't know what to make of that. Appreciate the explanation.

@keeganskeate
Copy link
Member

Definitely, let me explore the linting in this repository first, just don't want to add anything that may trip up the publishing process. This is the next task on my plate.

Copy link
Member

@keeganskeate keeganskeate left a comment

Choose a reason for hiding this comment

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

Hey Michael I am a fan of linting, so thank you for adding this. There are 2 main project-specific code style choices that have been made that conflict with the style enforced by Black:

  1. Apostrophes are preferred quotations for readability and speed of writing.
  2. A new line at the end of files is preferred to stay consistent with style across file types (i.e. all files should end in a new line, regardless of type). This is inline with the Python philosophy that there should be preferably 1 way to do something and special cases are not special enough to break the rules.

Other than these 2 main conflicts, Black does catch some fixes that need to be made, such as extra spaces, etc.

So, long story short, for my sake it would be a smaller change if you were able to ignore these 2 rules or make a request with specific style fixes, such as removing extraneous spaces.

Please let me know your thoughts and if I'm missing something. I definitely want to get your contribution committed.

Thank you and talk with you soon,
Keegan

@mathematicalmichael
Copy link
Author

yeahhh I prefer the apostrophes too. I write with them and let the autolinting take care of it as an after thought.
I am not sure if black allows overrides, I think its kind of against its philosophy. I do feel you on that, will look it up. May have to use autopep8 instead perhaps...

@mathematicalmichael
Copy link
Author

here's their rationale: https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html

let me know what you think. I dont care much, I type single ones while developing, and lint at the end.

there does seem to be an option to skip string normalization.

@keeganskeate
Copy link
Member

Thanks for looking into this. There appears to be an option to ignore single quotes. Perhaps we can try that and see if that would make adopting Black a smaller change. Would you mind exploring this option? Otherwise I can take a look tomorrow. Thank you for exploring this, it is going to be important to standardize the project to help with adoption.

Would you want to explore the option described below if you have time?

If you are adopting Black in a large project with pre-existing string conventions (like the popular “single quotes for data, double quotes for human-readable strings”), you can pass --skip-string-normalization on the command line. This is meant as an adoption helper, avoid using this for new projects.

@mathematicalmichael
Copy link
Author

mathematicalmichael commented Aug 2, 2021

@keeganskeate yeah I can try that but what do you think about the philosophy of "type single quotes, develop as you wish, and then let the formatter take care of linting?"

unfortunately I didn't stage the commits in pieces that would make reverting black easy (precommit was configured to not allow me to commit without black passing first, didn't think to disable that and commit that change first... but def noted for future attempts!!!), and did fix a number of linting errors manually. So I just want to make sure you're definitely sure that you want single quotes before re-doing the linting. That would look like: try a find/replace for all quotes to single, re-run black with that flag, and then manually review the diff to see if there were any double quotes that changed incorrectly.

@keeganskeate
Copy link
Member

Hey @mathematicalmichael , I don't have the strongest preference one way or the other (as long as the code runs!). I do have a slight preference for reading single quotes. I have been waffling over which to adopt, so if you have strong preferences then we can consider picking one.

If you don't mind, then smaller commits would be easier to review. I apologize that you may have to re-do some of the work. A good portion of the linting was helpful, so please see if there is a way that your work can be salvaged and merged in some manner.

So, perhaps start a new branch (not necessarily) and commit a handful of the changes and I can likely get everything merged. My apologies for the slow down, just want to make sure everything can get reviewed and merged into the project smoothly.

Thank you for your hard work.

P.S. I do think you may want to end up working in the main repository before too long, but please keep steamrolling wherever you are most comfortable.

@mathematicalmichael
Copy link
Author

@keeganskeate ran those sed statements and seems like there are some mixed usages left over. will comment in review.

""" Identify the user's Firebase account using an ID token. """
authorization = request.headers["Authorization"]
"""Identify the user's Firebase account using an ID token."""
authorization = request.headers['Authorization']
Copy link
Author

Choose a reason for hiding this comment

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

@keeganskeate preference?


Resources:

"""
import os
import requests

BASE = "http://127.0.0.1:4200/"
BASE = 'http://127.0.0.1:4200/'
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
BASE = 'http://127.0.0.1:4200/'
BASE = "http://127.0.0.1:4200/"

Comment on lines +18 to +19
BASE = 'http://127.0.0.1:4200/'
ENDPOINTS = ['', '/labs']
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
BASE = 'http://127.0.0.1:4200/'
ENDPOINTS = ['', '/labs']
BASE = "http://127.0.0.1:4200/"
ENDPOINTS = ["", "/labs"]

Copy link
Author

Choose a reason for hiding this comment

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

@keeganskeate how do you want to handle this?

</urlset>
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
</urlset>
</urlset>

Sitemap: https://www.api.cannlytics.com/sitemap.xml
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
Sitemap: https://www.api.cannlytics.com/sitemap.xml
Sitemap: https://www.api.cannlytics.com/sitemap.xml

# "--", "python", "manage.py", "collectstatic", "--no-input"]
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
# "--", "python", "manage.py", "collectstatic", "--no-input"]
# "--", "python", "manage.py", "collectstatic", "--no-input"]



def create_reference(database, reference):
"""Create a database reference for a given path."""
ref = database
parts = reference.split('/')
parts = reference.split("/")
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
parts = reference.split("/")
parts = reference.split('/')

@@ -31,7 +31,7 @@ def create_reference(database, reference):

def get_keywords(string):
"""Get keywords for a given string."""
keywords = string.lower().split(' ')
keywords = string.lower().split(" ")
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
keywords = string.lower().split(" ")
keywords = string.lower().split(' ')

Comment on lines +78 to +82
collection = collection.where(
filter["key"], filter["operation"], filter["value"]
)
if order_by and desc:
collection = collection.order_by(order_by, direction='DESCENDING')
collection = collection.order_by(order_by, direction="DESCENDING")
Copy link
Author

Choose a reason for hiding this comment

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

@keeganskeate mixed usage again.
Do you want these single or double?



def create_account(name, email, notification=True):
"""
Given user name and email, create an account if the email isn't being used
by an existing account.
"""
chars = 'abcdefghijklmnopqrstuvwxyz0123456789!@#$-_'
chars = "abcdefghijklmnopqrstuvwxyz0123456789!@#$-_"
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
chars = "abcdefghijklmnopqrstuvwxyz0123456789!@#$-_"
chars = 'abcdefghijklmnopqrstuvwxyz0123456789!@#$-_'

Comment on lines -142 to -147
print(
"File {} uploaded to {}.".format(
source_file_name, destination_blob_name
)
)

Copy link
Author

Choose a reason for hiding this comment

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

I actually prefer this older style but black does not... =/

Comment on lines +12 to +14
message = 'Welcome to the Cannlytics API.'
message += f'The current version is {VERSION} and is located at {BASE}/{VERSION}.'
return Response({'data': message}, content_type='application/json')
Copy link
Author

Choose a reason for hiding this comment

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

preference here?

Comment on lines +23 to +24
message += f'{endpoint}\n'
return Response({'data': message}, content_type='application/json')
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
message += f'{endpoint}\n'
return Response({'data': message}, content_type='application/json')
message += f"{endpoint}\n"
return Response({"data": message}, content_type="application/json")

Comment on lines +20 to +21
message = f'Welcome to {VERSION} of the Cannlytics API.'
message += 'Available endpoints:\n\n'
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
message = f'Welcome to {VERSION} of the Cannlytics API.'
message += 'Available endpoints:\n\n'
message = f"Welcome to {VERSION} of the Cannlytics API."
message += "Available endpoints:\n\n"

@mathematicalmichael
Copy link
Author

review leaves a lot of clarifications required. feel free to commit suggestions.

limit = request.query_params.get("limit", None)
order_by = request.query_params.get("order_by", "state")
# TODO: Get any filters from dict(request.query_params)
labs = get_collection('labs', order_by=order_by, limit=limit, filters=[])
return Response({ "data": labs}, content_type="application/json")
labs = get_collection("labs", order_by=order_by, limit=limit, filters=[])
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
labs = get_collection("labs", order_by=order_by, limit=limit, filters=[])
labs = get_collection('labs', order_by=order_by, limit=limit, filters=[])

@@ -29,17 +29,19 @@ def labs(request, format=None):
limit = request.query_params.get("limit", None)
order_by = request.query_params.get("order_by", "state")
# TODO: Get any filters from dict(request.query_params)
labs = get_collection('labs', order_by=order_by, limit=limit, filters=[])
return Response({ "data": labs}, content_type="application/json")
labs = get_collection("labs", order_by=order_by, limit=limit, filters=[])
Copy link
Author

@mathematicalmichael mathematicalmichael Aug 3, 2021

Choose a reason for hiding this comment

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

usage on line 90 uses double quotes, assuming that was the intent. leaving this

@@ -1,23 +1,26 @@
from rest_framework import status
# from rest_framework import status
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
# from rest_framework import status

from rest_framework.decorators import api_view
from rest_framework.response import Response

from utils.firebase import get_collection, get_document, update_document
# from utils.firebase import get_collection, get_document, update_document
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
# from utils.firebase import get_collection, get_document, update_document



@api_view(['GET', 'POST'])
def lab_results(request, format=None):
"""Get lab results data."""

if request.method == 'GET':
limit = request.query_params.get("limit", 1000)
limit = request.query_params.get('limit', 1000)
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
limit = request.query_params.get('limit', 1000)
limit = request.query_params.get("limit", 1000)

if limit:
limit = int(limit)
order_by = request.query_params.get("order_by", "")
order_by = request.query_params.get('order_by', '')
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
order_by = request.query_params.get('order_by', '')
order_by = request.query_params.get("order_by", "")

Comment on lines +19 to +21
docs = get_collection(
'tests/leaf/lab_results', order_by=order_by, limit=limit, filters=[]
)
Copy link
Author

Choose a reason for hiding this comment

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

I feel like I recall another get_collection with double quotes.

@@ -28,12 +31,13 @@ def mmes(request, format=None):
"""Get licensee (MME) data."""

if request.method == 'GET':
limit = request.query_params.get("limit", None)
limit = request.query_params.get('limit', None)
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
limit = request.query_params.get('limit', None)
limit = request.query_params.get("limit", None)

if limit:
limit = int(limit)
order_by = request.query_params.get("order_by", "")
order_by = request.query_params.get('order_by', '')
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
order_by = request.query_params.get('order_by', '')
order_by = request.query_params.get("order_by", "")

from datetime import datetime
from rest_framework import status

# from rest_framework import status
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
# from rest_framework import status

Comment on lines +6 to +8

# from .auth import authenticate
# from utils.firebase import get_document, update_document
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
# from .auth import authenticate
# from utils.firebase import get_document, update_document



@api_view(['GET'])
def base(request, format=None):
"""Informational version endpoint."""
message = f"Welcome to {VERSION} of the Cannlytics API. Available endpoints:\n\n"
message = f'Welcome to {VERSION} of the Cannlytics API. Available endpoints:\n\n'
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
message = f'Welcome to {VERSION} of the Cannlytics API. Available endpoints:\n\n'
message = f"Welcome to {VERSION} of the Cannlytics API. Available endpoints:\n\n"

Comment on lines +53 to +54
message += f'{endpoint}\n'
return Response({'message': message}, content_type='application/json')
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
message += f'{endpoint}\n'
return Response({'message': message}, content_type='application/json')
message += f"{endpoint}\n"
return Response({"message": message}, content_type="application/json")

print("Getting user...")
# limit = request.query_params.get("limit", None)
# order_by = request.query_params.get("order_by", "state")
print('Getting user...')
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
print('Getting user...')
print("Getting user...")

Comment on lines +69 to +70
# limit = request.query_params.get('limit', None)
# order_by = request.query_params.get('order_by', 'state')
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
# limit = request.query_params.get('limit', None)
# order_by = request.query_params.get('order_by', 'state')
# limit = request.query_params.get("limit", None)
# order_by = request.query_params.get("order_by", "state")

# # TODO: Get any filters from dict(request.query_params)
# labs = get_collection('labs', order_by=order_by, limit=limit, filters=[])
user = {}
return Response({ "data": user}, content_type="application/json")
return Response({'data': user}, content_type='application/json')
Copy link
Author

@mathematicalmichael mathematicalmichael Aug 3, 2021

Choose a reason for hiding this comment

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

Suggested change
return Response({'data': user}, content_type='application/json')
return Response({"data": user}, content_type="application/json")


# Update or create user(s).
elif request.method == 'POST':
print("Creating a user...")
return Response({ "success": True}, content_type="application/json")
print('Creating a user...')
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
print('Creating a user...')
print("Creating a user...")

print("Creating a user...")
return Response({ "success": True}, content_type="application/json")
print('Creating a user...')
return Response({'success': True}, content_type='application/json')
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
return Response({'success': True}, content_type='application/json')
return Response({"success": True}, content_type="application/json")

Comment on lines +93 to +94
limit = request.query_params.get('limit', None)
order_by = request.query_params.get('order_by', 'state')
Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
limit = request.query_params.get('limit', None)
order_by = request.query_params.get('order_by', 'state')
limit = request.query_params.get("limit", None)
order_by = request.query_params.get("order_by", "state")

@mathematicalmichael
Copy link
Author

ugh yeah... this wasn't a great idea. I think if you want to adopt black entirely, best to do so without the flag. it was addressing inconsistent usage.

since this repo isn't in use, might as well close this out but re-try on the real repo with the .pre-commit-config.yaml file from this PR, deal with it there instead.

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.

2 participants