Skip to content

Commit

Permalink
Merge pull request #63 from joecummings/refactor-logging
Browse files Browse the repository at this point in the history
Update Makefile w/ new style checks; remove unnecessary logging info
  • Loading branch information
joecummings authored Jan 25, 2021
2 parents 94c78c1 + d7b215c commit 16462e1
Show file tree
Hide file tree
Showing 20 changed files with 238 additions and 324 deletions.
22 changes: 22 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[flake8]
exclude =
# __init__.py file imports raise warnings about unused imports
__init__.py
ignore =
# False positives on imports used only in generic type annotations
F401
# Black recommends disabling
E203
W503
# the next two are hanging indent errors. We exclude these because pylint
# already catches them and in a few places we need to manually suppress
# them to avoid fighting with PyCharm. We'd rather just add one
# suppression comment.
E128
E131
# isort handles this now
E402
# already covered by PyLint and gives false positives for typing.overload
F811
# Let Black handle line length
max-line-length = 300
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ __pycache__/
.pytest_cache/
gitmine.key
build/
dist/
dist/
.coverage
5 changes: 3 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ cache:
pip: true

install:
- pip install -r requirements-dev.txt
- pip install -r requirements.txt
- pip install -e .

script:
- echo "python version $(python --version) running"
- echo "pip version $(pip --version) running"
- pytest tests/
- mypy gitmine/ tests/ --no-strict-optional --ignore-missing-imports
- make check
- pytest tests/
1 change: 0 additions & 1 deletion MANIFEST.in

This file was deleted.

41 changes: 41 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
default:
@echo "an explicit target is required"

SHELL=/usr/bin/env bash

