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
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@
*.pyo
*.pyd
README.md
.admin/tokens
.admin/tokens
5 changes: 5 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[flake8]
ignore = D203
exclude = .git,__pycache__,docs/source/conf.py,old,build,dist
max-complexity = 10
max-line-length = 88
18 changes: 18 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.3.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace

- repo: https://github.com/psf/black
rev: 19.3b0
hooks:
- id: black
args: ['--skip-string-normalization']

- repo: https://github.com/pycqa/flake8
rev: 3.9.2
hooks:
- id: flake8
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,4 @@
]
}
]
}
}
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"python.linting.pylintEnabled": true,
"[python]": {
"editor.insertSpaces": true,
"editor.tabSize": 4
"editor.tabSize": 4
},
"todo-tree.highlights.customHighlight": {
"TODO": {
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 changes: 5 additions & 5 deletions cannlytics_api/api/auth.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@

from firebase_admin import auth


def authenticate(request):
""" 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?

token = authorization.split(' ')[1]
claims = auth.verify_id_token(token)
uid = claims['uid']
request.session['uid'] = uid # Save user's custom claims in a session?
return claims
request.session['uid'] = uid # Save user's custom claims in a session?
return claims
18 changes: 10 additions & 8 deletions cannlytics_api/api/base.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
from rest_framework.decorators import api_view
from rest_framework.response import Response

BASE = "https://api.cannlytics.com"
ENDPOINTS = ["labs"]
VERSION = "v1"
BASE = 'https://api.cannlytics.com'
ENDPOINTS = ['labs']
VERSION = 'v1'


@api_view(['GET'])
def index(request, format=None):
"""Informational base endpoint."""
message = f"Welcome to the Cannlytics API. The current version is {VERSION} and is located at {BASE}/{VERSION}."
return Response({ "data": message}, content_type="application/json")
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')
Comment on lines +12 to +14
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?



@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.'
message += 'Available endpoints:\n\n'
Comment on lines +20 to +21
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"

for endpoint in ENDPOINTS:
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 +23 to +24
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")

14 changes: 9 additions & 5 deletions cannlytics_api/api/cannlypedia.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from rest_framework.decorators import api_view
from rest_framework.response import Response


@api_view(['GET'])
def scholars(request, format=None):
"""Get information about scholars."""
Expand All @@ -9,6 +10,7 @@ def scholars(request, format=None):
author = request.query_params.get('q', None)
if author:
from scholarly import scholarly

search_query = scholarly.search_author(author)
author_source = next(search_query)
author_data = {
Expand All @@ -18,9 +20,11 @@ def scholars(request, format=None):
'email_domain': author_source['email_domain'],
'interests': author_source['interests'],
'photo_url': author_source['url_picture'],
}
return Response(author_data, content_type="application/json")
}
return Response(author_data, content_type='application/json')

# Return an error if no author is specified.
error_message = 'Author not found in request. Specify ?q={url_encoded_author_name}'
return Response({ "error": error_message}, content_type="application/json")
error_message = (
'Author not found in request. Specify ?q={url_encoded_author_name}'
)
return Response({'error': error_message}, content_type='application/json')
68 changes: 34 additions & 34 deletions cannlytics_api/api/labs.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ def lab(request, format=None):

# Query labs.
if request.method == 'GET':
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=[])
return Response({ "data": labs}, content_type="application/json")
return Response({'data': labs}, content_type='application/json')


@api_view(['GET', 'POST'])
Expand All @@ -26,56 +26,58 @@ def labs(request, format=None):

# Query labs.
if request.method == 'GET':
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=[])
return Response({ "data": labs}, content_type="application/json")
return Response({'data': labs}, content_type='application/json')

# Update a lab given a valid Firebase token.
elif request.method == 'POST':

# Check token.
try:
claims = authenticate(request)
except:
return Response({"error": "Could not authenticate."}, status=status.HTTP_400_BAD_REQUEST)
except Exception: # TODO: what is the correct exception?
return Response(
{'error': 'Could not authenticate.'}, status=status.HTTP_400_BAD_REQUEST
)

# Get the posted lab data.
lab = request.data
org_id = lab["id"]
lab["slug"] = slugify(lab["name"])
org_id = lab['id']
lab['slug'] = slugify(lab['name'])

# TODO: Handle adding labs.
# Create uuid, latitude, and longitude, other fields?

# Determine any changes.
existing_data = get_document(f"labs/{org_id}")
existing_data = get_document(f'labs/{org_id}')
changes = []
for key, after in lab:
before = existing_data[key]
if before != after:
changes.append({"key": key, "before": before, "after": after})
changes.append({'key': key, 'before': before, 'after': after})

# Get a timestamp.
timestamp = datetime.now().isoformat()
lab["updated_at"] = timestamp
lab['updated_at'] = timestamp

# Create a change log.
log_entry = {
"action": "Updated lab data.",
"type": "change",
"created_at": lab["updated_at"],
"user": claims["uid"],
"user_name": claims["display_name"],
"user_email": claims["email"],
"photo_url": claims["photo_url"],
"changes": changes,
'action': 'Updated lab data.',
'type': 'change',
'created_at': lab['updated_at'],
'user': claims['uid'],
'user_name': claims['display_name'],
'user_email': claims['email'],
'photo_url': claims['photo_url'],
'changes': changes,
}
update_document(f"labs/{org_id}/logs/{timestamp}", log_entry)
update_document(f'labs/{org_id}/logs/{timestamp}', log_entry)

# Update the lab.
update_document(f"labs/{org_id}", lab)
update_document(f'labs/{org_id}', lab)

return Response(log_entry, status=status.HTTP_201_CREATED)

Expand All @@ -85,13 +87,12 @@ def lab_logs(request, org_id, format=None):
"""Get or create lab logs."""

if request.method == 'GET':
data = get_collection(f"labs/{org_id}/logs")
return Response({ "data": data}, content_type="application/json")
data = get_collection(f'labs/{org_id}/logs')
return Response({'data': data}, content_type='application/json')

elif request.method == 'POST':
# TODO: Create a log.
return Response({ "data": "Under construction"}, content_type="application/json")

return Response({'data': 'Under construction'}, content_type='application/json')


@api_view(['GET', 'POST'])
Expand All @@ -101,10 +102,9 @@ def lab_analyses(request, org_id, format=None):
"""

if request.method == 'GET':
data = get_collection(f"labs/{org_id}/analyses")
return Response({ "data": data}, content_type="application/json")
data = get_collection(f'labs/{org_id}/analyses')
return Response({'data': data}, content_type='application/json')

elif request.method == 'POST':
# TODO: Create an analysis.
return Response({ "data": "Under construction"}, content_type="application/json")

return Response({'data': 'Under construction'}, content_type='application/json')
30 changes: 17 additions & 13 deletions cannlytics_api/api/leaf_test_api.py
Original file line number Diff line number Diff line change
@@ -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

from utils.firebase import get_collection


@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", "")

# TODO: Get any filters from dict(request.query_params)
docs = get_collection('tests/leaf/lab_results', order_by=order_by, limit=limit, filters=[])
return Response(docs, content_type="application/json")

docs = get_collection(
'tests/leaf/lab_results', order_by=order_by, limit=limit, filters=[]
)
Comment on lines +19 to +21
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.

return Response(docs, content_type='application/json')

if request.method == 'POST':
print('TODO: Create lab results')
return NotImplementedError
Expand All @@ -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", "")

# TODO: Get any filters from dict(request.query_params)
# e.g. {"key": "name", "operation": "==", "value": "xyz"}
docs = get_collection('tests/leaf/mmes', order_by=order_by, limit=limit, filters=[])
return Response(docs, content_type="application/json")

# e.g. {'key': 'name', 'operation': '==', 'value': 'xyz'}
docs = get_collection(
'tests/leaf/mmes', order_by=order_by, limit=limit, filters=[]
)
return Response(docs, content_type='application/json')
34 changes: 18 additions & 16 deletions cannlytics_api/api/users.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@

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

from rest_framework.decorators import api_view
from rest_framework.response import Response
from .auth import authenticate
from utils.firebase import get_document, update_document

# from .auth import authenticate
# from utils.firebase import get_document, update_document
Comment on lines +6 to +8
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', 'POST'])
Expand All @@ -13,30 +14,31 @@ def users(request, format=None):
# try:
# claims = authenticate(request)
# except:
# return Response({"error": "Could not authenticate."}, status=status.HTTP_400_BAD_REQUEST)
# return Response({'error': 'Could not authenticate.'},
# status=status.HTTP_400_BAD_REQUEST)

# Get user(s).
if request.method == 'GET':
print("Getting user...")
# limit = request.query_params.get("limit", None)
# order_by = request.query_params.get("order_by", "state")
print('Getting user...')
# 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')

# Update or create user(s).
elif request.method == 'POST':
# TODO: Check if user already exists.
# get_document
print("Creating a user...")
print('Creating a user...')
timestamp = datetime.now().isoformat()
email = request.query_params.get("email", "")
email = request.query_params.get('email', '')
user = {
"email": email,
"created_at": timestamp,
# "uid": user.uid,
"photo_url": f"https://robohash.org/${email}?set=set5",
'email': email,
'created_at': timestamp,
# 'uid': user.uid,
'photo_url': f'https://robohash.org/${email}?set=set5',
}
print(user)
return Response({ "success": True}, content_type="application/json")
return Response({'success': True}, content_type='application/json')
Loading