From 6cdd6b887de1a4ad8caab28b605d5d0cb250f58b Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Thu, 22 Dec 2022 21:31:43 -0500 Subject: [PATCH 01/39] remove circleci --- .circleci/config.yml | 127 ------------------------------------------- 1 file changed, 127 deletions(-) delete mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index bb49d8c..0000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,127 +0,0 @@ -version: 2.1 - -executors: - - python: - - parameters: - tag: - description: circleci/python docker tag - type: string - - docker: - - image: circleci/python:<< parameters.tag >> - -commands: - - dependencies: - - steps: - - run: - name: Install Dependencies - command: | - python -m venv .venv - source .venv/bin/activate - python -m pip install --upgrade pip setuptools - pip install poetry - poetry config settings.virtualenvs.in-project true - poetry install - -jobs: - - test: - - parameters: - tag: - description: circleci/python docker tag - type: string - - executor: - name: python - tag: << parameters.tag >> - - steps: - - checkout - - - dependencies - - - run: - name: Pytest - command: | - source .venv/bin/activate - poetry run coverage run -m pytest --junit-xml=test-results/pytest/results.xml - - - run: - name: Codecov - command: | - source .venv/bin/activate - poetry run codecov - - - store_test_results: - path: test-results - - - store_artifacts: - path: test-results - destination: test-results - - lint: - - executor: - name: python - tag: 3.7.1 - - steps: - - checkout - - - dependencies - - - run: - name: Mypy - command: | - source .venv/bin/activate - poetry run mypy --ignore-missing-imports --strict --allow-untyped-decorators hb - poetry run mypy --ignore-missing-imports --strict --allow-untyped-decorators tests - - - run: - name: Pylint - # C0111: missing-docstring - # C0301: line-too-long - # C0321: multiple-statements - command: | - source .venv/bin/activate - poetry run pylint -d C0301 hb - poetry run pylint -d C0111,C0301,C0321 tests - -workflows: - - version: 2 - - commit: - - jobs: - - test: - name: python 3.7 - tag: 3.7.1 - - test: - name: python 3.6 - tag: 3.6.7 - - lint - - weekly: - - jobs: - - test: - name: python 3.7 - tag: 3.7.1 - - test: - name: python 3.6 - tag: 3.6.7 - - lint - - triggers: - - schedule: - cron: "1 0 * * 1" - filters: - branches: - only: - - master From 834cb0fd95652b3a6a4d9077fe338c276799b800 Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Thu, 22 Dec 2022 21:32:41 -0500 Subject: [PATCH 02/39] add github actions --- .github/workflows/test.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..0079106 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,31 @@ +name: Test + +on: + pull_request: + push: + branches: + - main + +jobs: + test: + strategy: + fail-fast: false + matrix: + os: [macos-latest, ubuntu-latest, windows-latest] + python-version: ["3.11"] + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v3 + + - run: pipx install poetry + + - uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + cache: "poetry" + + - run: poetry install + + - run: poetry run pytest From 93de6cfa5a6dd1bfb066e61e609486b40f336966 Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Thu, 22 Dec 2022 21:33:17 -0500 Subject: [PATCH 03/39] remove cli interface --- hb/cli.py | 80 ------------------------------------------------------- 1 file changed, 80 deletions(-) delete mode 100644 hb/cli.py diff --git a/hb/cli.py b/hb/cli.py deleted file mode 100644 index 6e6a896..0000000 --- a/hb/cli.py +++ /dev/null @@ -1,80 +0,0 @@ -"""Hash Brown CLI""" - -from concurrent.futures import ProcessPoolExecutor -from glob import iglob -from pathlib import Path -from time import time -from typing import Any, Tuple - -import click - -from hb.main import Checksum - - -def _shorten(error: Exception) -> str: - msg = str(error) - return msg.partition("] ")[-1] if "] " in msg else msg - -def _compute(algorithm: str, path: str, given: str) -> Tuple[int, str]: - try: - actual = Checksum(path).get(algorithm) - except OSError as error: - return (2, f"{click.style(_shorten(error), fg='yellow')}") - else: - if given: - if actual == given: - return (0, f"{Checksum.print(algorithm, path, given)} {click.style('OK', fg='green')}") - return (1, f"{Checksum.print(algorithm, path, given)} {click.style(f'BAD', fg='red')}") - return (0, Checksum.print(algorithm, path, actual)) - -def _algorithm_mode(algorithm: str, path: str, given: str, parallel: bool) -> None: - computed = 0 - with ProcessPoolExecutor(max_workers=None if parallel else 1) as executor: - for filename in iglob(path, recursive=True): - if not Path(filename).is_file(): - continue - future = executor.submit(_compute, algorithm, filename, given) - future.add_done_callback(lambda f: click.echo(f.result()[1])) - computed += 1 - if not computed: - click.echo(f"No files matched the pattern: '{path}'") - -def _check_mode(path: str, quiet: bool, parallel: bool) -> None: - def _cb(code: int, result: str) -> None: - if not quiet: - click.echo(result) - elif code: - click.echo(result) - with ProcessPoolExecutor(max_workers=None if parallel else 1) as executor: - for algorithm, filename, given in Checksum.parse(path): - future = executor.submit(_compute, algorithm, filename, given) - future.add_done_callback(lambda f: _cb(f.result()[0], f.result()[1])) - - -@click.version_option(version=Checksum.VERSION) -@click.command(context_settings={"help_option_names": ["-h", "--help"]}) -@click.option("-a", "--algorithm", type=click.Choice(Checksum.SUPPORTED)) -@click.option("-c", "--check", is_flag=True, help="Read checksums from a file.") -@click.option("-g", "--given", help="See if the given checksum `TEXT` matches the computed checksum. (use with -a)") -@click.option("-p", "--parallel", is_flag=True, default=False, help="Process files in parallel.") -@click.option("-q", "--quiet", is_flag=True, default=False, help="Hide results that are OK. (use with -c)") -@click.option("-t", "--timer", is_flag=True, help="Display elapsed time in seconds.") -@click.argument("path") -def cli(**kwargs: Any) -> None: - """Hash Brown: Compute and verify checksums.""" - start_time = time() - try: - if kwargs["algorithm"]: - _algorithm_mode(**{k: v for k, v in kwargs.items() if k in ["algorithm", "path", "given", "parallel"]}) - elif kwargs["check"]: - _check_mode(**{k: v for k, v in kwargs.items() if k in ["path", "quiet", "parallel"]}) - else: - pass - except (OSError, ValueError) as error: - click.echo(_shorten(error)) - if kwargs["timer"]: - click.echo(f"# {time() - start_time:.3f}s") - - -if __name__ == "__main__": - cli() From d688dac5c33622b2d6d4978004372650f70ec373 Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Thu, 22 Dec 2022 21:35:11 -0500 Subject: [PATCH 04/39] __init__.py --- hb/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 hb/__init__.py diff --git a/hb/__init__.py b/hb/__init__.py new file mode 100644 index 0000000..e69de29 From fa89c975970192abddeee351102afbb8d44506d7 Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Thu, 22 Dec 2022 21:35:47 -0500 Subject: [PATCH 05/39] refactored for clarity, simplicity, and python 3.11 --- hb/hb.py | 88 +++++++++++++++++++++++++++++ hb/main.py | 158 ----------------------------------------------------- 2 files changed, 88 insertions(+), 158 deletions(-) create mode 100644 hb/hb.py delete mode 100644 hb/main.py diff --git a/hb/hb.py b/hb/hb.py new file mode 100644 index 0000000..0e79689 --- /dev/null +++ b/hb/hb.py @@ -0,0 +1,88 @@ +"""Hash Brown""" + +from contextlib import contextmanager +from pathlib import Path +from threading import Thread +from typing import Generator +import hashlib +import os +import re +import sys +import time +import zlib + + +class HashBrown(): + def __init__(self, algo, path) -> None: + self.algo = algo.lower() + self.filesize = os.path.getsize(path) + self.hexdigest = None + self.path = Path(path) + self.tell = 0 + + @contextmanager + def open(self) -> Generator: + """File open with progress tracker.""" + def _progress() -> None: + while self.tell != self.filesize: + print("{:.3%} {} {}".format(self.tell / self.filesize, self.algo, self.path), end="\r", file=sys.stderr) + time.sleep(0.5) + + Thread(target=_progress).start() + with open(self.path, "rb") as lines: + yield lines + + def compute(self) -> str: + """Compute the hexdigest.""" + if self.hexdigest: + return self.hexdigest + + match self.algo: + case "adler32": + result = 1 + with self.open() as lines: + for line in lines: + result = zlib.adler32(line, result) + self.tell = lines.tell() + self.hexdigest = hex(result).removeprefix('0x').zfill(8) + case "crc32": + result = 0 + with self.open() as lines: + for line in lines: + result = zlib.crc32(line, result) + self.tell = lines.tell() + self.hexdigest = hex(result).removeprefix('0x').zfill(8) + case _: + result = hashlib.new(self.algo) + with self.open() as lines: + for line in lines: + result.update(line) + self.tell = lines.tell() + self.hexdigest = result.hexdigest() + + self.tell = self.filesize + return self.hexdigest + + def pprint(self) -> str: + """Pretty print the hexdigest.""" + return f"{self.compute()} {self.algo} {self.path}" + + +def compute(algo: str, path: str) -> str: + """Convenience function to compute and pprint.""" + return HashBrown(algo, path).pprint() + + +def scan(path: str) -> None: + """Scan a file of hexdigests to check if they match.""" + with open(Path(path)) as lines: + for i, line in enumerate(lines, start=1): + line = line.strip() + if not line or line.startswith("#"): # skip blank lines and comments + continue + if match := re.match(r"^([0-9A-Fa-f]+) (\w+) (.+)$", line): + given_hexdigest, algo, path = match.group(1, 2, 3) + computed_hexdigest = HashBrown(algo, path).compute() + print(f"{'OK' if computed_hexdigest == given_hexdigest else 'BAD'} {algo} {path}") + else: + print(f"\nUnable to read line {i}: '{line}'\n") diff --git a/hb/main.py b/hb/main.py deleted file mode 100644 index ec37e2b..0000000 --- a/hb/main.py +++ /dev/null @@ -1,158 +0,0 @@ -"""Hash Brown""" - -from contextlib import contextmanager -from pathlib import Path -from sys import stderr -from threading import Thread -from time import sleep -from typing import Dict, Generator, IO, List, Tuple -import hashlib -import re -import zlib - - -class Checksum(): - """Compute various checksums. - - Digest, hash, and checksum are all referred to as checksum for simplicity. - """ - SUPPORTED = ("blake2b", "blake2s", "md5", "sha1", "sha224", "sha256", "sha384", "sha512", "adler32", "crc32") - VERSION = "1.4.2" - - @staticmethod - def parse(path: str) -> List[Tuple[str, ...]]: - """Parse lines from a checksum file.""" - parsed_lines = [] - with Path(path).open("r") as lines: - for line in lines: - line = line.strip() - if not line or line[0] == "#": # skip blank lines and comments - continue - match = re.match(r"(\w+) \((.+)\) = (\w+)", line) - if not match: - raise ValueError(f"Bad line in checksum file: '{line}'") - parsed_lines.append(tuple(match.group(1, 2, 3))) - return parsed_lines - - @staticmethod - def print(algorithm: str, path: str, checksum: str) -> str: - """BSD style checksum output.""" - return f"{algorithm} ({Path(path)}) = {checksum}" - - def __init__(self, path: str, threshold: int = 200) -> None: - self._path = Path(path) - self.checksums: Dict[str, str] = {} - self.filesize = self._path.stat().st_size - self.threshold = threshold - - @contextmanager - def _progress_open(self) -> Generator: - def _p(file: IO) -> None: - while not file.closed: - print(f"{int(file.tell() / self.filesize * 100)}%", end="\r", file=stderr) - sleep(0.2) - print(" ", end="\r", file=stderr) # clear the progress display - with open(self._path, "rb") as lines: - thread = Thread(target=_p, args=(lines,)) - if self.filesize > self.threshold * 1024 * 1024: - thread.start() - yield lines - if thread.is_alive(): - thread.join() - - def _hashlib_compute(self, name: str) -> str: - result = hashlib.new(name) - with self._progress_open() as lines: - for line in lines: - result.update(line) - return result.hexdigest() - - def _zlib_compute(self, name: str) -> str: - if name == "adler32": - result = 1 - update = zlib.adler32 - elif name == "crc32": - result = 0 - update = zlib.crc32 - with self._progress_open() as lines: - for line in lines: - result = update(line, result) - return hex(result)[2:].zfill(8) - - def compute(self, algorithm: str) -> str: - """Compute a checksum.""" - if algorithm not in Checksum.SUPPORTED: - raise ValueError(f"Unsupported algorithm: '{algorithm}'") - elif algorithm in ["adler32", "crc32"]: - result = self._zlib_compute(algorithm) - else: - result = self._hashlib_compute(algorithm) - self.checksums[algorithm] = result - return result - - def get(self, algorithm: str) -> str: - """Same as `compute` but does not recalculate the checksum if it is already known.""" - if algorithm in self.checksums: - return self.checksums[algorithm] - return self.compute(algorithm) - - @property - def path(self) -> str: - """The path to calculate.""" - return str(self._path) - - @path.setter - def path(self, path: str) -> None: - """Set new path and clear the checksums dictionary.""" - self._path = Path(path) - self.checksums = {} - - @property - def blake2b(self) -> str: - """blake2b""" - return self.get("blake2b") - - @property - def blake2s(self) -> str: - """blake2s""" - return self.get("blake2s") - - @property - def md5(self) -> str: - """md5""" - return self.get("md5") - - @property - def sha1(self) -> str: - """sha1""" - return self.get("sha1") - - @property - def sha224(self) -> str: - """sha224""" - return self.get("sha224") - - @property - def sha256(self) -> str: - """sha256""" - return self.get("sha256") - - @property - def sha384(self) -> str: - """sha384""" - return self.get("sha384") - - @property - def sha512(self) -> str: - """sha512""" - return self.get("sha512") - - @property - def adler32(self) -> str: - """adler32""" - return self.get("adler32") - - @property - def crc32(self) -> str: - """crc32""" - return self.get("crc32") From 022a5ff5a8f3f0cf1c2878a3d4888bf3c1541062 Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Thu, 22 Dec 2022 21:36:21 -0500 Subject: [PATCH 06/39] update year --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 1121d41..58b0a5b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018 Ching Chow +Copyright (c) 2023 Ching Chow Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 39305fd3167e918e4bd47431c6d58cea072726ca Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Thu, 22 Dec 2022 21:38:11 -0500 Subject: [PATCH 07/39] simplify .gitignore --- .gitignore | 111 ++--------------------------------------------------- 1 file changed, 3 insertions(+), 108 deletions(-) diff --git a/.gitignore b/.gitignore index 3742d11..a2eeca3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,108 +1,3 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -.hypothesis/ -.pytest_cache/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -.static_storage/ -.media/ -local_settings.py - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# pyenv -.python-version - -# celery beat schedule file -celerybeat-schedule - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ - -# vscode -.vscode +__pycache__ +.mypy_cache +.pytest_cache From a915905a902ccd1251b87b18980ca68b32561426 Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Thu, 22 Dec 2022 21:41:59 -0500 Subject: [PATCH 08/39] update for python 3.11 and refactor --- pyproject.toml | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9736cc7..6c6da36 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,10 @@ [tool.poetry] name = "hb" -version = "1.4.2" -description = "A simple command-line utility for calculating checksums." -license = "MIT" -authors = ["Ching Chow "] +version = "2.0.0" +description = "A simple utility for calculating hashes and checksums." +authors = ["Ching Chow "] readme = "README.md" +license = "MIT" homepage = "https://github.com/chingc/Hash-Brown" repository = "https://github.com/chingc/Hash-Brown" documentation = "https://github.com/chingc/Hash-Brown" @@ -26,17 +26,18 @@ classifiers = [ "Topic :: Utilities" ] -[tool.poetry.scripts] -hb = "hb.cli:cli" [tool.poetry.dependencies] -python = "^3.6" -click = "^7.0" -colorama = "^0.4.0" +python = "^3.11" + + +[tool.poetry.group.test.dependencies] +flake8 = "^6.0.0" +mypy = "^0.991" +pylint = "^2.15.9" +pytest = "^7.2.0" + -[tool.poetry.dev-dependencies] -codecov = "^2.0" -mypy = "^0.620.0" -pylint = "^2.0" -pytest = "^3.0" -rope = "^0.10.7" +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" From 9e72489ec805af2a9ad2a59fea79008d0a50f2d8 Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Thu, 22 Dec 2022 21:47:04 -0500 Subject: [PATCH 09/39] update poetry.lock --- poetry.lock | 508 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 334 insertions(+), 174 deletions(-) diff --git a/poetry.lock b/poetry.lock index 8cd042e..16f66bf 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,271 +1,431 @@ +# This file is automatically @generated by Poetry and should not be changed by hand. + [[package]] -category = "dev" -description = "An abstract syntax tree for Python with inference support." name = "astroid" +version = "2.12.13" +description = "An abstract syntax tree for Python with inference support." +category = "dev" optional = false -python-versions = ">=3.4.*" -version = "2.0.4" +python-versions = ">=3.7.2" +files = [ + {file = "astroid-2.12.13-py3-none-any.whl", hash = "sha256:10e0ad5f7b79c435179d0d0f0df69998c4eef4597534aae44910db060baeb907"}, + {file = "astroid-2.12.13.tar.gz", hash = "sha256:1493fe8bd3dfd73dc35bd53c9d5b6e49ead98497c47b2307662556a5692d29d7"}, +] [package.dependencies] -lazy-object-proxy = "*" -six = "*" -wrapt = "*" - -[package.dependencies.typed-ast] -python = "<3.7" -version = "*" +lazy-object-proxy = ">=1.4.0" +wrapt = {version = ">=1.14,<2", markers = "python_version >= \"3.11\""} [[package]] +name = "attrs" +version = "22.2.0" +description = "Classes Without Boilerplate" category = "dev" -description = "Atomic file writes." -name = "atomicwrites" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.2.1" +python-versions = ">=3.6" +files = [ + {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, + {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, +] + +[package.extras] +cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] +dev = ["attrs[docs,tests]"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"] +tests = ["attrs[tests-no-zope]", "zope.interface"] +tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"] [[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." category = "dev" -description = "Classes Without Boilerplate" -name = "attrs" optional = false -python-versions = "*" -version = "18.2.0" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] [[package]] +name = "dill" +version = "0.3.6" +description = "serialize all of python" category = "dev" -description = "Python package for providing Mozilla's CA Bundle." -name = "certifi" optional = false -python-versions = "*" -version = "2018.10.15" +python-versions = ">=3.7" +files = [ + {file = "dill-0.3.6-py3-none-any.whl", hash = "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0"}, + {file = "dill-0.3.6.tar.gz", hash = "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373"}, +] + +[package.extras] +graph = ["objgraph (>=1.7.2)"] [[package]] +name = "flake8" +version = "6.0.0" +description = "the modular source code checker: pep8 pyflakes and co" category = "dev" -description = "Universal encoding detector for Python 2 and 3" -name = "chardet" optional = false -python-versions = "*" -version = "3.0.4" +python-versions = ">=3.8.1" +files = [ + {file = "flake8-6.0.0-py2.py3-none-any.whl", hash = "sha256:3833794e27ff64ea4e9cf5d410082a8b97ff1a06c16aa3d2027339cd0f1195c7"}, + {file = "flake8-6.0.0.tar.gz", hash = "sha256:c61007e76655af75e6785a931f452915b371dc48f56efd765247c8fe68f2b181"}, +] -[[package]] -category = "main" -description = "Composable command line interface toolkit" -name = "click" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "7.0" +[package.dependencies] +mccabe = ">=0.7.0,<0.8.0" +pycodestyle = ">=2.10.0,<2.11.0" +pyflakes = ">=3.0.0,<3.1.0" [[package]] +name = "iniconfig" +version = "1.1.1" +description = "iniconfig: brain-dead simple config-ini parsing" category = "dev" -description = "Hosted coverage reports for Github, Bitbucket and Gitlab" -name = "codecov" optional = false python-versions = "*" -version = "2.0.15" - -[package.dependencies] -coverage = "*" -requests = ">=2.7.9" +files = [ + {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, + {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, +] [[package]] -category = "main" -description = "Cross-platform colored terminal text." -name = "colorama" +name = "isort" +version = "5.11.4" +description = "A Python utility / library to sort Python imports." +category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "0.4.0" +python-versions = ">=3.7.0" +files = [ + {file = "isort-5.11.4-py3-none-any.whl", hash = "sha256:c033fd0edb91000a7f09527fe5c75321878f98322a77ddcc81adbd83724afb7b"}, + {file = "isort-5.11.4.tar.gz", hash = "sha256:6db30c5ded9815d813932c04c2f85a360bcdd35fed496f4d8f35495ef0a261b6"}, +] + +[package.extras] +colors = ["colorama (>=0.4.3,<0.5.0)"] +pipfile-deprecated-finder = ["pipreqs", "requirementslib"] +plugins = ["setuptools"] +requirements-deprecated-finder = ["pip-api", "pipreqs"] [[package]] +name = "lazy-object-proxy" +version = "1.8.0" +description = "A fast and thorough lazy object proxy." category = "dev" -description = "Code coverage measurement for Python" -name = "coverage" optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, <4" -version = "4.5.1" +python-versions = ">=3.7" +files = [ + {file = "lazy-object-proxy-1.8.0.tar.gz", hash = "sha256:c219a00245af0f6fa4e95901ed28044544f50152840c5b6a3e7b2568db34d156"}, + {file = "lazy_object_proxy-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4fd031589121ad46e293629b39604031d354043bb5cdf83da4e93c2d7f3389fe"}, + {file = "lazy_object_proxy-1.8.0-cp310-cp310-win32.whl", hash = "sha256:b70d6e7a332eb0217e7872a73926ad4fdc14f846e85ad6749ad111084e76df25"}, + {file = "lazy_object_proxy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:eb329f8d8145379bf5dbe722182410fe8863d186e51bf034d2075eb8d85ee25b"}, + {file = "lazy_object_proxy-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4e2d9f764f1befd8bdc97673261b8bb888764dfdbd7a4d8f55e4fbcabb8c3fb7"}, + {file = "lazy_object_proxy-1.8.0-cp311-cp311-win32.whl", hash = "sha256:e20bfa6db17a39c706d24f82df8352488d2943a3b7ce7d4c22579cb89ca8896e"}, + {file = "lazy_object_proxy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:14010b49a2f56ec4943b6cf925f597b534ee2fe1f0738c84b3bce0c1a11ff10d"}, + {file = "lazy_object_proxy-1.8.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6850e4aeca6d0df35bb06e05c8b934ff7c533734eb51d0ceb2d63696f1e6030c"}, + {file = "lazy_object_proxy-1.8.0-cp37-cp37m-win32.whl", hash = "sha256:5b51d6f3bfeb289dfd4e95de2ecd464cd51982fe6f00e2be1d0bf94864d58acd"}, + {file = "lazy_object_proxy-1.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:6f593f26c470a379cf7f5bc6db6b5f1722353e7bf937b8d0d0b3fba911998858"}, + {file = "lazy_object_proxy-1.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c1c7c0433154bb7c54185714c6929acc0ba04ee1b167314a779b9025517eada"}, + {file = "lazy_object_proxy-1.8.0-cp38-cp38-win32.whl", hash = "sha256:d176f392dbbdaacccf15919c77f526edf11a34aece58b55ab58539807b85436f"}, + {file = "lazy_object_proxy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:afcaa24e48bb23b3be31e329deb3f1858f1f1df86aea3d70cb5c8578bfe5261c"}, + {file = "lazy_object_proxy-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:71d9ae8a82203511a6f60ca5a1b9f8ad201cac0fc75038b2dc5fa519589c9288"}, + {file = "lazy_object_proxy-1.8.0-cp39-cp39-win32.whl", hash = "sha256:8f6ce2118a90efa7f62dd38c7dbfffd42f468b180287b748626293bf12ed468f"}, + {file = "lazy_object_proxy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:eac3a9a5ef13b332c059772fd40b4b1c3d45a3a2b05e33a361dee48e54a4dad0"}, + {file = "lazy_object_proxy-1.8.0-pp37-pypy37_pp73-any.whl", hash = "sha256:ae032743794fba4d171b5b67310d69176287b5bf82a21f588282406a79498891"}, + {file = "lazy_object_proxy-1.8.0-pp38-pypy38_pp73-any.whl", hash = "sha256:7e1561626c49cb394268edd00501b289053a652ed762c58e1081224c8d881cec"}, + {file = "lazy_object_proxy-1.8.0-pp39-pypy39_pp73-any.whl", hash = "sha256:ce58b2b3734c73e68f0e30e4e725264d4d6be95818ec0a0be4bb6bf9a7e79aa8"}, +] [[package]] +name = "mccabe" +version = "0.7.0" +description = "McCabe checker, plugin for flake8" category = "dev" -description = "Internationalized Domain Names in Applications (IDNA)" -name = "idna" optional = false -python-versions = "*" -version = "2.7" +python-versions = ">=3.6" +files = [ + {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, + {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, +] [[package]] +name = "mypy" +version = "0.991" +description = "Optional static typing for Python" category = "dev" -description = "A Python utility / library to sort Python imports." -name = "isort" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "4.3.4" +python-versions = ">=3.7" +files = [ + {file = "mypy-0.991-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7d17e0a9707d0772f4a7b878f04b4fd11f6f5bcb9b3813975a9b13c9332153ab"}, + {file = "mypy-0.991-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0714258640194d75677e86c786e80ccf294972cc76885d3ebbb560f11db0003d"}, + {file = "mypy-0.991-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0c8f3be99e8a8bd403caa8c03be619544bc2c77a7093685dcf308c6b109426c6"}, + {file = "mypy-0.991-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc9ec663ed6c8f15f4ae9d3c04c989b744436c16d26580eaa760ae9dd5d662eb"}, + {file = "mypy-0.991-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4307270436fd7694b41f913eb09210faff27ea4979ecbcd849e57d2da2f65305"}, + {file = "mypy-0.991-cp310-cp310-win_amd64.whl", hash = "sha256:901c2c269c616e6cb0998b33d4adbb4a6af0ac4ce5cd078afd7bc95830e62c1c"}, + {file = "mypy-0.991-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d13674f3fb73805ba0c45eb6c0c3053d218aa1f7abead6e446d474529aafc372"}, + {file = "mypy-0.991-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1c8cd4fb70e8584ca1ed5805cbc7c017a3d1a29fb450621089ffed3e99d1857f"}, + {file = "mypy-0.991-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:209ee89fbb0deed518605edddd234af80506aec932ad28d73c08f1400ef80a33"}, + {file = "mypy-0.991-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37bd02ebf9d10e05b00d71302d2c2e6ca333e6c2a8584a98c00e038db8121f05"}, + {file = "mypy-0.991-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:26efb2fcc6b67e4d5a55561f39176821d2adf88f2745ddc72751b7890f3194ad"}, + {file = "mypy-0.991-cp311-cp311-win_amd64.whl", hash = "sha256:3a700330b567114b673cf8ee7388e949f843b356a73b5ab22dd7cff4742a5297"}, + {file = "mypy-0.991-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:1f7d1a520373e2272b10796c3ff721ea1a0712288cafaa95931e66aa15798813"}, + {file = "mypy-0.991-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:641411733b127c3e0dab94c45af15fea99e4468f99ac88b39efb1ad677da5711"}, + {file = "mypy-0.991-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3d80e36b7d7a9259b740be6d8d906221789b0d836201af4234093cae89ced0cd"}, + {file = "mypy-0.991-cp37-cp37m-win_amd64.whl", hash = "sha256:e62ebaad93be3ad1a828a11e90f0e76f15449371ffeecca4a0a0b9adc99abcef"}, + {file = "mypy-0.991-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b86ce2c1866a748c0f6faca5232059f881cda6dda2a893b9a8373353cfe3715a"}, + {file = "mypy-0.991-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ac6e503823143464538efda0e8e356d871557ef60ccd38f8824a4257acc18d93"}, + {file = "mypy-0.991-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0cca5adf694af539aeaa6ac633a7afe9bbd760df9d31be55ab780b77ab5ae8bf"}, + {file = "mypy-0.991-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a12c56bf73cdab116df96e4ff39610b92a348cc99a1307e1da3c3768bbb5b135"}, + {file = "mypy-0.991-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:652b651d42f155033a1967739788c436491b577b6a44e4c39fb340d0ee7f0d70"}, + {file = "mypy-0.991-cp38-cp38-win_amd64.whl", hash = "sha256:4175593dc25d9da12f7de8de873a33f9b2b8bdb4e827a7cae952e5b1a342e243"}, + {file = "mypy-0.991-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:98e781cd35c0acf33eb0295e8b9c55cdbef64fcb35f6d3aa2186f289bed6e80d"}, + {file = "mypy-0.991-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6d7464bac72a85cb3491c7e92b5b62f3dcccb8af26826257760a552a5e244aa5"}, + {file = "mypy-0.991-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c9166b3f81a10cdf9b49f2d594b21b31adadb3d5e9db9b834866c3258b695be3"}, + {file = "mypy-0.991-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8472f736a5bfb159a5e36740847808f6f5b659960115ff29c7cecec1741c648"}, + {file = "mypy-0.991-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e80e758243b97b618cdf22004beb09e8a2de1af481382e4d84bc52152d1c476"}, + {file = "mypy-0.991-cp39-cp39-win_amd64.whl", hash = "sha256:74e259b5c19f70d35fcc1ad3d56499065c601dfe94ff67ae48b85596b9ec1461"}, + {file = "mypy-0.991-py3-none-any.whl", hash = "sha256:de32edc9b0a7e67c2775e574cb061a537660e51210fbf6006b0b36ea695ae9bb"}, + {file = "mypy-0.991.tar.gz", hash = "sha256:3c0165ba8f354a6d9881809ef29f1a9318a236a6d81c690094c5df32107bde06"}, +] + +[package.dependencies] +mypy-extensions = ">=0.4.3" +typing-extensions = ">=3.10" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +install-types = ["pip"] +python2 = ["typed-ast (>=1.4.0,<2)"] +reports = ["lxml"] [[package]] +name = "mypy-extensions" +version = "0.4.3" +description = "Experimental type system extensions for programs checked with the mypy typechecker." category = "dev" -description = "A fast and thorough lazy object proxy." -name = "lazy-object-proxy" optional = false python-versions = "*" -version = "1.3.1" +files = [ + {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, + {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, +] [[package]] +name = "packaging" +version = "22.0" +description = "Core utilities for Python packages" category = "dev" -description = "McCabe checker, plugin for flake8" -name = "mccabe" optional = false -python-versions = "*" -version = "0.6.1" +python-versions = ">=3.7" +files = [ + {file = "packaging-22.0-py3-none-any.whl", hash = "sha256:957e2148ba0e1a3b282772e791ef1d8083648bc131c8ab0c1feba110ce1146c3"}, + {file = "packaging-22.0.tar.gz", hash = "sha256:2198ec20bd4c017b8f9717e00f0c8714076fc2fd93816750ab48e2c41de2cfd3"}, +] [[package]] +name = "platformdirs" +version = "2.6.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" -description = "More routines for operating on iterables, beyond itertools" -name = "more-itertools" optional = false -python-versions = "*" -version = "4.3.0" +python-versions = ">=3.7" +files = [ + {file = "platformdirs-2.6.0-py3-none-any.whl", hash = "sha256:1a89a12377800c81983db6be069ec068eee989748799b946cce2a6e80dcc54ca"}, + {file = "platformdirs-2.6.0.tar.gz", hash = "sha256:b46ffafa316e6b83b47489d240ce17173f123a9b9c83282141c3daf26ad9ac2e"}, +] -[package.dependencies] -six = ">=1.0.0,<2.0.0" +[package.extras] +docs = ["furo (>=2022.9.29)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.4)"] +test = ["appdirs (==1.4.4)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] [[package]] +name = "pluggy" +version = "1.0.0" +description = "plugin and hook calling mechanisms for python" category = "dev" -description = "Optional static typing for Python" -name = "mypy" optional = false -python-versions = "*" -version = "0.620" +python-versions = ">=3.6" +files = [ + {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, + {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, +] -[package.dependencies] -typed-ast = ">=1.1.0,<1.2.0" +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] [[package]] +name = "pycodestyle" +version = "2.10.0" +description = "Python style guide checker" category = "dev" -description = "plugin and hook calling mechanisms for python" -name = "pluggy" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "0.8.0" +python-versions = ">=3.6" +files = [ + {file = "pycodestyle-2.10.0-py2.py3-none-any.whl", hash = "sha256:8a4eaf0d0495c7395bdab3589ac2db602797d76207242c17d470186815706610"}, + {file = "pycodestyle-2.10.0.tar.gz", hash = "sha256:347187bdb476329d98f695c213d7295a846d1152ff4fe9bacb8a9590b8ee7053"}, +] [[package]] +name = "pyflakes" +version = "3.0.1" +description = "passive checker of Python programs" category = "dev" -description = "library with cross-python path, ini-parsing, io, code, log facilities" -name = "py" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.7.0" +python-versions = ">=3.6" +files = [ + {file = "pyflakes-3.0.1-py2.py3-none-any.whl", hash = "sha256:ec55bf7fe21fff7f1ad2f7da62363d749e2a470500eab1b555334b67aa1ef8cf"}, + {file = "pyflakes-3.0.1.tar.gz", hash = "sha256:ec8b276a6b60bd80defed25add7e439881c19e64850afd9b346283d4165fd0fd"}, +] [[package]] -category = "dev" -description = "python code static checker" name = "pylint" -optional = false -python-versions = ">=3.4.*" -version = "2.1.1" - -[package.dependencies] -astroid = ">=2.0.0" -colorama = "*" -isort = ">=4.2.5" -mccabe = "*" - -[[package]] +version = "2.15.9" +description = "python code static checker" category = "dev" -description = "pytest: simple powerful testing with Python" -name = "pytest" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "3.9.3" +python-versions = ">=3.7.2" +files = [ + {file = "pylint-2.15.9-py3-none-any.whl", hash = "sha256:349c8cd36aede4d50a0754a8c0218b43323d13d5d88f4b2952ddfe3e169681eb"}, + {file = "pylint-2.15.9.tar.gz", hash = "sha256:18783cca3cfee5b83c6c5d10b3cdb66c6594520ffae61890858fe8d932e1c6b4"}, +] [package.dependencies] -atomicwrites = ">=1.0" -attrs = ">=17.4.0" -colorama = "*" -more-itertools = ">=4.0.0" -pluggy = ">=0.7" -py = ">=1.5.0" -setuptools = "*" -six = ">=1.10.0" +astroid = ">=2.12.13,<=2.14.0-dev0" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +dill = {version = ">=0.3.6", markers = "python_version >= \"3.11\""} +isort = ">=4.2.5,<6" +mccabe = ">=0.6,<0.8" +platformdirs = ">=2.2.0" +tomlkit = ">=0.10.1" + +[package.extras] +spelling = ["pyenchant (>=3.2,<4.0)"] +testutils = ["gitpython (>3)"] [[package]] +name = "pytest" +version = "7.2.0" +description = "pytest: simple powerful testing with Python" category = "dev" -description = "Python HTTP for Humans." -name = "requests" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.20.0" +python-versions = ">=3.7" +files = [ + {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"}, + {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"}, +] [package.dependencies] -certifi = ">=2017.4.17" -chardet = ">=3.0.2,<3.1.0" -idna = ">=2.5,<2.8" -urllib3 = ">=1.21.1,<1.25" - -[[package]] -category = "dev" -description = "a python refactoring library..." -name = "rope" -optional = false -python-versions = "*" -version = "0.10.7" +attrs = ">=19.2.0" +colorama = {version = "*", markers = "sys_platform == \"win32\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" -[[package]] -category = "dev" -description = "Python 2 and 3 compatibility utilities" -name = "six" -optional = false -python-versions = "*" -version = "1.11.0" +[package.extras] +testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] [[package]] +name = "tomlkit" +version = "0.11.6" +description = "Style preserving TOML library" category = "dev" -description = "a fork of Python 2 and 3 ast modules with type comment support" -name = "typed-ast" optional = false -python-versions = "*" -version = "1.1.0" +python-versions = ">=3.6" +files = [ + {file = "tomlkit-0.11.6-py3-none-any.whl", hash = "sha256:07de26b0d8cfc18f871aec595fda24d95b08fef89d147caa861939f37230bf4b"}, + {file = "tomlkit-0.11.6.tar.gz", hash = "sha256:71b952e5721688937fb02cf9d354dbcf0785066149d2855e44531ebdd2b65d73"}, +] [[package]] +name = "typing-extensions" +version = "4.4.0" +description = "Backported and Experimental Type Hints for Python 3.7+" category = "dev" -description = "HTTP library with thread-safe connection pooling, file post, and more." -name = "urllib3" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4" -version = "1.24.1" +python-versions = ">=3.7" +files = [ + {file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"}, + {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, +] [[package]] -category = "dev" -description = "Module for decorators, wrappers and monkey patching." name = "wrapt" +version = "1.14.1" +description = "Module for decorators, wrappers and monkey patching." +category = "dev" optional = false -python-versions = "*" -version = "1.10.11" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +files = [ + {file = "wrapt-1.14.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3"}, + {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef"}, + {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28"}, + {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59"}, + {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87"}, + {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1"}, + {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b"}, + {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462"}, + {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1"}, + {file = "wrapt-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320"}, + {file = "wrapt-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2"}, + {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4"}, + {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069"}, + {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310"}, + {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f"}, + {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656"}, + {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c"}, + {file = "wrapt-1.14.1-cp310-cp310-win32.whl", hash = "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8"}, + {file = "wrapt-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164"}, + {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907"}, + {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3"}, + {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3"}, + {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d"}, + {file = "wrapt-1.14.1-cp35-cp35m-win32.whl", hash = "sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7"}, + {file = "wrapt-1.14.1-cp35-cp35m-win_amd64.whl", hash = "sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00"}, + {file = "wrapt-1.14.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4"}, + {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1"}, + {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1"}, + {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff"}, + {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d"}, + {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1"}, + {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569"}, + {file = "wrapt-1.14.1-cp36-cp36m-win32.whl", hash = "sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed"}, + {file = "wrapt-1.14.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471"}, + {file = "wrapt-1.14.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248"}, + {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68"}, + {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d"}, + {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77"}, + {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7"}, + {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015"}, + {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a"}, + {file = "wrapt-1.14.1-cp37-cp37m-win32.whl", hash = "sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853"}, + {file = "wrapt-1.14.1-cp37-cp37m-win_amd64.whl", hash = "sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c"}, + {file = "wrapt-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456"}, + {file = "wrapt-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f"}, + {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc"}, + {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1"}, + {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af"}, + {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b"}, + {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0"}, + {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57"}, + {file = "wrapt-1.14.1-cp38-cp38-win32.whl", hash = "sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5"}, + {file = "wrapt-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d"}, + {file = "wrapt-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383"}, + {file = "wrapt-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7"}, + {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86"}, + {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735"}, + {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b"}, + {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3"}, + {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3"}, + {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe"}, + {file = "wrapt-1.14.1-cp39-cp39-win32.whl", hash = "sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5"}, + {file = "wrapt-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb"}, + {file = "wrapt-1.14.1.tar.gz", hash = "sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d"}, +] [metadata] -content-hash = "ef7ed9625ca7fc1a50017fa99d10a122e42e5db45deb2a08023cf31354c6e6c4" -python-versions = "^3.6" - -[metadata.hashes] -astroid = ["292fa429e69d60e4161e7612cb7cc8fa3609e2e309f80c224d93a76d5e7b58be", "c7013d119ec95eb626f7a2011f0b63d0c9a095df9ad06d8507b37084eada1a8d"] -atomicwrites = ["0312ad34fcad8fac3704d441f7b317e50af620823353ec657a53e981f92920c0", "ec9ae8adaae229e4f8446952d204a3e4b5fdd2d099f9be3aaf556120135fb3ee"] -attrs = ["10cbf6e27dbce8c30807caf056c8eb50917e0eaafe86347671b57254006c3e69", "ca4be454458f9dec299268d472aaa5a11f67a4ff70093396e1ceae9c76cf4bbb"] -certifi = ["339dc09518b07e2fa7eda5450740925974815557727d6bd35d319c1524a04a4c", "6d58c986d22b038c8c0df30d639f23a3e6d172a05c3583e766f4c0b785c0986a"] -chardet = ["84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", "fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"] -click = ["2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", "5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"] -codecov = ["8ed8b7c6791010d359baed66f84f061bba5bd41174bf324c31311e8737602788", "ae00d68e18d8a20e9c3288ba3875ae03db3a8e892115bf9b83ef20507732bed4"] -colorama = ["a3d89af5db9e9806a779a50296b5fdb466e281147c2c235e8225ecc6dbf7bbf3", "c9b54bebe91a6a803e0772c8561d53f2926bfeb17cd141fbabcb08424086595c"] -coverage = ["03481e81d558d30d230bc12999e3edffe392d244349a90f4ef9b88425fac74ba", "0b136648de27201056c1869a6c0d4e23f464750fd9a9ba9750b8336a244429ed", "0bf8cbbd71adfff0ef1f3a1531e6402d13b7b01ac50a79c97ca15f030dba6306", "104ab3934abaf5be871a583541e8829d6c19ce7bde2923b2751e0d3ca44db60a", "10a46017fef60e16694a30627319f38a2b9b52e90182dddb6e37dcdab0f4bf95", "15b111b6a0f46ee1a485414a52a7ad1d703bdf984e9ed3c288a4414d3871dcbd", "198626739a79b09fa0a2f06e083ffd12eb55449b5f8bfdbeed1df4910b2ca640", "1c383d2ef13ade2acc636556fd544dba6e14fa30755f26812f54300e401f98f2", "23d341cdd4a0371820eb2b0bd6b88f5003a7438bbedb33688cd33b8eae59affd", "28b2191e7283f4f3568962e373b47ef7f0392993bb6660d079c62bd50fe9d162", "2a5b73210bad5279ddb558d9a2bfedc7f4bf6ad7f3c988641d83c40293deaec1", "2eb564bbf7816a9d68dd3369a510be3327f1c618d2357fa6b1216994c2e3d508", "337ded681dd2ef9ca04ef5d93cfc87e52e09db2594c296b4a0a3662cb1b41249", "3a2184c6d797a125dca8367878d3b9a178b6fdd05fdc2d35d758c3006a1cd694", "3c79a6f7b95751cdebcd9037e4d06f8d5a9b60e4ed0cd231342aa8ad7124882a", "3d72c20bd105022d29b14a7d628462ebdc61de2f303322c0212a054352f3b287", "3eb42bf89a6be7deb64116dd1cc4b08171734d721e7a7e57ad64cc4ef29ed2f1", "4635a184d0bbe537aa185a34193898eee409332a8ccb27eea36f262566585000", "56e448f051a201c5ebbaa86a5efd0ca90d327204d8b059ab25ad0f35fbfd79f1", "5a13ea7911ff5e1796b6d5e4fbbf6952381a611209b736d48e675c2756f3f74e", "69bf008a06b76619d3c3f3b1983f5145c75a305a0fea513aca094cae5c40a8f5", "6bc583dc18d5979dc0f6cec26a8603129de0304d5ae1f17e57a12834e7235062", "701cd6093d63e6b8ad7009d8a92425428bc4d6e7ab8d75efbb665c806c1d79ba", "7608a3dd5d73cb06c531b8925e0ef8d3de31fed2544a7de6c63960a1e73ea4bc", "76ecd006d1d8f739430ec50cc872889af1f9c1b6b8f48e29941814b09b0fd3cc", "7aa36d2b844a3e4a4b356708d79fd2c260281a7390d678a10b91ca595ddc9e99", "7d3f553904b0c5c016d1dad058a7554c7ac4c91a789fca496e7d8347ad040653", "7e1fe19bd6dce69d9fd159d8e4a80a8f52101380d5d3a4d374b6d3eae0e5de9c", "8c3cb8c35ec4d9506979b4cf90ee9918bc2e49f84189d9bf5c36c0c1119c6558", "9d6dd10d49e01571bf6e147d3b505141ffc093a06756c60b053a859cb2128b1f", "9e112fcbe0148a6fa4f0a02e8d58e94470fc6cb82a5481618fea901699bf34c4", "ac4fef68da01116a5c117eba4dd46f2e06847a497de5ed1d64bb99a5fda1ef91", "b8815995e050764c8610dbc82641807d196927c3dbed207f0a079833ffcf588d", "be6cfcd8053d13f5f5eeb284aa8a814220c3da1b0078fa859011c7fffd86dab9", "c1bb572fab8208c400adaf06a8133ac0712179a334c09224fb11393e920abcdd", "de4418dadaa1c01d497e539210cb6baa015965526ff5afc078c57ca69160108d", "e05cb4d9aad6233d67e0541caa7e511fa4047ed7750ec2510d466e806e0255d6", "e4d96c07229f58cb686120f168276e434660e4358cc9cf3b0464210b04913e77", "f05a636b4564104120111800021a92e43397bc12a5c72fed7036be8556e0029e", "f3f501f345f24383c0000395b26b726e46758b71393267aeae0bd36f8b3ade80", "f8a923a85cb099422ad5a2e345fe877bbc89a8a8b23235824a93488150e45f6e"] -idna = ["156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e", "684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16"] -isort = ["1153601da39a25b14ddc54955dbbacbb6b2d19135386699e2ad58517953b34af", "b9c40e9750f3d77e6e4d441d8b0266cf555e7cdabdcff33c4fd06366ca761ef8", "ec9ef8f4a9bc6f71eec99e1806bfa2de401650d996c59330782b89a5555c1497"] -lazy-object-proxy = ["0ce34342b419bd8f018e6666bfef729aec3edf62345a53b537a4dcc115746a33", "1b668120716eb7ee21d8a38815e5eb3bb8211117d9a90b0f8e21722c0758cc39", "209615b0fe4624d79e50220ce3310ca1a9445fd8e6d3572a896e7f9146bbf019", "27bf62cb2b1a2068d443ff7097ee33393f8483b570b475db8ebf7e1cba64f088", "27ea6fd1c02dcc78172a82fc37fcc0992a94e4cecf53cb6d73f11749825bd98b", "2c1b21b44ac9beb0fc848d3993924147ba45c4ebc24be19825e57aabbe74a99e", "2df72ab12046a3496a92476020a1a0abf78b2a7db9ff4dc2036b8dd980203ae6", "320ffd3de9699d3892048baee45ebfbbf9388a7d65d832d7e580243ade426d2b", "50e3b9a464d5d08cc5227413db0d1c4707b6172e4d4d915c1c70e4de0bbff1f5", "5276db7ff62bb7b52f77f1f51ed58850e315154249aceb42e7f4c611f0f847ff", "61a6cf00dcb1a7f0c773ed4acc509cb636af2d6337a08f362413c76b2b47a8dd", "6ae6c4cb59f199d8827c5a07546b2ab7e85d262acaccaacd49b62f53f7c456f7", "7661d401d60d8bf15bb5da39e4dd72f5d764c5aff5a86ef52a042506e3e970ff", "7bd527f36a605c914efca5d3d014170b2cb184723e423d26b1fb2fd9108e264d", "7cb54db3535c8686ea12e9535eb087d32421184eacc6939ef15ef50f83a5e7e2", "7f3a2d740291f7f2c111d86a1c4851b70fb000a6c8883a59660d95ad57b9df35", "81304b7d8e9c824d058087dcb89144842c8e0dea6d281c031f59f0acf66963d4", "933947e8b4fbe617a51528b09851685138b49d511af0b6c0da2539115d6d4514", "94223d7f060301b3a8c09c9b3bc3294b56b2188e7d8179c762a1cda72c979252", "ab3ca49afcb47058393b0122428358d2fbe0408cf99f1b58b295cfeb4ed39109", "bd6292f565ca46dee4e737ebcc20742e3b5be2b01556dafe169f6c65d088875f", "cb924aa3e4a3fb644d0c463cad5bc2572649a6a3f68a7f8e4fbe44aaa6d77e4c", "d0fc7a286feac9077ec52a927fc9fe8fe2fabab95426722be4c953c9a8bede92", "ddc34786490a6e4ec0a855d401034cbd1242ef186c20d79d2166d6a4bd449577", "e34b155e36fa9da7e1b7c738ed7767fc9491a62ec6af70fe9da4a057759edc2d", "e5b9e8f6bda48460b7b143c3821b21b452cb3a835e6bbd5dd33aa0c8d3f5137d", "e81ebf6c5ee9684be8f2c87563880f93eedd56dd2b6146d8a725b50b7e5adb0f", "eb91be369f945f10d3a49f5f9be8b3d0b93a4c2be8f8a5b83b0571b8123e0a7a", "f460d1ceb0e4a5dcb2a652db0904224f367c9b3c1470d5a7683c0480e582468b"] -mccabe = ["ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", "dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"] -more-itertools = ["c187a73da93e7a8acc0001572aebc7e3c69daf7bf6881a2cea10650bd4420092", "c476b5d3a34e12d40130bc2f935028b5f636df8f372dc2c1c01dc19681b2039e", "fcbfeaea0be121980e15bc97b3817b5202ca73d0eae185b4550cbfce2a3ebb3d"] -mypy = ["673ea75fb750289b7d1da1331c125dc62fc1c3a8db9129bb372ae7b7d5bf300a", "c770605a579fdd4a014e9f0a34b6c7a36ce69b08100ff728e96e27445cef3b3c"] -pluggy = ["447ba94990e8014ee25ec853339faf7b0fc8050cdc3289d4d71f7f410fb90095", "bde19360a8ec4dfd8a20dcb811780a30998101f078fc7ded6162f0076f50508f"] -py = ["bf92637198836372b520efcba9e020c330123be8ce527e535d185ed4b6f45694", "e76826342cefe3c3d5f7e8ee4316b80d1dd8a300781612ddbc765c17ba25a6c6"] -pylint = ["1d6d3622c94b4887115fe5204982eee66fdd8a951cf98635ee5caee6ec98c3ec", "31142f764d2a7cd41df5196f9933b12b7ee55e73ef12204b648ad7e556c119fb"] -pytest = ["a9e5e8d7ab9d5b0747f37740276eb362e6a76275d76cebbb52c6049d93b475db", "bf47e8ed20d03764f963f0070ff1c8fda6e2671fc5dd562a4d3b7148ad60f5ca"] -requests = ["99dcfdaaeb17caf6e526f32b6a7b780461512ab3f1d992187801694cba42770c", "a84b8c9ab6239b578f22d1c21d51b696dcfe004032bb80ea832398d6909d7279"] -rope = ["a09edfd2034fd50099a67822f9bd851fbd0f4e98d3b87519f6267b60e50d80d1"] -six = ["70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", "832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"] -typed-ast = ["0948004fa228ae071054f5208840a1e88747a357ec1101c17217bfe99b299d58", "10703d3cec8dcd9eef5a630a04056bbc898abc19bac5691612acba7d1325b66d", "1f6c4bd0bdc0f14246fd41262df7dfc018d65bb05f6e16390b7ea26ca454a291", "25d8feefe27eb0303b73545416b13d108c6067b846b543738a25ff304824ed9a", "29464a177d56e4e055b5f7b629935af7f49c196be47528cc94e0a7bf83fbc2b9", "2e214b72168ea0275efd6c884b114ab42e316de3ffa125b267e732ed2abda892", "3e0d5e48e3a23e9a4d1a9f698e32a542a4a288c871d33ed8df1b092a40f3a0f9", "519425deca5c2b2bdac49f77b2c5625781abbaf9a809d727d3a5596b30bb4ded", "57fe287f0cdd9ceaf69e7b71a2e94a24b5d268b35df251a88fef5cc241bf73aa", "668d0cec391d9aed1c6a388b0d5b97cd22e6073eaa5fbaa6d2946603b4871efe", "68ba70684990f59497680ff90d18e756a47bf4863c604098f10de9716b2c0bdd", "6de012d2b166fe7a4cdf505eee3aaa12192f7ba365beeefaca4ec10e31241a85", "79b91ebe5a28d349b6d0d323023350133e927b4de5b651a8aa2db69c761420c6", "8550177fa5d4c1f09b5e5f524411c44633c80ec69b24e0e98906dd761941ca46", "898f818399cafcdb93cbbe15fc83a33d05f18e29fb498ddc09b0214cdfc7cd51", "94b091dc0f19291adcb279a108f5d38de2430411068b219f41b343c03b28fb1f", "a26863198902cda15ab4503991e8cf1ca874219e0118cbf07c126bce7c4db129", "a8034021801bc0440f2e027c354b4eafd95891b573e12ff0418dec385c76785c", "bc978ac17468fe868ee589c795d06777f75496b1ed576d308002c8a5756fb9ea", "c05b41bc1deade9f90ddc5d988fe506208019ebba9f2578c622516fd201f5863", "c9b060bd1e5a26ab6e8267fd46fc9e02b54eb15fffb16d112d4c7b1c12987559", "edb04bdd45bfd76c8292c4d9654568efaedf76fe78eb246dde69bdb13b2dad87", "f19f2a4f547505fe9072e15f6f4ae714af51b5a681a97f187971f50c283193b6"] -urllib3 = ["61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39", "de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22"] -wrapt = ["d4d560d479f2c21e1b5443bbd15fe7ec4b37fe7e53d335d3b9b0a7b1226fe3c6"] +lock-version = "2.0" +python-versions = "^3.11" +content-hash = "0e478f674b438cf6c4af4b9f185a83510c3bff562abf068385c7e894865142b6" From b2670491090106ea7e8823239d307e21720cc374 Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Fri, 23 Dec 2022 10:22:36 -0500 Subject: [PATCH 10/39] clear file --- tests/__init__.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/__init__.py b/tests/__init__.py index d6d00d2..e69de29 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,8 +0,0 @@ -"""Allow tests to discover the modules.""" - -import sys -from pathlib import Path - - -_ROOT = Path(__file__).resolve().parent.parent -sys.path.insert(0, str(_ROOT / "hb")) From ca682bdbac4c57607cbbedab90a270359d2cc022 Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Fri, 23 Dec 2022 10:46:59 -0500 Subject: [PATCH 11/39] add black --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 6c6da36..4a87a52 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,6 +32,7 @@ python = "^3.11" [tool.poetry.group.test.dependencies] +black = "^22.12.0" flake8 = "^6.0.0" mypy = "^0.991" pylint = "^2.15.9" From 39f5988e7dea05259dc8a7f11e9c0104742b14e7 Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Fri, 23 Dec 2022 10:47:05 -0500 Subject: [PATCH 12/39] update poetry.lock --- poetry.lock | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index 16f66bf..55a08b3 100644 --- a/poetry.lock +++ b/poetry.lock @@ -35,6 +35,55 @@ docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib- tests = ["attrs[tests-no-zope]", "zope.interface"] tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"] +[[package]] +name = "black" +version = "22.12.0" +description = "The uncompromising code formatter." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "black-22.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d"}, + {file = "black-22.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351"}, + {file = "black-22.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f"}, + {file = "black-22.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4"}, + {file = "black-22.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2"}, + {file = "black-22.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350"}, + {file = "black-22.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d"}, + {file = "black-22.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc"}, + {file = "black-22.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320"}, + {file = "black-22.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148"}, + {file = "black-22.12.0-py3-none-any.whl", hash = "sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf"}, + {file = "black-22.12.0.tar.gz", hash = "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f"}, +] + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +pathspec = ">=0.9.0" +platformdirs = ">=2" + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "click" +version = "8.1.3" +description = "Composable command line interface toolkit" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, + {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + [[package]] name = "colorama" version = "0.4.6" @@ -224,6 +273,18 @@ files = [ {file = "packaging-22.0.tar.gz", hash = "sha256:2198ec20bd4c017b8f9717e00f0c8714076fc2fd93816750ab48e2c41de2cfd3"}, ] +[[package]] +name = "pathspec" +version = "0.10.3" +description = "Utility library for gitignore style pattern matching of file paths." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pathspec-0.10.3-py3-none-any.whl", hash = "sha256:3c95343af8b756205e2aba76e843ba9520a24dd84f68c22b9f93251507509dd6"}, + {file = "pathspec-0.10.3.tar.gz", hash = "sha256:56200de4077d9d0791465aa9095a01d421861e405b5096955051deefd697d6f6"}, +] + [[package]] name = "platformdirs" version = "2.6.0" @@ -428,4 +489,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "0e478f674b438cf6c4af4b9f185a83510c3bff562abf068385c7e894865142b6" +content-hash = "07bdb70fdaaa672a051ab7ccb2bdcced367b4eaa797991d4de45055f8c9afda0" From cdfa8afe0cd7c374d9c810a8b53959656483a1d0 Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Fri, 23 Dec 2022 10:47:16 -0500 Subject: [PATCH 13/39] linted --- hb/hb.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/hb/hb.py b/hb/hb.py index 0e79689..3ade97f 100644 --- a/hb/hb.py +++ b/hb/hb.py @@ -1,4 +1,4 @@ -"""Hash Brown""" +"""hb.py""" from contextlib import contextmanager from pathlib import Path @@ -12,7 +12,8 @@ import zlib -class HashBrown(): +class HashBrown: + """Hash Brown""" def __init__(self, algo, path) -> None: self.algo = algo.lower() self.filesize = os.path.getsize(path) @@ -23,9 +24,14 @@ def __init__(self, algo, path) -> None: @contextmanager def open(self) -> Generator: """File open with progress tracker.""" + def _progress() -> None: while self.tell != self.filesize: - print("{:.3%} {} {}".format(self.tell / self.filesize, self.algo, self.path), end="\r", file=sys.stderr) + print( + f"{self.tell / self.filesize:.3%} {self.algo} {self.path}", + end="\r", + file=sys.stderr, + ) time.sleep(0.5) Thread(target=_progress).start() @@ -44,14 +50,14 @@ def compute(self) -> str: for line in lines: result = zlib.adler32(line, result) self.tell = lines.tell() - self.hexdigest = hex(result).removeprefix('0x').zfill(8) + self.hexdigest = hex(result).removeprefix("0x").zfill(8) case "crc32": result = 0 with self.open() as lines: for line in lines: result = zlib.crc32(line, result) self.tell = lines.tell() - self.hexdigest = hex(result).removeprefix('0x').zfill(8) + self.hexdigest = hex(result).removeprefix("0x").zfill(8) case _: result = hashlib.new(self.algo) with self.open() as lines: @@ -75,14 +81,14 @@ def compute(algo: str, path: str) -> str: def scan(path: str) -> None: """Scan a file of hexdigests to check if they match.""" - with open(Path(path)) as lines: + with open(Path(path), encoding="utf-8") as lines: for i, line in enumerate(lines, start=1): line = line.strip() if not line or line.startswith("#"): # skip blank lines and comments continue if match := re.match(r"^([0-9A-Fa-f]+) (\w+) (.+)$", line): - given_hexdigest, algo, path = match.group(1, 2, 3) - computed_hexdigest = HashBrown(algo, path).compute() - print(f"{'OK' if computed_hexdigest == given_hexdigest else 'BAD'} {algo} {path}") + given, algo, path = match.group(1, 2, 3) + computed = HashBrown(algo, path).compute() + print(f"{'OK' if computed == given else 'BAD'} {algo} {path}") else: print(f"\nUnable to read line {i}: '{line}'\n") From faa8d037083d82195040c128b99adc2de570f63b Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Fri, 23 Dec 2022 10:52:41 -0500 Subject: [PATCH 14/39] make mypy happy --- hb/hb.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/hb/hb.py b/hb/hb.py index 3ade97f..923924b 100644 --- a/hb/hb.py +++ b/hb/hb.py @@ -14,10 +14,11 @@ class HashBrown: """Hash Brown""" + def __init__(self, algo, path) -> None: self.algo = algo.lower() self.filesize = os.path.getsize(path) - self.hexdigest = None + self.hexdigest = "" self.path = Path(path) self.tell = 0 @@ -35,7 +36,7 @@ def _progress() -> None: time.sleep(0.5) Thread(target=_progress).start() - with open(self.path, "rb") as lines: + with open(self.path, mode="rb") as lines: yield lines def compute(self) -> str: @@ -45,26 +46,26 @@ def compute(self) -> str: match self.algo: case "adler32": - result = 1 + checksum = 1 with self.open() as lines: for line in lines: - result = zlib.adler32(line, result) + checksum = zlib.adler32(line, checksum) self.tell = lines.tell() - self.hexdigest = hex(result).removeprefix("0x").zfill(8) + self.hexdigest = hex(checksum).removeprefix("0x").zfill(8) case "crc32": - result = 0 + checksum = 0 with self.open() as lines: for line in lines: - result = zlib.crc32(line, result) + checksum = zlib.crc32(line, checksum) self.tell = lines.tell() - self.hexdigest = hex(result).removeprefix("0x").zfill(8) + self.hexdigest = hex(checksum).removeprefix("0x").zfill(8) case _: - result = hashlib.new(self.algo) + digest = hashlib.new(self.algo) with self.open() as lines: for line in lines: - result.update(line) + digest.update(line) self.tell = lines.tell() - self.hexdigest = result.hexdigest() + self.hexdigest = digest.hexdigest() self.tell = self.filesize return self.hexdigest From f53298a215ee83b10f4e39b44535de3d9dc214a7 Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Fri, 23 Dec 2022 11:06:32 -0500 Subject: [PATCH 15/39] rename file --- tests/{test_main.py => test_hb.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/{test_main.py => test_hb.py} (100%) diff --git a/tests/test_main.py b/tests/test_hb.py similarity index 100% rename from tests/test_main.py rename to tests/test_hb.py From ff022676a919c4ee97549ce7775e94b3c8ab1b5c Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Fri, 23 Dec 2022 12:05:53 -0500 Subject: [PATCH 16/39] add pytest-subtests --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 4a87a52..1f06020 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,6 +37,7 @@ flake8 = "^6.0.0" mypy = "^0.991" pylint = "^2.15.9" pytest = "^7.2.0" +pytest-subtests = "^0.9.0" [build-system] From 31b154f2672ccdba3d35f4aaca03e23786e777df Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Fri, 23 Dec 2022 12:05:59 -0500 Subject: [PATCH 17/39] update poetry.lock --- poetry.lock | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index 55a08b3..3f1204e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -388,6 +388,21 @@ pluggy = ">=0.12,<2.0" [package.extras] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] +[[package]] +name = "pytest-subtests" +version = "0.9.0" +description = "unittest subTest() support and subtests fixture" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-subtests-0.9.0.tar.gz", hash = "sha256:c0317cd5f6a5eb3e957e89dbe4fc3322a9afddba2db8414355ed2a2cb91a844e"}, + {file = "pytest_subtests-0.9.0-py3-none-any.whl", hash = "sha256:f5f616b92c13405909d210569d6d3914db6fe156333ff5426534f97d5b447861"}, +] + +[package.dependencies] +pytest = ">=7.0" + [[package]] name = "tomlkit" version = "0.11.6" @@ -489,4 +504,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "07bdb70fdaaa672a051ab7ccb2bdcced367b4eaa797991d4de45055f8c9afda0" +content-hash = "54f63610b50f9126c986c0ddcb22b7faf09b98dc9700dae3a10e92ea1e8b8df8" From 16b46f8958a7f4ecec7d66ac8aa48e0b853c0a36 Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Fri, 23 Dec 2022 12:07:22 -0500 Subject: [PATCH 18/39] use length 64 for shake algos --- hb/hb.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hb/hb.py b/hb/hb.py index 923924b..d3c470a 100644 --- a/hb/hb.py +++ b/hb/hb.py @@ -65,7 +65,10 @@ def compute(self) -> str: for line in lines: digest.update(line) self.tell = lines.tell() - self.hexdigest = digest.hexdigest() + if self.algo.startswith("shake_"): + self.hexdigest = digest.hexdigest(64) # type: ignore + else: + self.hexdigest = digest.hexdigest() self.tell = self.filesize return self.hexdigest From 438f0c6b050d5f7558aed902847b0450f76d6131 Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Fri, 23 Dec 2022 12:33:43 -0500 Subject: [PATCH 19/39] update tests --- tests/conftest.py | 79 --------------- tests/test_files/checklist_bad_01.txt | 3 - tests/test_files/checklist_bad_02.txt | 3 - tests/test_files/checklist_bad_03.txt | 3 - tests/test_files/checklist_good.txt | 3 - tests/test_files/fox.txt | 1 - tests/test_hb.py | 133 ++++++++++---------------- 7 files changed, 53 insertions(+), 172 deletions(-) delete mode 100644 tests/conftest.py delete mode 100644 tests/test_files/checklist_bad_01.txt delete mode 100644 tests/test_files/checklist_bad_02.txt delete mode 100644 tests/test_files/checklist_bad_03.txt delete mode 100644 tests/test_files/checklist_good.txt delete mode 100644 tests/test_files/fox.txt diff --git a/tests/conftest.py b/tests/conftest.py deleted file mode 100644 index d9263b3..0000000 --- a/tests/conftest.py +++ /dev/null @@ -1,79 +0,0 @@ -"""Fixtures""" - -from hashlib import algorithms_guaranteed -from pathlib import Path -from typing import List - -import pytest - -from hb.main import Checksum - - -_HERE = Path(__file__).parent -_FOX = str(_HERE / "test_files" / "fox.txt") - - -@pytest.fixture -def supported() -> List[str]: - return [x for x in sorted(algorithms_guaranteed) if "_" not in x] + ["adler32", "crc32"] - -@pytest.fixture -def version() -> str: - ver = "Cannot find version!" - with open(_HERE.parent / "pyproject.toml", "r") as lines: - for line in lines: - if line.startswith("version = "): - ver = line.strip().split(" = ")[1][1:-1] - return ver - -@pytest.fixture -def good_checklists() -> List[str]: - return [str(_HERE / "test_files" / "checklist_good.txt")] - -@pytest.fixture -def bad_checklists() -> List[str]: - return [str(_HERE / "test_files" / f"checklist_bad_0{i}.txt") for i in range(1, 4)] - -@pytest.fixture -def blake2b() -> str: - return str(Checksum(_FOX).blake2b) - -@pytest.fixture -def blake2s() -> str: - return str(Checksum(_FOX).blake2s) - -@pytest.fixture -def md5() -> str: - return str(Checksum(_FOX).md5) - -@pytest.fixture -def sha1() -> str: - return str(Checksum(_FOX).sha1) - -@pytest.fixture -def sha224() -> str: - return str(Checksum(_FOX).sha224) - -@pytest.fixture -def sha256() -> str: - return str(Checksum(_FOX).sha256) - -@pytest.fixture -def sha384() -> str: - return str(Checksum(_FOX).sha384) - -@pytest.fixture -def sha512() -> str: - return str(Checksum(_FOX).sha512) - -@pytest.fixture -def adler32() -> str: - return str(Checksum(_FOX).adler32) - -@pytest.fixture -def crc32() -> str: - return str(Checksum(_FOX).crc32) - -@pytest.fixture -def checksum_obj() -> Checksum: - return Checksum(_FOX, threshold=0) diff --git a/tests/test_files/checklist_bad_01.txt b/tests/test_files/checklist_bad_01.txt deleted file mode 100644 index f48b4bf..0000000 --- a/tests/test_files/checklist_bad_01.txt +++ /dev/null @@ -1,3 +0,0 @@ -# missing algorithm - -(test.txt) = c08420f4c716f3814c268dd845356276 diff --git a/tests/test_files/checklist_bad_02.txt b/tests/test_files/checklist_bad_02.txt deleted file mode 100644 index 36f138b..0000000 --- a/tests/test_files/checklist_bad_02.txt +++ /dev/null @@ -1,3 +0,0 @@ -# missing file - -md5 () = c08420f4c716f3814c268dd845356276 diff --git a/tests/test_files/checklist_bad_03.txt b/tests/test_files/checklist_bad_03.txt deleted file mode 100644 index 4910083..0000000 --- a/tests/test_files/checklist_bad_03.txt +++ /dev/null @@ -1,3 +0,0 @@ -# missing checksum - -md5 (test.txt) = diff --git a/tests/test_files/checklist_good.txt b/tests/test_files/checklist_good.txt deleted file mode 100644 index d770634..0000000 --- a/tests/test_files/checklist_good.txt +++ /dev/null @@ -1,3 +0,0 @@ -# comments are allowed - -md5 (test.txt) = c08420f4c716f3814c268dd845356276 # here too diff --git a/tests/test_files/fox.txt b/tests/test_files/fox.txt deleted file mode 100644 index 84102df..0000000 --- a/tests/test_files/fox.txt +++ /dev/null @@ -1 +0,0 @@ -The quick brown fox jumps over the lazy dog diff --git a/tests/test_hb.py b/tests/test_hb.py index c49516f..c3a32a3 100644 --- a/tests/test_hb.py +++ b/tests/test_hb.py @@ -1,80 +1,53 @@ -"""Tests""" - -from typing import List - -import pytest - -from hb.main import Checksum - - -def test_supported(supported: str) -> None: - assert list(Checksum.SUPPORTED) == supported - -def test_unsupported() -> None: - with pytest.raises(ValueError): - Checksum(".").compute("unsupported") - -def test_version(version: str) -> None: - assert Checksum.VERSION == version - -def test_parse(good_checklists: List[str], bad_checklists: List[str]) -> None: - for checklist in good_checklists: - for algorithm, path, checksum in Checksum.parse(checklist): - assert algorithm == "md5" - assert path == "test.txt" - assert checksum == "c08420f4c716f3814c268dd845356276" - - for checklist in bad_checklists: - with pytest.raises(ValueError): - for algorithm, path, checksum in Checksum.parse(checklist): pass - -def test_print() -> None: - assert Checksum.print("a", "b", "c") == "a (b) = c" - -def test_path(checksum_obj: Checksum) -> None: - checksum_obj.get("md5") - assert checksum_obj.path != "abc" - assert checksum_obj.checksums - - checksum_obj.path = "abc" - assert checksum_obj.path == "abc" - assert not checksum_obj.checksums - -def test_blake2b(blake2b: str) -> None: - assert blake2b == "20a9ed5b422c04cf7328b36c0d4ad235408d034bee5a15d77a4185c1bf2c30202d340c212e872d1074f3556f428357e2503b749f3e198b59a74313ad2975a951" - -def test_blake2s(blake2s: str) -> None: - assert blake2s == "668e0a8671f032f313c8a12d24f5c8669259ba6d9a9f6f62451ea33fda9f2f79" - -def test_md5(md5: str) -> None: - assert md5 == "37c4b87edffc5d198ff5a185cee7ee09" - -def test_sha1(sha1: str) -> None: - assert sha1 == "be417768b5c3c5c1d9bcb2e7c119196dd76b5570" - -def test_sha224(sha224: str) -> None: - assert sha224 == "62e514e536e4ed4633eeec99d60f97b4d95889227975d975b2ad0de3" - -def test_sha256(sha256: str) -> None: - assert sha256 == "c03905fcdab297513a620ec81ed46ca44ddb62d41cbbd83eb4a5a3592be26a69" - -def test_sha384(sha384: str) -> None: - assert sha384 == "f565ad8f9c76cf8c4a2e145e712df740702e066a5908f6285eafa1a83a623e882207643ce5ec29628ff0186150275ef3" - -def test_sha512(sha512: str) -> None: - assert sha512 == "a12ac6bdd854ac30c5cc5b576e1ee2c060c0d8c2bec8797423d7119aa2b962f7f30ce2e39879cbff0109c8f0a3fd9389a369daae45df7d7b286d7d98272dc5b1" - -def test_adler32(adler32: str) -> None: - assert adler32 == "6bc00fe4" - -def test_crc32(crc32: str) -> None: - assert crc32 == "6d93c138" - -def test_via_get(checksum_obj: Checksum) -> None: - assert checksum_obj.get("md5") == "37c4b87edffc5d198ff5a185cee7ee09" - assert checksum_obj.get("crc32") == "6d93c138" - - # should not actually go through full compute again - # this covers some lines for code coverage - assert checksum_obj.md5 == "37c4b87edffc5d198ff5a185cee7ee09" - assert checksum_obj.crc32 == "6d93c138" +"""test_hb.py""" + +# mypy: ignore-errors + +import hashlib +import zlib + +from hb import hb +from hb.hb import HashBrown + + +def use_stdlib(algo, path) -> str: + """Compute the hexdigest using hashlib and zlib.""" + match algo: + case "adler32": + checksum = 1 + with open(path, mode="rb") as lines: + for line in lines: + checksum = zlib.adler32(line, checksum) + hexdigest = hex(checksum).removeprefix("0x").zfill(8) + case "crc32": + checksum = 0 + with open(path, mode="rb") as lines: + for line in lines: + checksum = zlib.crc32(line, checksum) + hexdigest = hex(checksum).removeprefix("0x").zfill(8) + case _: + digest = hashlib.new(algo) + with open(path, mode="rb") as lines: + for line in lines: + digest.update(line) + if algo.startswith("shake_"): + hexdigest = digest.hexdigest(64) + else: + hexdigest = digest.hexdigest() + return hexdigest + + +def test_compute(subtests): + """Compare with direct usage of hashlib and zlib.""" + for algo in hashlib.algorithms_guaranteed | {"adler32", "crc32"}: + with subtests.test(algo=algo): + using_hb = HashBrown(algo, "LICENSE").compute() + using_stdlib = use_stdlib(algo, "LICENSE") + assert using_hb == using_stdlib + + +def test_pprint(subtests): + """Check pretty print output.""" + for algo in hashlib.algorithms_guaranteed | {"adler32", "crc32"}: + with subtests.test(algo=algo): + hexdigest = use_stdlib(algo, "LICENSE") + assert hb.compute(algo, "LICENSE") == f"{hexdigest} {algo} LICENSE" From 4fb2b5125cc4055510aacf28042c2b3915053271 Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Fri, 23 Dec 2022 13:01:13 -0500 Subject: [PATCH 20/39] update pyproject.toml --- pyproject.toml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1f06020..b0d44ae 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,28 +1,22 @@ [tool.poetry] name = "hb" version = "2.0.0" -description = "A simple utility for calculating hashes and checksums." +description = "A convenient interface for hashlib and zlib." authors = ["Ching Chow "] readme = "README.md" license = "MIT" homepage = "https://github.com/chingc/Hash-Brown" repository = "https://github.com/chingc/Hash-Brown" documentation = "https://github.com/chingc/Hash-Brown" -keywords = ["checksum", "digest", "hash", "md5", "sha1"] +keywords = ["checksum", "digest", "hashlib", "zlib", "crc32", "md5", "sha"] classifiers = [ "Development Status :: 4 - Beta", - "Environment :: Console", "Intended Audience :: Developers", "Intended Audience :: System Administrators", "License :: OSI Approved :: MIT License", "Operating System :: MacOS", "Operating System :: Microsoft :: Windows", - "Operating System :: POSIX :: BSD", "Operating System :: POSIX :: Linux", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.6", - "Topic :: Security", - "Topic :: System :: Archiving", "Topic :: Utilities" ] From ee0639bca7fdc9c3bd8f8a8e3f5336f3fc0ce025 Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Fri, 23 Dec 2022 13:10:18 -0500 Subject: [PATCH 21/39] cancel in progress if pull request --- .github/workflows/test.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0079106..77f876d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,6 +6,10 @@ on: branches: - main +concurrency: + group: test-${{ github.head_ref || github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + jobs: test: strategy: From 4f9cb7b1d5d893cce8735bf3263fc9396838a788 Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Fri, 23 Dec 2022 22:48:48 -0500 Subject: [PATCH 22/39] generate random file for compute --- tests/test_hb.py | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/tests/test_hb.py b/tests/test_hb.py index c3a32a3..2789b72 100644 --- a/tests/test_hb.py +++ b/tests/test_hb.py @@ -1,15 +1,21 @@ """test_hb.py""" # mypy: ignore-errors +# pylint: disable=W import hashlib +import os +import tempfile +import uuid import zlib +import pytest + from hb import hb from hb.hb import HashBrown -def use_stdlib(algo, path) -> str: +def use_stdlib(algo, path): """Compute the hexdigest using hashlib and zlib.""" match algo: case "adler32": @@ -36,18 +42,30 @@ def use_stdlib(algo, path) -> str: return hexdigest -def test_compute(subtests): +@pytest.fixture +def randfile(): + """Generate a random ~1MB file.""" + temp = tempfile.NamedTemporaryFile(mode="w", delete=False, encoding="utf-8") + print("\n".join([str(uuid.uuid4()) for _ in range(30000)]), file=temp) + temp.close() + assert os.path.getsize(temp.name) > 1000000 + yield temp.name + os.unlink(temp.name) + assert not os.path.exists(temp.name) + + +def test_compute(subtests, randfile): """Compare with direct usage of hashlib and zlib.""" for algo in hashlib.algorithms_guaranteed | {"adler32", "crc32"}: with subtests.test(algo=algo): - using_hb = HashBrown(algo, "LICENSE").compute() - using_stdlib = use_stdlib(algo, "LICENSE") + using_hb = HashBrown(algo, randfile).compute() + using_stdlib = use_stdlib(algo, randfile) assert using_hb == using_stdlib -def test_pprint(subtests): +def test_pprint(subtests, randfile): """Check pretty print output.""" for algo in hashlib.algorithms_guaranteed | {"adler32", "crc32"}: with subtests.test(algo=algo): - hexdigest = use_stdlib(algo, "LICENSE") - assert hb.compute(algo, "LICENSE") == f"{hexdigest} {algo} LICENSE" + hexdigest = use_stdlib(algo, randfile) + assert hb.compute(algo, randfile) == f"{hexdigest} {algo} {randfile}" From dbeebef20deb6e98f2e7db4a44a7aa0af69fab86 Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Sat, 24 Dec 2022 00:05:33 -0500 Subject: [PATCH 23/39] option to also return results as a list --- hb/hb.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/hb/hb.py b/hb/hb.py index d3c470a..4256d14 100644 --- a/hb/hb.py +++ b/hb/hb.py @@ -83,8 +83,9 @@ def compute(algo: str, path: str) -> str: return HashBrown(algo, path).pprint() -def scan(path: str) -> None: +def scan(path: str, stdout_only: bool = True) -> None | list[str]: """Scan a file of hexdigests to check if they match.""" + results = [] with open(Path(path), encoding="utf-8") as lines: for i, line in enumerate(lines, start=1): line = line.strip() @@ -93,6 +94,10 @@ def scan(path: str) -> None: if match := re.match(r"^([0-9A-Fa-f]+) (\w+) (.+)$", line): given, algo, path = match.group(1, 2, 3) computed = HashBrown(algo, path).compute() - print(f"{'OK' if computed == given else 'BAD'} {algo} {path}") + result = f"{'OK' if computed == given else 'BAD'} {algo} {path}" else: - print(f"\nUnable to read line {i}: '{line}'\n") + result = f"\nUnable to read line {i}: '{line}'\n" + print(result) + if not stdout_only: + results.append(result) + return None if stdout_only else results From f7db31eb4380eb5d316badfe1bb082d9aa57d20f Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Sat, 24 Dec 2022 00:21:56 -0500 Subject: [PATCH 24/39] test scanner --- tests/test_hb.py | 59 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 11 deletions(-) diff --git a/tests/test_hb.py b/tests/test_hb.py index 2789b72..27f87e3 100644 --- a/tests/test_hb.py +++ b/tests/test_hb.py @@ -5,6 +5,7 @@ import hashlib import os +import re import tempfile import uuid import zlib @@ -43,29 +44,65 @@ def use_stdlib(algo, path): @pytest.fixture -def randfile(): +def guaranteed(): + """Supported algos.""" + return hashlib.algorithms_guaranteed | {"adler32", "crc32"} + + +@pytest.fixture +def rand_file(): """Generate a random ~1MB file.""" temp = tempfile.NamedTemporaryFile(mode="w", delete=False, encoding="utf-8") print("\n".join([str(uuid.uuid4()) for _ in range(30000)]), file=temp) temp.close() - assert os.path.getsize(temp.name) > 1000000 + assert os.path.getsize(temp.name) > 1_000_000 yield temp.name os.unlink(temp.name) assert not os.path.exists(temp.name) -def test_compute(subtests, randfile): +@pytest.fixture +def rand_digestfile(guaranteed, rand_file): + """Generate a file of digests.""" + temp = tempfile.NamedTemporaryFile(mode="w", delete=False, encoding="utf-8") + for algo in guaranteed: + print(hb.compute(algo, rand_file), file=temp) + temp.close() + yield temp.name + os.unlink(temp.name) + assert not os.path.exists(temp.name) + + +def test_compute(subtests, guaranteed, rand_file): """Compare with direct usage of hashlib and zlib.""" - for algo in hashlib.algorithms_guaranteed | {"adler32", "crc32"}: + for algo in guaranteed: with subtests.test(algo=algo): - using_hb = HashBrown(algo, randfile).compute() - using_stdlib = use_stdlib(algo, randfile) - assert using_hb == using_stdlib + with_hb = HashBrown(algo, rand_file).compute() + with_stdlib = use_stdlib(algo, rand_file) + assert with_hb == with_stdlib -def test_pprint(subtests, randfile): +def test_pprint(subtests, guaranteed, rand_file): """Check pretty print output.""" - for algo in hashlib.algorithms_guaranteed | {"adler32", "crc32"}: + for algo in guaranteed: with subtests.test(algo=algo): - hexdigest = use_stdlib(algo, randfile) - assert hb.compute(algo, randfile) == f"{hexdigest} {algo} {randfile}" + with_hb = hb.compute(algo, rand_file) + with_stdlib = f"{use_stdlib(algo, rand_file)} {algo} {rand_file}" + assert with_hb == with_stdlib + + +def test_scan(rand_digestfile): + """Verify file scanner.""" + with_hb = hb.scan(rand_digestfile, stdout_only=False) + with_stdlib = [] + + with open(rand_digestfile, encoding="utf-8") as lines: + for line in lines: + if match := re.match(r"^([0-9A-Fa-f]+) (\w+) (.+)$", line): + given, algo, path = match.group(1, 2, 3) + if use_stdlib(algo, path) == given: + with_stdlib.append(f"OK {algo} {path}") + else: + with_stdlib.append(f"BAD {algo} {path}") + + assert with_hb == with_stdlib From e5c40cdf9c234f00fe44878db276821fd786fbf8 Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Sat, 24 Dec 2022 16:30:45 -0500 Subject: [PATCH 25/39] add changelog --- CHANGELOG.md | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..ae5e0e8 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,73 @@ +# CHANGELOG + +## v2.0.0b1 - TBD + +- Breaking: Refactored for Python 3.11. +- Breaking: Refactored for clarity and simplicity. +- Breaking: Removed command line interface. Might return in the future. +- Misc: Moved to GitHub Actions from CircleCI. + +## v1.4.2 - 2018.11.04 + +- Fixed: Colorized text didn't appear properly. +- Misc: Code cleanup. + +## v1.4.1 - 2018.08.02 + +- Fixed: Progress meter also piped to file when redirecting output. [#3](https://github.com/chingc/Hash-Brown/issues/3) +- Fixed: Progress meter sometimes not cleared. [#4](https://github.com/chingc/Hash-Brown/issues/4) + +## v1.4.0 - 2018.08.01 + +- New: Option to hide results that are OK during check mode. + +## v1.3.0 - 2018.07.31 + +- New: Blast processing! (process files in parallel) + +## v1.2.0 - 2018.07.30 + +- New: Option to show elapsed time to hash all files. +- Misc: Code cleanup. + +## v1.1.1 - 2018.07.25 + +- Publish to PyPI! + +## v1.1.0 - 2018.07.25 + +- Changed: Checksum methods are now properties. +- Misc: Code cleanup. + +## v1.0.0 - 2018.07.16 + +- Breaking: Refactored for Python 3.7. +- Breaking: Simplified command line interface. +- Misc: Code cleanup. + +## v0.4.0 - 2018.06.27 + +- Misc: Code cleanup. + +## v0.3.2 - 2018.06.27 + +- Changed: Refactored for Python 3.2. + +## v0.3.1 - 2018.06.27 + +- Changed: Progress meter display format. +- Misc: Documentation update. + +## v0.3.0 - 2018.06.27 + +- Misc: Code cleanup. + +## v0.2.0 - 2018.06.27 + +- New: Recursive path expansion for Windows. +- New: Mismatch counting. +- Misc: Code cleanup. + +## v0.1.0 - 2018.06.27 + +- First release! From 25ae1b926cd565b8dbc2aeb3b61e37e0be4bd8d3 Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Mon, 26 Dec 2022 01:34:32 -0500 Subject: [PATCH 26/39] fix type annotations --- hb/hb.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hb/hb.py b/hb/hb.py index 4256d14..08cdfcd 100644 --- a/hb/hb.py +++ b/hb/hb.py @@ -9,13 +9,14 @@ import re import sys import time +import typing import zlib class HashBrown: """Hash Brown""" - def __init__(self, algo, path) -> None: + def __init__(self, algo: str, path: str | Path) -> None: self.algo = algo.lower() self.filesize = os.path.getsize(path) self.hexdigest = "" @@ -23,7 +24,7 @@ def __init__(self, algo, path) -> None: self.tell = 0 @contextmanager - def open(self) -> Generator: + def open(self) -> Generator[typing.BinaryIO, None, None]: """File open with progress tracker.""" def _progress() -> None: @@ -78,12 +79,12 @@ def pprint(self) -> str: return f"{self.compute()} {self.algo} {self.path}" -def compute(algo: str, path: str) -> str: +def compute(algo: str, path: str | Path) -> str: """Convenience function to compute and pprint.""" return HashBrown(algo, path).pprint() -def scan(path: str, stdout_only: bool = True) -> None | list[str]: +def scan(path: str | Path, stdout_only: bool = True) -> None | list[str]: """Scan a file of hexdigests to check if they match.""" results = [] with open(Path(path), encoding="utf-8") as lines: From 3f2a90a09bdd49ef38ba017eebe834cd1289311c Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Mon, 26 Dec 2022 01:56:10 -0500 Subject: [PATCH 27/39] add NotAFileError --- hb/hb.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/hb/hb.py b/hb/hb.py index 08cdfcd..bc60929 100644 --- a/hb/hb.py +++ b/hb/hb.py @@ -13,15 +13,23 @@ import zlib +class NotAFileError(OSError): + pass + + class HashBrown: """Hash Brown""" def __init__(self, algo: str, path: str | Path) -> None: - self.algo = algo.lower() - self.filesize = os.path.getsize(path) - self.hexdigest = "" - self.path = Path(path) - self.tell = 0 + path = Path(path) + if path.is_file(): + self.algo = algo.lower() + self.filesize = os.path.getsize(path) + self.hexdigest = "" + self.path = path + self.tell = 0 + else: + raise NotAFileError(f"Skipping '{path}' because it is not a file") @contextmanager def open(self) -> Generator[typing.BinaryIO, None, None]: From 7055c9f983e2a4a54cada2db43556f6375fdf665 Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Mon, 26 Dec 2022 01:59:46 -0500 Subject: [PATCH 28/39] make 'python -m hb' work --- hb/__main__.py | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 hb/__main__.py diff --git a/hb/__main__.py b/hb/__main__.py new file mode 100644 index 0000000..e6e3ae6 --- /dev/null +++ b/hb/__main__.py @@ -0,0 +1,10 @@ +if __name__ == "__main__": + import sys + + from hb import hb + + for path in sys.argv[2:]: + try: + print(hb.compute(sys.argv[1], path)) + except hb.NotAFileError as e: + print(e, file=sys.stderr) From 1254562cfc32082b4b76a535cd4f665b980538d3 Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Mon, 26 Dec 2022 02:14:18 -0500 Subject: [PATCH 29/39] add linting --- .github/workflows/test.yml | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 77f876d..426dea3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,10 +7,30 @@ on: - main concurrency: - group: test-${{ github.head_ref || github.ref }} + group: test-${{ github.actor }}-${{ github.head_ref || github.ref }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: + lint: + runs-on: ubuntu-latest + timeout-minutes: 5 + + steps: + - uses: actions/checkout@v3 + + - run: pipx install poetry + + - uses: actions/setup-python@v4 + with: + python-version: "3.11" + cache: "poetry" + + - run: poetry install + + - run: poetry run mypy --pretty --strict . + + - run: poetry run flake8 --ignore=E501 . + test: strategy: fail-fast: false @@ -19,6 +39,7 @@ jobs: python-version: ["3.11"] runs-on: ${{ matrix.os }} + timeout-minutes: 5 steps: - uses: actions/checkout@v3 From 7786dc451942168ab677d4a28d079815833fdbeb Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Tue, 27 Dec 2022 01:39:29 -0500 Subject: [PATCH 30/39] remove pylint --- poetry.lock | 191 +------------------------------------------------ pyproject.toml | 1 - 2 files changed, 1 insertion(+), 191 deletions(-) diff --git a/poetry.lock b/poetry.lock index 3f1204e..6635b62 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,21 +1,5 @@ # This file is automatically @generated by Poetry and should not be changed by hand. -[[package]] -name = "astroid" -version = "2.12.13" -description = "An abstract syntax tree for Python with inference support." -category = "dev" -optional = false -python-versions = ">=3.7.2" -files = [ - {file = "astroid-2.12.13-py3-none-any.whl", hash = "sha256:10e0ad5f7b79c435179d0d0f0df69998c4eef4597534aae44910db060baeb907"}, - {file = "astroid-2.12.13.tar.gz", hash = "sha256:1493fe8bd3dfd73dc35bd53c9d5b6e49ead98497c47b2307662556a5692d29d7"}, -] - -[package.dependencies] -lazy-object-proxy = ">=1.4.0" -wrapt = {version = ">=1.14,<2", markers = "python_version >= \"3.11\""} - [[package]] name = "attrs" version = "22.2.0" @@ -96,21 +80,6 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] -[[package]] -name = "dill" -version = "0.3.6" -description = "serialize all of python" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "dill-0.3.6-py3-none-any.whl", hash = "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0"}, - {file = "dill-0.3.6.tar.gz", hash = "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373"}, -] - -[package.extras] -graph = ["objgraph (>=1.7.2)"] - [[package]] name = "flake8" version = "6.0.0" @@ -140,53 +109,6 @@ files = [ {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, ] -[[package]] -name = "isort" -version = "5.11.4" -description = "A Python utility / library to sort Python imports." -category = "dev" -optional = false -python-versions = ">=3.7.0" -files = [ - {file = "isort-5.11.4-py3-none-any.whl", hash = "sha256:c033fd0edb91000a7f09527fe5c75321878f98322a77ddcc81adbd83724afb7b"}, - {file = "isort-5.11.4.tar.gz", hash = "sha256:6db30c5ded9815d813932c04c2f85a360bcdd35fed496f4d8f35495ef0a261b6"}, -] - -[package.extras] -colors = ["colorama (>=0.4.3,<0.5.0)"] -pipfile-deprecated-finder = ["pipreqs", "requirementslib"] -plugins = ["setuptools"] -requirements-deprecated-finder = ["pip-api", "pipreqs"] - -[[package]] -name = "lazy-object-proxy" -version = "1.8.0" -description = "A fast and thorough lazy object proxy." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "lazy-object-proxy-1.8.0.tar.gz", hash = "sha256:c219a00245af0f6fa4e95901ed28044544f50152840c5b6a3e7b2568db34d156"}, - {file = "lazy_object_proxy-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4fd031589121ad46e293629b39604031d354043bb5cdf83da4e93c2d7f3389fe"}, - {file = "lazy_object_proxy-1.8.0-cp310-cp310-win32.whl", hash = "sha256:b70d6e7a332eb0217e7872a73926ad4fdc14f846e85ad6749ad111084e76df25"}, - {file = "lazy_object_proxy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:eb329f8d8145379bf5dbe722182410fe8863d186e51bf034d2075eb8d85ee25b"}, - {file = "lazy_object_proxy-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4e2d9f764f1befd8bdc97673261b8bb888764dfdbd7a4d8f55e4fbcabb8c3fb7"}, - {file = "lazy_object_proxy-1.8.0-cp311-cp311-win32.whl", hash = "sha256:e20bfa6db17a39c706d24f82df8352488d2943a3b7ce7d4c22579cb89ca8896e"}, - {file = "lazy_object_proxy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:14010b49a2f56ec4943b6cf925f597b534ee2fe1f0738c84b3bce0c1a11ff10d"}, - {file = "lazy_object_proxy-1.8.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6850e4aeca6d0df35bb06e05c8b934ff7c533734eb51d0ceb2d63696f1e6030c"}, - {file = "lazy_object_proxy-1.8.0-cp37-cp37m-win32.whl", hash = "sha256:5b51d6f3bfeb289dfd4e95de2ecd464cd51982fe6f00e2be1d0bf94864d58acd"}, - {file = "lazy_object_proxy-1.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:6f593f26c470a379cf7f5bc6db6b5f1722353e7bf937b8d0d0b3fba911998858"}, - {file = "lazy_object_proxy-1.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c1c7c0433154bb7c54185714c6929acc0ba04ee1b167314a779b9025517eada"}, - {file = "lazy_object_proxy-1.8.0-cp38-cp38-win32.whl", hash = "sha256:d176f392dbbdaacccf15919c77f526edf11a34aece58b55ab58539807b85436f"}, - {file = "lazy_object_proxy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:afcaa24e48bb23b3be31e329deb3f1858f1f1df86aea3d70cb5c8578bfe5261c"}, - {file = "lazy_object_proxy-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:71d9ae8a82203511a6f60ca5a1b9f8ad201cac0fc75038b2dc5fa519589c9288"}, - {file = "lazy_object_proxy-1.8.0-cp39-cp39-win32.whl", hash = "sha256:8f6ce2118a90efa7f62dd38c7dbfffd42f468b180287b748626293bf12ed468f"}, - {file = "lazy_object_proxy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:eac3a9a5ef13b332c059772fd40b4b1c3d45a3a2b05e33a361dee48e54a4dad0"}, - {file = "lazy_object_proxy-1.8.0-pp37-pypy37_pp73-any.whl", hash = "sha256:ae032743794fba4d171b5b67310d69176287b5bf82a21f588282406a79498891"}, - {file = "lazy_object_proxy-1.8.0-pp38-pypy38_pp73-any.whl", hash = "sha256:7e1561626c49cb394268edd00501b289053a652ed762c58e1081224c8d881cec"}, - {file = "lazy_object_proxy-1.8.0-pp39-pypy39_pp73-any.whl", hash = "sha256:ce58b2b3734c73e68f0e30e4e725264d4d6be95818ec0a0be4bb6bf9a7e79aa8"}, -] - [[package]] name = "mccabe" version = "0.7.0" @@ -341,31 +263,6 @@ files = [ {file = "pyflakes-3.0.1.tar.gz", hash = "sha256:ec8b276a6b60bd80defed25add7e439881c19e64850afd9b346283d4165fd0fd"}, ] -[[package]] -name = "pylint" -version = "2.15.9" -description = "python code static checker" -category = "dev" -optional = false -python-versions = ">=3.7.2" -files = [ - {file = "pylint-2.15.9-py3-none-any.whl", hash = "sha256:349c8cd36aede4d50a0754a8c0218b43323d13d5d88f4b2952ddfe3e169681eb"}, - {file = "pylint-2.15.9.tar.gz", hash = "sha256:18783cca3cfee5b83c6c5d10b3cdb66c6594520ffae61890858fe8d932e1c6b4"}, -] - -[package.dependencies] -astroid = ">=2.12.13,<=2.14.0-dev0" -colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} -dill = {version = ">=0.3.6", markers = "python_version >= \"3.11\""} -isort = ">=4.2.5,<6" -mccabe = ">=0.6,<0.8" -platformdirs = ">=2.2.0" -tomlkit = ">=0.10.1" - -[package.extras] -spelling = ["pyenchant (>=3.2,<4.0)"] -testutils = ["gitpython (>3)"] - [[package]] name = "pytest" version = "7.2.0" @@ -403,18 +300,6 @@ files = [ [package.dependencies] pytest = ">=7.0" -[[package]] -name = "tomlkit" -version = "0.11.6" -description = "Style preserving TOML library" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "tomlkit-0.11.6-py3-none-any.whl", hash = "sha256:07de26b0d8cfc18f871aec595fda24d95b08fef89d147caa861939f37230bf4b"}, - {file = "tomlkit-0.11.6.tar.gz", hash = "sha256:71b952e5721688937fb02cf9d354dbcf0785066149d2855e44531ebdd2b65d73"}, -] - [[package]] name = "typing-extensions" version = "4.4.0" @@ -427,81 +312,7 @@ files = [ {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, ] -[[package]] -name = "wrapt" -version = "1.14.1" -description = "Module for decorators, wrappers and monkey patching." -category = "dev" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -files = [ - {file = "wrapt-1.14.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1"}, - {file = "wrapt-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320"}, - {file = "wrapt-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2"}, - {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4"}, - {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069"}, - {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310"}, - {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f"}, - {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656"}, - {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c"}, - {file = "wrapt-1.14.1-cp310-cp310-win32.whl", hash = "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8"}, - {file = "wrapt-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d"}, - {file = "wrapt-1.14.1-cp35-cp35m-win32.whl", hash = "sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7"}, - {file = "wrapt-1.14.1-cp35-cp35m-win_amd64.whl", hash = "sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00"}, - {file = "wrapt-1.14.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4"}, - {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1"}, - {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1"}, - {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff"}, - {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d"}, - {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1"}, - {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569"}, - {file = "wrapt-1.14.1-cp36-cp36m-win32.whl", hash = "sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed"}, - {file = "wrapt-1.14.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471"}, - {file = "wrapt-1.14.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248"}, - {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68"}, - {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d"}, - {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77"}, - {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7"}, - {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015"}, - {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a"}, - {file = "wrapt-1.14.1-cp37-cp37m-win32.whl", hash = "sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853"}, - {file = "wrapt-1.14.1-cp37-cp37m-win_amd64.whl", hash = "sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c"}, - {file = "wrapt-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456"}, - {file = "wrapt-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f"}, - {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc"}, - {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1"}, - {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af"}, - {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b"}, - {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0"}, - {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57"}, - {file = "wrapt-1.14.1-cp38-cp38-win32.whl", hash = "sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5"}, - {file = "wrapt-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d"}, - {file = "wrapt-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383"}, - {file = "wrapt-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7"}, - {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86"}, - {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735"}, - {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b"}, - {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3"}, - {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3"}, - {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe"}, - {file = "wrapt-1.14.1-cp39-cp39-win32.whl", hash = "sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5"}, - {file = "wrapt-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb"}, - {file = "wrapt-1.14.1.tar.gz", hash = "sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d"}, -] - [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "54f63610b50f9126c986c0ddcb22b7faf09b98dc9700dae3a10e92ea1e8b8df8" +content-hash = "677bdf12d239f45492fa31759c18934b0d14feaa65d4998a4e5678f3b0d004c0" diff --git a/pyproject.toml b/pyproject.toml index b0d44ae..1b85e31 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,7 +29,6 @@ python = "^3.11" black = "^22.12.0" flake8 = "^6.0.0" mypy = "^0.991" -pylint = "^2.15.9" pytest = "^7.2.0" pytest-subtests = "^0.9.0" From 0f03584242a19f0f72faa397dd23da22bebe089b Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Tue, 27 Dec 2022 01:39:55 -0500 Subject: [PATCH 31/39] cleanup --- hb/hb.py | 10 ++++------ tests/test_hb.py | 3 --- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/hb/hb.py b/hb/hb.py index bc60929..8b89a93 100644 --- a/hb/hb.py +++ b/hb/hb.py @@ -1,9 +1,3 @@ -"""hb.py""" - -from contextlib import contextmanager -from pathlib import Path -from threading import Thread -from typing import Generator import hashlib import os import re @@ -11,6 +5,10 @@ import time import typing import zlib +from contextlib import contextmanager +from pathlib import Path +from threading import Thread +from typing import Generator class NotAFileError(OSError): diff --git a/tests/test_hb.py b/tests/test_hb.py index 27f87e3..55ab7dd 100644 --- a/tests/test_hb.py +++ b/tests/test_hb.py @@ -1,7 +1,4 @@ -"""test_hb.py""" - # mypy: ignore-errors -# pylint: disable=W import hashlib import os From 6bcf9b368a51af73544e4943e6f5b54fdabde5ca Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Tue, 27 Dec 2022 01:46:33 -0500 Subject: [PATCH 32/39] add bandit --- poetry.lock | 144 ++++++++++++++++++++++++++++++++++++++++++++++++- pyproject.toml | 1 + 2 files changed, 144 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index 6635b62..f9420cf 100644 --- a/poetry.lock +++ b/poetry.lock @@ -19,6 +19,29 @@ docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib- tests = ["attrs[tests-no-zope]", "zope.interface"] tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"] +[[package]] +name = "bandit" +version = "1.7.4" +description = "Security oriented static analyser for python code." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "bandit-1.7.4-py3-none-any.whl", hash = "sha256:412d3f259dab4077d0e7f0c11f50f650cc7d10db905d98f6520a95a18049658a"}, + {file = "bandit-1.7.4.tar.gz", hash = "sha256:2d63a8c573417bae338962d4b9b06fbc6080f74ecd955a092849e1e65c717bd2"}, +] + +[package.dependencies] +colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} +GitPython = ">=1.0.1" +PyYAML = ">=5.3.1" +stevedore = ">=1.20.0" + +[package.extras] +test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)", "toml"] +toml = ["toml"] +yaml = ["PyYAML"] + [[package]] name = "black" version = "22.12.0" @@ -97,6 +120,36 @@ mccabe = ">=0.7.0,<0.8.0" pycodestyle = ">=2.10.0,<2.11.0" pyflakes = ">=3.0.0,<3.1.0" +[[package]] +name = "gitdb" +version = "4.0.10" +description = "Git Object Database" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "gitdb-4.0.10-py3-none-any.whl", hash = "sha256:c286cf298426064079ed96a9e4a9d39e7f3e9bf15ba60701e95f5492f28415c7"}, + {file = "gitdb-4.0.10.tar.gz", hash = "sha256:6eb990b69df4e15bad899ea868dc46572c3f75339735663b81de79b06f17eb9a"}, +] + +[package.dependencies] +smmap = ">=3.0.1,<6" + +[[package]] +name = "gitpython" +version = "3.1.29" +description = "GitPython is a python library used to interact with Git repositories" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "GitPython-3.1.29-py3-none-any.whl", hash = "sha256:41eea0deec2deea139b459ac03656f0dd28fc4a3387240ec1d3c259a2c47850f"}, + {file = "GitPython-3.1.29.tar.gz", hash = "sha256:cc36bfc4a3f913e66805a28e84703e419d9c264c1077e537b54f0e1af85dbefd"}, +] + +[package.dependencies] +gitdb = ">=4.0.1,<5" + [[package]] name = "iniconfig" version = "1.1.1" @@ -207,6 +260,18 @@ files = [ {file = "pathspec-0.10.3.tar.gz", hash = "sha256:56200de4077d9d0791465aa9095a01d421861e405b5096955051deefd697d6f6"}, ] +[[package]] +name = "pbr" +version = "5.11.0" +description = "Python Build Reasonableness" +category = "dev" +optional = false +python-versions = ">=2.6" +files = [ + {file = "pbr-5.11.0-py2.py3-none-any.whl", hash = "sha256:db2317ff07c84c4c63648c9064a79fe9d9f5c7ce85a9099d4b6258b3db83225a"}, + {file = "pbr-5.11.0.tar.gz", hash = "sha256:b97bc6695b2aff02144133c2e7399d5885223d42b7912ffaec2ca3898e673bfe"}, +] + [[package]] name = "platformdirs" version = "2.6.0" @@ -300,6 +365,83 @@ files = [ [package.dependencies] pytest = ">=7.0" +[[package]] +name = "pyyaml" +version = "6.0" +description = "YAML parser and emitter for Python" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, + {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, + {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, + {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, + {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, + {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, + {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, + {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, + {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, + {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, + {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, + {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, + {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, + {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, + {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, + {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, + {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, + {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, + {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, + {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, +] + +[[package]] +name = "smmap" +version = "5.0.0" +description = "A pure Python implementation of a sliding window memory map manager" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"}, + {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"}, +] + +[[package]] +name = "stevedore" +version = "4.1.1" +description = "Manage dynamic plugins for Python applications" +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "stevedore-4.1.1-py3-none-any.whl", hash = "sha256:aa6436565c069b2946fe4ebff07f5041e0c8bf18c7376dd29edf80cf7d524e4e"}, + {file = "stevedore-4.1.1.tar.gz", hash = "sha256:7f8aeb6e3f90f96832c301bff21a7eb5eefbe894c88c506483d355565d88cc1a"}, +] + +[package.dependencies] +pbr = ">=2.0.0,<2.1.0 || >2.1.0" + [[package]] name = "typing-extensions" version = "4.4.0" @@ -315,4 +457,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "677bdf12d239f45492fa31759c18934b0d14feaa65d4998a4e5678f3b0d004c0" +content-hash = "2654e080872adfeb437fba8c17acac0975ffe70544c2e187d6e9a742cfe5d131" diff --git a/pyproject.toml b/pyproject.toml index 1b85e31..71433d7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,6 +26,7 @@ python = "^3.11" [tool.poetry.group.test.dependencies] +bandit = "^1.7.4" black = "^22.12.0" flake8 = "^6.0.0" mypy = "^0.991" From eefe3722547e3f8088971e9e7071a2f6b479008a Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Tue, 27 Dec 2022 01:47:49 -0500 Subject: [PATCH 33/39] additional linting --- .github/workflows/test.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 426dea3..b94f2a0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,10 +27,14 @@ jobs: - run: poetry install - - run: poetry run mypy --pretty --strict . + - run: poetry run black . - run: poetry run flake8 --ignore=E501 . + - run: poetry run mypy --pretty --strict . + + - run: poetry run bandit --recursive hb + test: strategy: fail-fast: false From 2745d333c4cc6d2553832bba95e08986cf9a10ce Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Tue, 27 Dec 2022 02:35:37 -0500 Subject: [PATCH 34/39] add flake8-pyproject and isort --- poetry.lock | 37 ++++++++++++++++++++++++++++++++++++- pyproject.toml | 2 ++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index f9420cf..fad8d03 100644 --- a/poetry.lock +++ b/poetry.lock @@ -120,6 +120,23 @@ mccabe = ">=0.7.0,<0.8.0" pycodestyle = ">=2.10.0,<2.11.0" pyflakes = ">=3.0.0,<3.1.0" +[[package]] +name = "flake8-pyproject" +version = "1.2.2" +description = "Flake8 plug-in loading the configuration from pyproject.toml" +category = "dev" +optional = false +python-versions = ">= 3.6" +files = [ + {file = "flake8_pyproject-1.2.2-py3-none-any.whl", hash = "sha256:52d412219e7db6227faa654675b1435947b11d49b453f3eced760f19bdd6f06a"}, +] + +[package.dependencies] +Flake8 = ">=5" + +[package.extras] +dev = ["pyTest", "pyTest-cov"] + [[package]] name = "gitdb" version = "4.0.10" @@ -162,6 +179,24 @@ files = [ {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, ] +[[package]] +name = "isort" +version = "5.11.4" +description = "A Python utility / library to sort Python imports." +category = "dev" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "isort-5.11.4-py3-none-any.whl", hash = "sha256:c033fd0edb91000a7f09527fe5c75321878f98322a77ddcc81adbd83724afb7b"}, + {file = "isort-5.11.4.tar.gz", hash = "sha256:6db30c5ded9815d813932c04c2f85a360bcdd35fed496f4d8f35495ef0a261b6"}, +] + +[package.extras] +colors = ["colorama (>=0.4.3,<0.5.0)"] +pipfile-deprecated-finder = ["pipreqs", "requirementslib"] +plugins = ["setuptools"] +requirements-deprecated-finder = ["pip-api", "pipreqs"] + [[package]] name = "mccabe" version = "0.7.0" @@ -457,4 +492,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "2654e080872adfeb437fba8c17acac0975ffe70544c2e187d6e9a742cfe5d131" +content-hash = "26bc122ac048d95099ba6aabfcdbecc29a47e2eadbcbb3356098a7ebef4198ff" diff --git a/pyproject.toml b/pyproject.toml index 71433d7..f3c94e4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,6 +29,8 @@ python = "^3.11" bandit = "^1.7.4" black = "^22.12.0" flake8 = "^6.0.0" +flake8-pyproject = "^1.2.2" +isort = "^5.11.4" mypy = "^0.991" pytest = "^7.2.0" pytest-subtests = "^0.9.0" From 01ad312be4e7d934c57d5170ab7031c12aac11bd Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Tue, 27 Dec 2022 02:36:19 -0500 Subject: [PATCH 35/39] move linter configs into pyproject.toml --- .github/workflows/test.yml | 6 ++++-- pyproject.toml | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b94f2a0..123fed9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,9 +29,11 @@ jobs: - run: poetry run black . - - run: poetry run flake8 --ignore=E501 . + - run: poetry run isort . - - run: poetry run mypy --pretty --strict . + - run: poetry run flake8 . + + - run: poetry run mypy . - run: poetry run bandit --recursive hb diff --git a/pyproject.toml b/pyproject.toml index f3c94e4..def4e60 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,3 +39,20 @@ pytest-subtests = "^0.9.0" [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" + + +[tool.black] +line-length = 999 + + +[tool.flake8] +extend-ignore = ["E501"] + + +[tool.isort] +profile = "black" + + +[tool.mypy] +pretty = true +strict = true From fd38c48143cb95e6e0cedc14959c9fdd0edd0ddd Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Wed, 28 Dec 2022 16:12:46 -0500 Subject: [PATCH 36/39] update lock --- poetry.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index fad8d03..454bb84 100644 --- a/poetry.lock +++ b/poetry.lock @@ -309,19 +309,19 @@ files = [ [[package]] name = "platformdirs" -version = "2.6.0" +version = "2.6.2" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "platformdirs-2.6.0-py3-none-any.whl", hash = "sha256:1a89a12377800c81983db6be069ec068eee989748799b946cce2a6e80dcc54ca"}, - {file = "platformdirs-2.6.0.tar.gz", hash = "sha256:b46ffafa316e6b83b47489d240ce17173f123a9b9c83282141c3daf26ad9ac2e"}, + {file = "platformdirs-2.6.2-py3-none-any.whl", hash = "sha256:83c8f6d04389165de7c9b6f0c682439697887bca0aa2f1c87ef1826be3584490"}, + {file = "platformdirs-2.6.2.tar.gz", hash = "sha256:e1fea1fe471b9ff8332e229df3cb7de4f53eeea4998d3b6bfff542115e998bd2"}, ] [package.extras] -docs = ["furo (>=2022.9.29)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.4)"] -test = ["appdirs (==1.4.4)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] +docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.5)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] [[package]] name = "pluggy" From 19e8f5e22e6b475a2bcde4f0a11f04609041138e Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Wed, 28 Dec 2022 16:34:29 -0500 Subject: [PATCH 37/39] add property to return list of supported algos --- hb/hb.py | 3 +++ tests/test_hb.py | 18 ++++++------------ 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/hb/hb.py b/hb/hb.py index 8b89a93..ed01ffc 100644 --- a/hb/hb.py +++ b/hb/hb.py @@ -108,3 +108,6 @@ def scan(path: str | Path, stdout_only: bool = True) -> None | list[str]: if not stdout_only: results.append(result) return None if stdout_only else results + + +algorithms_guaranteed = sorted(hashlib.algorithms_guaranteed | {"adler32", "crc32"}) diff --git a/tests/test_hb.py b/tests/test_hb.py index 55ab7dd..e6d8ab9 100644 --- a/tests/test_hb.py +++ b/tests/test_hb.py @@ -40,12 +40,6 @@ def use_stdlib(algo, path): return hexdigest -@pytest.fixture -def guaranteed(): - """Supported algos.""" - return hashlib.algorithms_guaranteed | {"adler32", "crc32"} - - @pytest.fixture def rand_file(): """Generate a random ~1MB file.""" @@ -59,10 +53,10 @@ def rand_file(): @pytest.fixture -def rand_digestfile(guaranteed, rand_file): +def rand_digestfile(rand_file): """Generate a file of digests.""" temp = tempfile.NamedTemporaryFile(mode="w", delete=False, encoding="utf-8") - for algo in guaranteed: + for algo in hb.algorithms_guaranteed: print(hb.compute(algo, rand_file), file=temp) temp.close() yield temp.name @@ -70,18 +64,18 @@ def rand_digestfile(guaranteed, rand_file): assert not os.path.exists(temp.name) -def test_compute(subtests, guaranteed, rand_file): +def test_compute(subtests, rand_file): """Compare with direct usage of hashlib and zlib.""" - for algo in guaranteed: + for algo in hb.algorithms_guaranteed: with subtests.test(algo=algo): with_hb = HashBrown(algo, rand_file).compute() with_stdlib = use_stdlib(algo, rand_file) assert with_hb == with_stdlib -def test_pprint(subtests, guaranteed, rand_file): +def test_pprint(subtests, rand_file): """Check pretty print output.""" - for algo in guaranteed: + for algo in hb.algorithms_guaranteed: with subtests.test(algo=algo): with_hb = hb.compute(algo, rand_file) with_stdlib = f"{use_stdlib(algo, rand_file)} {algo} {rand_file}" From 13ad7956800fe2c092a51315f7b31747e65f911f Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Wed, 28 Dec 2022 17:05:42 -0500 Subject: [PATCH 38/39] update readme --- README.md | 64 +++++++++++++++++++++---------------------------------- 1 file changed, 24 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 5fd6081..0e13a29 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@ # Hash Brown -[![CircleCI](https://circleci.com/gh/chingc/Hash-Brown.svg?style=shield)](https://circleci.com/gh/chingc/workflows/Hash-Brown) [![codecov](https://codecov.io/gh/chingc/Hash-Brown/branch/master/graph/badge.svg)](https://codecov.io/gh/chingc/Hash-Brown) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE) [![PyPI](https://img.shields.io/pypi/v/hb.svg)](https://pypi.org/project/hb/) - -A simple command-line utility for calculating checksums. +A convenient interface for hashlib and zlib. ## Install @@ -12,51 +10,37 @@ pip install hb ## Usage -Calculate the sha1 of a file: - -``` -$ hb -a sha1 hello.txt -sha1 (hello.txt) = 493a253abf93d705d67edeb463134a5c8752fc9d ``` +>>> from hb import hb -Check to see if file matches a given checksum: +>>> hb.algorithms_guaranteed +['adler32', 'blake2b', 'blake2s', 'crc32', 'md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512', 'sha512', 'shake_128', 'shake_256'] -``` -$ hb -a md5 hello.txt -g 77060c267470021a97392b815138733e -md5 (hello.txt) = 77060c267470021a97392b815138733e OK +>>> hb.compute('sha1', 'hello.txt') +'fab3fff31b58f5c50ce0213407eb3e047cf2a8dc sha1 hello.txt' -$ hb -a md5 hello.txt -g 0123456789abcdef -md5 (hello.txt) = 0123456789abcdef BAD +>>> hb.scan('hexdigests.txt') +OK crc32 hello.txt +OK md5 world.txt +OK sha1 image.jpg +OK sha256 video.mp4 ``` -Checksums can be read from a file: +From the command line ``` -$ hb -c checksums.txt -sha512 (hello.txt) = 493a253abf93d705d67edeb463134a5c8752fc9d OK -sha512 (world.txt) = 683e4ee04e75e71a6dca42807001f00be1fcb2a3 OK -sha512 (image.jpg) = f3a53e6c2743645f08faedadd7a2c57cbc38632f OK -sha512 (video.mp4) = 03ba9191fc4cd74f218df58542643fbc07dca532 OK -``` +$ python -m hb -c sha1 hello.txt +fab3fff31b58f5c50ce0213407eb3e047cf2a8dc sha1 hello.txt -Hash Brown outputs its results in BSD style. The checksum files are also BSD style. +$ cat hexdigests.txt +71d4f5e9 crc32 hello.txt +039c6a18baa8d77474b61fac86aeb7c7 md5 world.txt +ff0023686cd30938c2eade9b08e1507747d7fbf6 sha1 image.jpg +006e7bcdbdc2b77636b6ca695b7b68227b30c10130106b990f20d3ccace1cb9b sha256 video.mp4 -All files are read in binary mode. - -Globbing and recursive globbing are supported via `*` and `**` respectively. - -Dotfiles are not included when globbing and need to be specified explicitly. - -## Options - -``` --a, --algorithm [blake2b|blake2s|md5|sha1|sha224|sha256|sha384|sha512|adler32|crc32] --c, --check Read checksums from a file. --g, --given TEXT See if the given checksum `TEXT` matches the - computed checksum. (use with -a) --p, --parallel Process files in parallel. --q, --quiet Hide results that are OK. (use with -c) --t, --timer Display elapsed time in seconds. ---version Show the version and exit. --h, --help Show this message and exit. +$ python -m hb -s hexdigests.txt +OK crc32 hello.txt +OK md5 world.txt +OK sha1 image.jpg +OK sha256 video.mp4 ``` From 2b323e8fc4ab961fcfeb314bcb28775f38366991 Mon Sep 17 00:00:00 2001 From: Ching Chow Date: Wed, 28 Dec 2022 17:06:02 -0500 Subject: [PATCH 39/39] add scanning option --- hb/__main__.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/hb/__main__.py b/hb/__main__.py index e6e3ae6..209d795 100644 --- a/hb/__main__.py +++ b/hb/__main__.py @@ -3,8 +3,13 @@ from hb import hb - for path in sys.argv[2:]: - try: - print(hb.compute(sys.argv[1], path)) - except hb.NotAFileError as e: - print(e, file=sys.stderr) + match sys.argv[1]: + case "-c": + for path in sys.argv[3:]: + try: + print(hb.compute(sys.argv[2], path)) + except hb.NotAFileError as e: + print(e, file=sys.stderr) + case "-s": + for path in sys.argv[2:]: + hb.scan(path)