PYTHON_FILES=gitmine/*.py gitmine/commands/*.py

install:
pip install -r requirements.txt

lint:
pylint $(PYTHON_FILES)

docstyle:
pydocstyle --convention=google $(PYTHON_FILES)

mypy:
mypy $(PYTHON_FILES)

flake8:
flake8 $(PYTHON_FILES)

SORT=LC_ALL=C sort --key=1,1 --key=3V --field-separator="="

reqs-fix:
$(SORT) --output=requirements.txt requirements.txt
$(SORT) --output=requirements-dev.txt requirements-dev.txt

reqs-check:
$(SORT) --check requirements.txt
$(SORT) --check requirements-dev.txt

black-fix:
isort $(PYTHON_FILES)
black --config pyproject.toml $(PYTHON_FILES)

black-check:
isort --check $(PYTHON_FILES)
black --config pyproject.toml --check $(PYTHON_FILES)

check: reqs-check black-check flake8 mypy lint
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

Stop getting buried under countless Github Issues and PRs. Organize, reference, and close with ease.

Based on the amazing work done by Github itself on [hub](https://github.com/github/hub).
Based on the amazing work done by Github itself on [hub](https://github.com/github/hub) and [Github CLI](https://cli.github.com/) (release while we were working on this project. Well done, us).

#### Who is this for?

Expand Down
68 changes: 33 additions & 35 deletions gitmine/commands/config.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,27 @@
import base64
import binascii
import logging
import os
from contextlib import contextmanager
from copy import copy
from pathlib import Path
from typing import Union
from types import TracebackType
from typing import IO, Optional, Type

import click
from cryptography.exceptions import InvalidSignature
from cryptography.fernet import Fernet, InvalidToken
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC

from gitmine.constants import GITHUB_CREDENTIALS_PATH, KEY_PATH, LOGGER
from gitmine.constants import GITHUB_CREDENTIALS_PATH, KEY_PATH

logger = logging.getLogger(LOGGER)
logger = logging.getLogger()


class GithubConfig:
""" Github Config object, holds information about username and bearer token
"""

def __init__(self):
self.token = None
self.username = None
self.key = None
def __init__(self) -> None:
self.token = ""
self.username = ""
self.key = ""

def get_value(self, prop: str) -> str:
def get_value(self, prop: str) -> Optional[str]:
if prop == "key":
return self.key
elif prop == "token":
Expand All @@ -37,7 +30,7 @@ def get_value(self, prop: str) -> str:
return self.username
raise click.BadArgumentUsage(message=f"Unknown property specified: {prop}")

def set_prop(self, prop: str, value: Union[str, bytes]) -> None:
def set_prop(self, prop: str, value: str) -> None:
if prop == "key":
self.key = value
elif prop == "token":
Expand All @@ -48,9 +41,7 @@ def set_prop(self, prop: str, value: Union[str, bytes]) -> None:
raise click.BadArgumentUsage(message=f"Unknown property specified: {prop}")


def config_command(
ctx: click.Context, prop: str, value: str, encrypt: bool, decrypt: bool
) -> None:
def config_command(ctx: click.Context, prop: str, value: str, encrypt: bool, decrypt: bool) -> None:
""" Implementation of the *config* command
"""
handle_encrypt_option(encrypt, decrypt)
Expand All @@ -61,12 +52,12 @@ def config_command(
elif value:
ctx.obj.set_prop(prop, value)

with open_credentials("r") as read_handle:
with OpenCredentials("r") as read_handle:
props_val = {}
for line in read_handle:
curr_prop, curr_value = line.split()
props_val[curr_prop] = curr_value
with open_credentials("w+") as write_handle:
with OpenCredentials("w+") as write_handle:
props_val[prop] = value
for true_prop, true_value in props_val.items():
write_handle.write(f"{true_prop} {true_value}\n")
Expand All @@ -84,15 +75,15 @@ def get_or_create_github_config() -> GithubConfig:
github_config = GithubConfig()

logger.info("Found github credentials - loading into Config")
with open_credentials("r") as cred_handle:
with OpenCredentials("r") as cred_handle:
for line in cred_handle:
prop, value = line.split()
github_config.set_prop(prop, value)

return github_config


class open_credentials(object):
class OpenCredentials:
def __init__(self, method: str):
self.file_name = GITHUB_CREDENTIALS_PATH
if not self.file_name.exists():
Expand All @@ -104,23 +95,31 @@ def __init__(self, method: str):
self.key = key_handle.read()
decrypt_file(self.key, self.file_name)

def __enter__(self):
self.file_obj = open(self.file_name, self.method)
def __enter__(self) -> IO[str]:
self.file_obj = open( # pylint: disable=attribute-defined-outside-init
self.file_name, self.method
)
if len(self.file_obj.read().split()) == 1 and not self.key_exists:
raise click.FileError(
f"MissingKey: Credentials file is currently encrypted and the key is missing, please try resetting your credentials file"
"MissingKey: Credentials file is currently encrypted and the key is missing, please try resetting your credentials file."
)
# reset file pointer
self.file_obj.seek(0)
return self.file_obj

def __exit__(self, type, value, traceback):
def __exit__(
self,
exception_type: Optional[Type[BaseException]],
exception_value: Optional[BaseException],
traceback: Optional[TracebackType],
) -> Optional[bool]:
if self.key_exists:
encrypt_file(self.key, self.file_name)
self.file_obj.close()
return True


def handle_encrypt_option(e: bool, d: bool):
def handle_encrypt_option(encrypt: bool, decrypt: bool) -> None:
"""Encryption can be True or False as specified by the user parameter:
True: we generate a key and encrypt the credentials file using Fernet Encryption
False: if the file is currently encrypted - we decrypt it and delete the key
Expand All @@ -133,7 +132,7 @@ def handle_encrypt_option(e: bool, d: bool):
key = read_handle.read()

# Encrypt the file
if e:
if encrypt:
if not key_exists:
key = Fernet.generate_key()
with open(KEY_PATH, "wb") as write_handle:
Expand All @@ -142,11 +141,10 @@ def handle_encrypt_option(e: bool, d: bool):
encrypt_file(key, GITHUB_CREDENTIALS_PATH)

# Decrypt the file
if d:
if decrypt:
if not key_exists:
raise click.BadOptionUsage(
option_name="--decrypt",
message="cannot be used when file is already decrypted",
option_name="--decrypt", message="cannot be used when file is already decrypted",
)
decrypt_file(key, GITHUB_CREDENTIALS_PATH)
KEY_PATH.unlink()
Expand All @@ -163,7 +161,7 @@ def encrypt_file(key: bytes, file: Path) -> None:
f = Fernet(key)
except (binascii.Error, ValueError):
raise click.ClickException(
f"Error: Cannot Encrypt File - given key is in incorrect format, please try resetting your credentials"
"Error: Cannot Encrypt File - given key is in incorrect format, please try resetting your credentials."
)

with open(file, "r") as read_handle:
Expand Down Expand Up @@ -191,7 +189,7 @@ def decrypt_file(key: bytes, file: Path) -> None:
f = Fernet(key)
except (binascii.Error, ValueError):
raise click.ClickException(
f"Error: Cannot Decrypt File - given key is in incorrect format, please try resetting your credentials"
"Error: Cannot Decrypt File - given key is in incorrect format, please try resetting your credentials."
)

with open(file, "rb") as read_handle:
Expand Down
Loading

0 comments on commit 16462e1

Please sign in to comment.