From 578a0b24da380ecdcfc84e7c6dddab9298c1dbcc Mon Sep 17 00:00:00 2001 From: fabianhe <39628987+fabianhe@users.noreply.github.com> Date: Wed, 14 Jul 2021 16:54:44 +0200 Subject: [PATCH 01/19] Bump version --- pyproject.toml | 2 +- pyrepositoryminer/__init__.py | 2 +- tests/test_pyrepositoryminer.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 4c0140e..d94c316 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pyrepositoryminer" -version = "0.7.0" +version = "0.8.0" description = "Efficient Repository Mining in Python" license = "GPL-3.0-or-later" authors = ["Fabian Heseding <39628987+fabianhe@users.noreply.github.com>"] diff --git a/pyrepositoryminer/__init__.py b/pyrepositoryminer/__init__.py index 748ddf6..b2ff1db 100644 --- a/pyrepositoryminer/__init__.py +++ b/pyrepositoryminer/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.7.0" +__version__ = "0.8.0" from typer import Typer diff --git a/tests/test_pyrepositoryminer.py b/tests/test_pyrepositoryminer.py index 14eda61..f854cc1 100644 --- a/tests/test_pyrepositoryminer.py +++ b/tests/test_pyrepositoryminer.py @@ -2,4 +2,4 @@ def test_version() -> None: - assert __version__ == "0.7.0" + assert __version__ == "0.8.0" From 2471a72dc7d778f33a4353ddd666be35da87e65c Mon Sep 17 00:00:00 2001 From: fabianhe <39628987+fabianhe@users.noreply.github.com> Date: Wed, 14 Jul 2021 16:55:38 +0200 Subject: [PATCH 02/19] Update dependencies --- poetry.lock | 65 ++++++++++++++++++++++++++++++++++++-------------- pyproject.toml | 2 +- 2 files changed, 48 insertions(+), 19 deletions(-) diff --git a/poetry.lock b/poetry.lock index fcd9c54..f3b6e20 100644 --- a/poetry.lock +++ b/poetry.lock @@ -28,6 +28,18 @@ docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"] tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"] +[[package]] +name = "backports.entry-points-selectable" +version = "1.1.0" +description = "Compatibility shim providing selectable entry points for older implementations" +category = "dev" +optional = false +python-versions = ">=2.7" + +[package.extras] +docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] +testing = ["pytest (>=4.6)", "pytest-flake8", "pytest-cov", "pytest-black (>=0.3.7)", "pytest-mypy", "pytest-checkdocs (>=2.4)", "pytest-enabler (>=1.0.1)"] + [[package]] name = "black" version = "21.6b0" @@ -254,6 +266,14 @@ category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +[[package]] +name = "platformdirs" +version = "2.0.2" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + [[package]] name = "pluggy" version = "0.13.1" @@ -459,7 +479,7 @@ python-versions = "*" [[package]] name = "uvloop" -version = "0.15.2" +version = "0.15.3" description = "Fast implementation of asyncio event loop on top of libuv" category = "main" optional = false @@ -472,16 +492,17 @@ test = ["aiohttp", "flake8 (>=3.8.4,<3.9.0)", "psutil", "pycodestyle (>=2.6.0,<2 [[package]] name = "virtualenv" -version = "20.4.7" +version = "20.5.0" description = "Virtual Python Environment builder" category = "dev" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [package.dependencies] -appdirs = ">=1.4.3,<2" +"backports.entry-points-selectable" = ">=1.0.4" distlib = ">=0.3.1,<1" filelock = ">=3.0.0,<4" +platformdirs = ">=2,<3" six = ">=1.9.0,<2" [package.extras] @@ -510,8 +531,8 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytes [metadata] lock-version = "1.1" -python-versions = "^3.8" -content-hash = "f631427746d948fad31e0aa17fab0fad991a50fdba9a38c794002a880223d231" +python-versions = "^3.9" +content-hash = "db93c9da9b03e1bc43517fcf2e05959f3aaf7b0daf0d42465369a162d93649ae" [metadata.files] appdirs = [ @@ -526,6 +547,10 @@ attrs = [ {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"}, {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"}, ] +"backports.entry-points-selectable" = [ + {file = "backports.entry_points_selectable-1.1.0-py2.py3-none-any.whl", hash = "sha256:a6d9a871cde5e15b4c4a53e3d43ba890cc6861ec1332c9c2428c92f977192acc"}, + {file = "backports.entry_points_selectable-1.1.0.tar.gz", hash = "sha256:988468260ec1c196dab6ae1149260e2f5472c9110334e5d51adcb77867361f6a"}, +] black = [ {file = "black-21.6b0-py3-none-any.whl", hash = "sha256:dfb8c5a069012b2ab1e972e7b908f5fb42b6bbabcba0a788b86dc05067c7d9c7"}, {file = "black-21.6b0.tar.gz", hash = "sha256:dc132348a88d103016726fe360cb9ede02cecf99b76e3660ce6c596be132ce04"}, @@ -667,6 +692,10 @@ pathspec = [ {file = "pathspec-0.8.1-py2.py3-none-any.whl", hash = "sha256:aa0cb481c4041bf52ffa7b0d8fa6cd3e88a2ca4879c533c9153882ee2556790d"}, {file = "pathspec-0.8.1.tar.gz", hash = "sha256:86379d6b86d75816baba717e64b1a3a3469deb93bb76d613c9ce79edc5cb68fd"}, ] +platformdirs = [ + {file = "platformdirs-2.0.2-py2.py3-none-any.whl", hash = "sha256:0b9547541f599d3d242078ae60b927b3e453f0ad52f58b4d4bc3be86aed3ec41"}, + {file = "platformdirs-2.0.2.tar.gz", hash = "sha256:3b00d081227d9037bbbca521a5787796b5ef5000faea1e43fd76f1d44b06fcfa"}, +] pluggy = [ {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, @@ -858,20 +887,20 @@ typing-extensions = [ {file = "typing_extensions-3.10.0.0.tar.gz", hash = "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342"}, ] uvloop = [ - {file = "uvloop-0.15.2-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:19fa1d56c91341318ac5d417e7b61c56e9a41183946cc70c411341173de02c69"}, - {file = "uvloop-0.15.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:e5e5f855c9bf483ee6cd1eb9a179b740de80cb0ae2988e3fa22309b78e2ea0e7"}, - {file = "uvloop-0.15.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:42eda9f525a208fbc4f7cecd00fa15c57cc57646c76632b3ba2fe005004f051d"}, - {file = "uvloop-0.15.2-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:90e56f17755e41b425ad19a08c41dc358fa7bf1226c0f8e54d4d02d556f7af7c"}, - {file = "uvloop-0.15.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:7ae39b11a5f4cec1432d706c21ecc62f9e04d116883178b09671aa29c46f7a47"}, - {file = "uvloop-0.15.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:b45218c99795803fb8bdbc9435ff7f54e3a591b44cd4c121b02fa83affb61c7c"}, - {file = "uvloop-0.15.2-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:114543c84e95df1b4ff546e6e3a27521580466a30127f12172a3278172ad68bc"}, - {file = "uvloop-0.15.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:44cac8575bf168601424302045234d74e3561fbdbac39b2b54cc1d1d00b70760"}, - {file = "uvloop-0.15.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:6de130d0cb78985a5d080e323b86c5ecaf3af82f4890492c05981707852f983c"}, - {file = "uvloop-0.15.2.tar.gz", hash = "sha256:2bb0624a8a70834e54dde8feed62ed63b50bad7a1265c40d6403a2ac447bce01"}, + {file = "uvloop-0.15.3-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:e71fb9038bfcd7646ca126c5ef19b17e48d4af9e838b2bcfda7a9f55a6552a32"}, + {file = "uvloop-0.15.3-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7522df4e45e4f25b50adbbbeb5bb9847495c438a628177099d2721f2751ff825"}, + {file = "uvloop-0.15.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae2b325c0f6d748027f7463077e457006b4fdb35a8788f01754aadba825285ee"}, + {file = "uvloop-0.15.3-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:0de811931e90ae2da9e19ce70ffad73047ab0c1dba7c6e74f9ae1a3aabeb89bd"}, + {file = "uvloop-0.15.3-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7f4b8a905df909a407c5791fb582f6c03b0d3b491ecdc1cdceaefbc9bf9e08f6"}, + {file = "uvloop-0.15.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d8ffe44ae709f839c54bacf14ed283f41bee90430c3b398e521e10f8d117b3a"}, + {file = "uvloop-0.15.3-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:63a3288abbc9c8ee979d7e34c34e780b2fbab3e7e53d00b6c80271119f277399"}, + {file = "uvloop-0.15.3-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5cda65fc60a645470b8525ce014516b120b7057b576fa876cdfdd5e60ab1efbb"}, + {file = "uvloop-0.15.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ff05116ede1ebdd81802df339e5b1d4cab1dfbd99295bf27e90b4cec64d70e9"}, + {file = "uvloop-0.15.3.tar.gz", hash = "sha256:905f0adb0c09c9f44222ee02f6b96fd88b493478fffb7a345287f9444e926030"}, ] virtualenv = [ - {file = "virtualenv-20.4.7-py2.py3-none-any.whl", hash = "sha256:2b0126166ea7c9c3661f5b8e06773d28f83322de7a3ff7d06f0aed18c9de6a76"}, - {file = "virtualenv-20.4.7.tar.gz", hash = "sha256:14fdf849f80dbb29a4eb6caa9875d476ee2a5cf76a5f5415fa2f1606010ab467"}, + {file = "virtualenv-20.5.0-py2.py3-none-any.whl", hash = "sha256:b7afa7f32abbf7dd4c24269a596cfbb0a422bb83c47215a785a7bf607cb88e1b"}, + {file = "virtualenv-20.5.0.tar.gz", hash = "sha256:6b0e3eeb6cb081c9c81ec85633785e29edcdf6ff271d70e0d1e2bd616495c08c"}, ] wcwidth = [ {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, diff --git a/pyproject.toml b/pyproject.toml index d94c316..88abc5d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ documentation = "https://github.com/fabianhe/pyrepositoryminer/blob/master/DOCS. pyrepositoryminer = "pyrepositoryminer:app" [tool.poetry.dependencies] -python = "^3.8" +python = "^3.9" pygit2 = "^1.5.0" typer = {extras = ["all"], version = "^0.3.2"} radon = "^4.5.0" From 8920e82e716b0247d69bf01185a2f45388c828d7 Mon Sep 17 00:00:00 2001 From: fabianhe <39628987+fabianhe@users.noreply.github.com> Date: Fri, 16 Jul 2021 13:30:08 +0200 Subject: [PATCH 03/19] Add pylint --- .pre-commit-config.yaml | 8 ++ poetry.lock | 80 +++++++++++++++- pyproject.toml | 1 + pyrepositoryminer/analyze.py | 1 + pyrepositoryminer/commands/analyze.py | 13 ++- pyrepositoryminer/commands/commits.py | 7 +- .../metrics/diffdir/difftokei.py | 8 +- pyrepositoryminer/metrics/diffdir/main.py | 8 +- pyrepositoryminer/metrics/diffdir/seerene.py | 93 +++++++++---------- pyrepositoryminer/metrics/dir/main.py | 8 +- pyrepositoryminer/metrics/dir/tokei.py | 8 +- pyrepositoryminer/metrics/main.py | 3 +- .../metrics/nativeblob/complexity.py | 10 +- .../metrics/nativeblob/halstead.py | 12 +-- .../metrics/nativeblob/linecount.py | 10 +- .../metrics/nativeblob/linelength.py | 10 +- .../metrics/nativeblob/maintainability.py | 10 +- .../metrics/nativeblob/nesting.py | 10 +- .../metrics/nativeblob/pylinecount.py | 10 +- pyrepositoryminer/metrics/nativeblob/raw.py | 10 +- .../metrics/nativetree/blobcount.py | 4 +- .../metrics/nativetree/cacherate.py | 4 +- pyrepositoryminer/metrics/nativetree/loc.py | 4 +- .../metrics/nativetree/touchedlines.py | 8 +- pyrepositoryminer/pobjects.py | 6 +- setup.cfg | 7 +- 26 files changed, 227 insertions(+), 126 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d7d8721..1a6f976 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,6 +22,14 @@ repos: hooks: - id: flake8 additional_dependencies: ["flake8-absolute-import"] + - repo: local + hooks: + - id: pylint + name: pylint + entry: pylint + language: system + types: [python] + require_serial: true - repo: https://github.com/pre-commit/mirrors-mypy rev: v0.812 hooks: diff --git a/poetry.lock b/poetry.lock index f3b6e20..e3e1189 100644 --- a/poetry.lock +++ b/poetry.lock @@ -6,6 +6,18 @@ category = "dev" optional = false python-versions = "*" +[[package]] +name = "astroid" +version = "2.6.2" +description = "An abstract syntax tree for Python with inference support." +category = "dev" +optional = false +python-versions = "~=3.6" + +[package.dependencies] +lazy-object-proxy = ">=1.4.0" +wrapt = ">=1.11,<1.13" + [[package]] name = "atomicwrites" version = "1.4.0" @@ -185,6 +197,14 @@ requirements_deprecated_finder = ["pipreqs", "pip-api"] colors = ["colorama (>=0.4.3,<0.5.0)"] plugins = ["setuptools"] +[[package]] +name = "lazy-object-proxy" +version = "1.6.0" +description = "A fast and thorough lazy object proxy." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" + [[package]] name = "mando" version = "0.6.4" @@ -344,6 +364,21 @@ python-versions = "*" [package.dependencies] cffi = ">=1.4.0" +[[package]] +name = "pylint" +version = "2.9.3" +description = "python code static checker" +category = "dev" +optional = false +python-versions = "~=3.6" + +[package.dependencies] +astroid = ">=2.6.2,<2.7" +colorama = {version = "*", markers = "sys_platform == \"win32\""} +isort = ">=4.2.5,<6" +mccabe = ">=0.6,<0.7" +toml = ">=0.7.1" + [[package]] name = "pyparsing" version = "2.4.7" @@ -517,6 +552,14 @@ category = "dev" optional = false python-versions = "*" +[[package]] +name = "wrapt" +version = "1.12.1" +description = "Module for decorators, wrappers and monkey patching." +category = "dev" +optional = false +python-versions = "*" + [[package]] name = "zipp" version = "3.5.0" @@ -532,13 +575,17 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytes [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "db93c9da9b03e1bc43517fcf2e05959f3aaf7b0daf0d42465369a162d93649ae" +content-hash = "65c9408bb176660504dff5b1042eb8d261d8a0bc740e7cb18409ce8ded8472be" [metadata.files] appdirs = [ {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, ] +astroid = [ + {file = "astroid-2.6.2-py3-none-any.whl", hash = "sha256:606b2911d10c3dcf35e58d2ee5c97360e8477d7b9f3efc3f24811c93e6fc2cd9"}, + {file = "astroid-2.6.2.tar.gz", hash = "sha256:38b95085e9d92e2ca06cf8b35c12a74fa81da395a6f9e65803742e6509c05892"}, +] atomicwrites = [ {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, @@ -640,6 +687,30 @@ isort = [ {file = "isort-5.9.2-py3-none-any.whl", hash = "sha256:eed17b53c3e7912425579853d078a0832820f023191561fcee9d7cae424e0813"}, {file = "isort-5.9.2.tar.gz", hash = "sha256:f65ce5bd4cbc6abdfbe29afc2f0245538ab358c14590912df638033f157d555e"}, ] +lazy-object-proxy = [ + {file = "lazy-object-proxy-1.6.0.tar.gz", hash = "sha256:489000d368377571c6f982fba6497f2aa13c6d1facc40660963da62f5c379726"}, + {file = "lazy_object_proxy-1.6.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:c6938967f8528b3668622a9ed3b31d145fab161a32f5891ea7b84f6b790be05b"}, + {file = "lazy_object_proxy-1.6.0-cp27-cp27m-win32.whl", hash = "sha256:ebfd274dcd5133e0afae738e6d9da4323c3eb021b3e13052d8cbd0e457b1256e"}, + {file = "lazy_object_proxy-1.6.0-cp27-cp27m-win_amd64.whl", hash = "sha256:ed361bb83436f117f9917d282a456f9e5009ea12fd6de8742d1a4752c3017e93"}, + {file = "lazy_object_proxy-1.6.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d900d949b707778696fdf01036f58c9876a0d8bfe116e8d220cfd4b15f14e741"}, + {file = "lazy_object_proxy-1.6.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5743a5ab42ae40caa8421b320ebf3a998f89c85cdc8376d6b2e00bd12bd1b587"}, + {file = "lazy_object_proxy-1.6.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:bf34e368e8dd976423396555078def5cfc3039ebc6fc06d1ae2c5a65eebbcde4"}, + {file = "lazy_object_proxy-1.6.0-cp36-cp36m-win32.whl", hash = "sha256:b579f8acbf2bdd9ea200b1d5dea36abd93cabf56cf626ab9c744a432e15c815f"}, + {file = "lazy_object_proxy-1.6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:4f60460e9f1eb632584c9685bccea152f4ac2130e299784dbaf9fae9f49891b3"}, + {file = "lazy_object_proxy-1.6.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d7124f52f3bd259f510651450e18e0fd081ed82f3c08541dffc7b94b883aa981"}, + {file = "lazy_object_proxy-1.6.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:22ddd618cefe54305df49e4c069fa65715be4ad0e78e8d252a33debf00f6ede2"}, + {file = "lazy_object_proxy-1.6.0-cp37-cp37m-win32.whl", hash = "sha256:9d397bf41caad3f489e10774667310d73cb9c4258e9aed94b9ec734b34b495fd"}, + {file = "lazy_object_proxy-1.6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:24a5045889cc2729033b3e604d496c2b6f588c754f7a62027ad4437a7ecc4837"}, + {file = "lazy_object_proxy-1.6.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:17e0967ba374fc24141738c69736da90e94419338fd4c7c7bef01ee26b339653"}, + {file = "lazy_object_proxy-1.6.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:410283732af311b51b837894fa2f24f2c0039aa7f220135192b38fcc42bd43d3"}, + {file = "lazy_object_proxy-1.6.0-cp38-cp38-win32.whl", hash = "sha256:85fb7608121fd5621cc4377a8961d0b32ccf84a7285b4f1d21988b2eae2868e8"}, + {file = "lazy_object_proxy-1.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:d1c2676e3d840852a2de7c7d5d76407c772927addff8d742b9808fe0afccebdf"}, + {file = "lazy_object_proxy-1.6.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:b865b01a2e7f96db0c5d12cfea590f98d8c5ba64ad222300d93ce6ff9138bcad"}, + {file = "lazy_object_proxy-1.6.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:4732c765372bd78a2d6b2150a6e99d00a78ec963375f236979c0626b97ed8e43"}, + {file = "lazy_object_proxy-1.6.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:9698110e36e2df951c7c36b6729e96429c9c32b3331989ef19976592c5f3c77a"}, + {file = "lazy_object_proxy-1.6.0-cp39-cp39-win32.whl", hash = "sha256:1fee665d2638491f4d6e55bd483e15ef21f6c8c2095f235fef72601021e64f61"}, + {file = "lazy_object_proxy-1.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:f5144c75445ae3ca2057faac03fda5a902eff196702b0a24daf1d6ce0650514b"}, +] mando = [ {file = "mando-0.6.4-py2.py3-none-any.whl", hash = "sha256:4ce09faec7e5192ffc3c57830e26acba0fd6cd11e1ee81af0d4df0657463bd1c"}, {file = "mando-0.6.4.tar.gz", hash = "sha256:79feb19dc0f097daa64a1243db578e7674909b75f88ac2220f1c065c10a0d960"}, @@ -743,6 +814,10 @@ pygit2 = [ {file = "pygit2-1.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:f90775afb11f69376e2af21ab56fcfbb52f6bc84117059ddf0355f81e5e36352"}, {file = "pygit2-1.6.1.tar.gz", hash = "sha256:c3303776f774d3e0115c1c4f6e1fc35470d15f113a7ae9401a0b90acfa1661ac"}, ] +pylint = [ + {file = "pylint-2.9.3-py3-none-any.whl", hash = "sha256:5d46330e6b8886c31b5e3aba5ff48c10f4aa5e76cbf9002c6544306221e63fbc"}, + {file = "pylint-2.9.3.tar.gz", hash = "sha256:23a1dc8b30459d78e9ff25942c61bb936108ccbe29dd9e71c01dc8274961709a"}, +] pyparsing = [ {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, @@ -906,6 +981,9 @@ wcwidth = [ {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, ] +wrapt = [ + {file = "wrapt-1.12.1.tar.gz", hash = "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"}, +] zipp = [ {file = "zipp-3.5.0-py3-none-any.whl", hash = "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3"}, {file = "zipp-3.5.0.tar.gz", hash = "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"}, diff --git a/pyproject.toml b/pyproject.toml index 88abc5d..752408a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,6 +27,7 @@ flake8 = "^3.9.1" isort = "^5.8.0" pre-commit = "^2.12.1" typer-cli = "^0.0.11" +pylint = "^2.9.3" [build-system] requires = ["poetry-core>=1.0.0"] diff --git a/pyrepositoryminer/analyze.py b/pyrepositoryminer/analyze.py index 35c2961..e3b16c3 100644 --- a/pyrepositoryminer/analyze.py +++ b/pyrepositoryminer/analyze.py @@ -32,6 +32,7 @@ class InitArgs(NamedTuple): custom_metrics: Tuple[Any, ...] # TODO make this a metric abc +# pylint: disable=global-statement repo: Repository native_blob_metrics: Tuple[Any, ...] native_blob_visitor: NativeBlobVisitor diff --git a/pyrepositoryminer/commands/analyze.py b/pyrepositoryminer/commands/analyze.py index f694668..e39e052 100644 --- a/pyrepositoryminer/commands/analyze.py +++ b/pyrepositoryminer/commands/analyze.py @@ -34,12 +34,12 @@ def import_metric(import_str: str): # type: ignore # TODO make this a metric a if e.name != module_str: raise e from None echo(f'Could not import module "{module_str}"') - raise Abort() + raise Abort() from e try: instance = reduce(getattr, (module, *attrs_str.split("."))) # type: ignore - except AttributeError: + except AttributeError as e: print(f'Attribute "{attrs_str}" not found in module "{module_str}"') - raise Abort() + raise Abort() from e if not isclass(instance): print(f'Instance "{instance}" must be a class') raise Abort() @@ -55,7 +55,7 @@ def analyze( metrics: Optional[List[AvailableMetrics]] = Argument(None, case_sensitive=False), commits: Optional[FileText] = Option( None, - help="The newline-separated input file of commit ids. Commit ids are read from stdin if this is not passed.", # noqa: E501 + help="The newline-separated input file of commit ids. Commit ids are read from stdin if this is not passed.", # pylint: disable=line-too-long ), custom_metrics: List[str] = Option([]), workers: int = 1, @@ -64,7 +64,10 @@ def analyze( Either provide the commit ids to analyze on stdin or as a file argument.""" metrics = metrics if metrics else [] - ids = (id.strip() for id in (commits if commits else stdin)) + ids = ( + id.strip() + for id in (commits if commits else stdin) # pylint: disable=superfluous-parens + ) with Pool( max(workers, 1), initialize, diff --git a/pyrepositoryminer/commands/commits.py b/pyrepositoryminer/commands/commits.py index 13d7b1a..df12571 100644 --- a/pyrepositoryminer/commands/commits.py +++ b/pyrepositoryminer/commands/commits.py @@ -22,6 +22,7 @@ class Sort(str, Enum): def __init__(self, name: str) -> None: self.sort_name = name + super().__init__() @property def flag(self): # type: ignore @@ -67,7 +68,7 @@ def commits( dir_okay=False, writable=False, readable=True, - help="The newline-separated input file of branches to pull the commits from. Branches are read from stdin if this is not passed.", # noqa: E501 + help="The newline-separated input file of branches to pull the commits from. Branches are read from stdin if this is not passed.", # pylint: disable=line-too-long ), simplify_first_parent: bool = True, drop_duplicates: bool = True, @@ -77,11 +78,11 @@ def commits( ) -> None: """Get the commit ids of a repository. - Either provide the branches to get the commit ids from on stdin or as a file argument.""" # noqa: E501 + Either provide the branches to get the commit ids from on stdin or as a file argument.""" # pylint: disable=line-too-long branch_names: Iterable[str] if branches != Path("-"): with open(branches) as f: - branch_names = [line for line in f] + branch_names = list(f) else: branch_names = (line for line in stdin) branch_names = (branch.strip() for branch in branch_names) diff --git a/pyrepositoryminer/metrics/diffdir/difftokei.py b/pyrepositoryminer/metrics/diffdir/difftokei.py index 8dc5fc9..e9d6602 100644 --- a/pyrepositoryminer/metrics/diffdir/difftokei.py +++ b/pyrepositoryminer/metrics/diffdir/difftokei.py @@ -14,9 +14,9 @@ def descend_tree(tree: Tree, obj_name: str) -> str: class DiffTokei(DiffDirMetric): - async def analyze(self, dir_tup: DirMetricInput) -> Iterable[Metric]: + async def analyze(self, tup: DirMetricInput) -> Iterable[Metric]: p = await create_subprocess_exec( - "tokei", "--output", "json", dir_tup.path, stdout=PIPE + "tokei", "--output", "json", tup.path, stdout=PIPE ) stdout, _ = await p.communicate() data = loads(bytes(stdout).decode("utf-8")) @@ -31,8 +31,8 @@ async def analyze(self, dir_tup: DirMetricInput) -> Iterable[Metric]: }, False, ObjectIdentifier( - descend_tree(dir_tup.tree, report["name"][len(dir_tup.path) + 1 :]), - report["name"][len(dir_tup.path) + 1 :], + descend_tree(tup.tree, report["name"][len(tup.path) + 1 :]), + report["name"][len(tup.path) + 1 :], ), ) for category_name, reports in data["Total"]["children"].items() diff --git a/pyrepositoryminer/metrics/diffdir/main.py b/pyrepositoryminer/metrics/diffdir/main.py index e788a52..cfe2d10 100644 --- a/pyrepositoryminer/metrics/diffdir/main.py +++ b/pyrepositoryminer/metrics/diffdir/main.py @@ -27,11 +27,14 @@ def __init__(self, repository: Repository, base_dir: Optional[str] = None) -> No super().__init__() self.repository = repository self.base_dir = base_dir + self.tempdir: Optional[TemporaryDirectory[str]] = None def __call__(self, visitable_object: Object) -> Optional[DirMetricInput]: if not isinstance(visitable_object, Commit): return None - self.tempdir: TemporaryDirectory[str] = TemporaryDirectory(dir=self.base_dir) + self.tempdir = TemporaryDirectory( # pylint: disable=consider-using-with + dir=self.base_dir + ) self.repository.checkout_tree( visitable_object.tree.obj, directory=self.tempdir.name, @@ -43,7 +46,8 @@ def __call__(self, visitable_object: Object) -> Optional[DirMetricInput]: return DirMetricInput(is_cached, self.tempdir.name, visitable_object.tree) def close(self) -> None: - self.tempdir.cleanup() + if self.tempdir is not None: + self.tempdir.cleanup() class DiffDirMetric(BaseMetric[DirMetricInput], ABC): diff --git a/pyrepositoryminer/metrics/diffdir/seerene.py b/pyrepositoryminer/metrics/diffdir/seerene.py index aefe089..f933a13 100644 --- a/pyrepositoryminer/metrics/diffdir/seerene.py +++ b/pyrepositoryminer/metrics/diffdir/seerene.py @@ -20,7 +20,7 @@ def descend_tree(tree: Tree, obj_name: str) -> str: class Seerene(DiffDirMetric): - async def analyze(self, dir_tup: DirMetricInput) -> Iterable[Metric]: + async def analyze(self, tup: DirMetricInput) -> Iterable[Metric]: # assuming 'init' and 'import' have been called if (executables := getenv("EXECUTABLES")) is None or ( token := getenv("LOCALANALYZER_TOKEN") @@ -28,54 +28,53 @@ async def analyze(self, dir_tup: DirMetricInput) -> Iterable[Metric]: return [] localanalyzer = (Path(executables) / "localanalyzer-v2.16").resolve() p = await create_subprocess_exec( - localanalyzer, "init", "--token", token, cwd=dir_tup.path, stdout=PIPE + localanalyzer, "init", "--token", token, cwd=tup.path, stdout=PIPE ) await p.communicate() - f = NamedTemporaryFile("w") - log = NamedTemporaryFile("w") - dump( - { - "author-anonymization": False, - "components": { - "code-log-export": { - ".": { - "export-codedir-path": ".", - "export-logfile-path": log.name, - "prefix": "", - "vcs-type": "git", - } - } - }, - "type": "seerene-application-import-configuration", - "version": "1", - }, - f, - sort_keys=True, - indent=4, - ) - f.seek(0) - p = await create_subprocess_exec( - localanalyzer, "import", f.name, cwd=dir_tup.path, stdout=PIPE - ) - await p.communicate() - f.close() - p = await create_subprocess_exec( - localanalyzer, "analyze", cwd=dir_tup.path, stdout=PIPE - ) - await p.communicate() - log.close() + with NamedTemporaryFile("w") as log: + with NamedTemporaryFile("w") as f: + dump( + { + "author-anonymization": False, + "components": { + "code-log-export": { + ".": { + "export-codedir-path": ".", + "export-logfile-path": log.name, + "prefix": "", + "vcs-type": "git", + } + } + }, + "type": "seerene-application-import-configuration", + "version": "1", + }, + f, + sort_keys=True, + indent=4, + ) + f.seek(0) + p = await create_subprocess_exec( + localanalyzer, "import", f.name, cwd=tup.path, stdout=PIPE + ) + await p.communicate() + p = await create_subprocess_exec( + localanalyzer, "analyze", cwd=tup.path, stdout=PIPE + ) + await p.communicate() result = [] - with ZipFile(list((Path(dir_tup.path) / "pending").glob("*.zip"))[0]) as myzip: - with TextIOWrapper(myzip.open("m_main.csv")) as f: - reader = DictReader(f, delimiter=";") - for row in reader: - path = row.pop("filename") - result.append( - Metric( - self.name, - row, - False, - ObjectIdentifier(descend_tree(dir_tup.tree, path), path), + with ZipFile(list((Path(tup.path) / "pending").glob("*.zip"))[0]) as myzip: + with myzip.open("m_main.csv") as z: + with TextIOWrapper(z) as f: + reader = DictReader(f, delimiter=";") + for row in reader: + path = row.pop("filename") + result.append( + Metric( + self.name, + row, + False, + ObjectIdentifier(descend_tree(tup.tree, path), path), + ) ) - ) return result diff --git a/pyrepositoryminer/metrics/dir/main.py b/pyrepositoryminer/metrics/dir/main.py index 7e9f787..55a7762 100644 --- a/pyrepositoryminer/metrics/dir/main.py +++ b/pyrepositoryminer/metrics/dir/main.py @@ -14,11 +14,14 @@ def __init__(self, repository: Repository, base_dir: Optional[str] = None) -> No super().__init__() self.repository = repository self.base_dir = base_dir + self.tempdir: Optional[TemporaryDirectory[str]] = None def __call__(self, visitable_object: Object) -> Optional[DirMetricInput]: if not isinstance(visitable_object, Commit): return None - self.tempdir: TemporaryDirectory[str] = TemporaryDirectory(dir=self.base_dir) + self.tempdir = TemporaryDirectory( # pylint: disable=consider-using-with + dir=self.base_dir + ) self.repository.checkout_tree( visitable_object.tree.obj, directory=self.tempdir.name, @@ -29,7 +32,8 @@ def __call__(self, visitable_object: Object) -> Optional[DirMetricInput]: return DirMetricInput(is_cached, self.tempdir.name, visitable_object.tree) def close(self) -> None: - self.tempdir.cleanup() + if self.tempdir is not None: + self.tempdir.cleanup() class DirMetric(BaseMetric[DirMetricInput], ABC): diff --git a/pyrepositoryminer/metrics/dir/tokei.py b/pyrepositoryminer/metrics/dir/tokei.py index 079489d..be6f346 100644 --- a/pyrepositoryminer/metrics/dir/tokei.py +++ b/pyrepositoryminer/metrics/dir/tokei.py @@ -16,9 +16,9 @@ def descend_tree(tree: Tree, obj_name: str) -> str: class Tokei(DirMetric): - async def analyze(self, dir_tup: DirMetricInput) -> Iterable[Metric]: + async def analyze(self, tup: DirMetricInput) -> Iterable[Metric]: p = await create_subprocess_exec( - "tokei", "--output", "json", dir_tup.path, stdout=PIPE + "tokei", "--output", "json", tup.path, stdout=PIPE ) stdout, _ = await p.communicate() data = loads(bytes(stdout).decode("utf-8")) @@ -33,8 +33,8 @@ async def analyze(self, dir_tup: DirMetricInput) -> Iterable[Metric]: }, False, ObjectIdentifier( - descend_tree(dir_tup.tree, report["name"][len(dir_tup.path) + 1 :]), - report["name"][len(dir_tup.path) + 1 :], + descend_tree(tup.tree, report["name"][len(tup.path) + 1 :]), + report["name"][len(tup.path) + 1 :], ), ) for category_name, reports in data["Total"]["children"].items() diff --git a/pyrepositoryminer/metrics/main.py b/pyrepositoryminer/metrics/main.py index abd569d..0092304 100644 --- a/pyrepositoryminer/metrics/main.py +++ b/pyrepositoryminer/metrics/main.py @@ -35,8 +35,7 @@ def analyze(self, tup: T) -> Awaitable[Iterable[Metric]]: async def __call__(self, tup: T) -> Iterable[Metric]: if tup.is_cached: return await self.cache_hit(tup) - else: - return await self.analyze(tup) + return await self.analyze(tup) @classmethod @property diff --git a/pyrepositoryminer/metrics/nativeblob/complexity.py b/pyrepositoryminer/metrics/nativeblob/complexity.py index e54a176..18178ba 100644 --- a/pyrepositoryminer/metrics/nativeblob/complexity.py +++ b/pyrepositoryminer/metrics/nativeblob/complexity.py @@ -13,19 +13,19 @@ class Complexity(NativeBlobMetric): filter = NativeBlobFilter(NativeBlobFilter.endswith(".py")) - async def cache_hit(self, blob_tup: NativeBlobMetricInput) -> Iterable[Metric]: + async def cache_hit(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: return [ Metric( self.name, None, True, - ObjectIdentifier(blob_tup.blob.id, blob_tup.path), + ObjectIdentifier(tup.blob.id, tup.path), ) ] - async def analyze(self, blob_tup: NativeBlobMetricInput) -> Iterable[Metric]: + async def analyze(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: try: - cc_data = cc_visit(blob_tup.blob.data) + cc_data = cc_visit(tup.blob.data) except (SyntaxError, UnicodeDecodeError): return [] # TODO get an error output? result = [ @@ -33,7 +33,7 @@ async def analyze(self, blob_tup: NativeBlobMetricInput) -> Iterable[Metric]: self.name, subobject.complexity, False, - ObjectIdentifier(blob_tup.blob.id, blob_tup.path), + ObjectIdentifier(tup.blob.id, tup.path), subobject.fullname, ) for subobject in cc_data diff --git a/pyrepositoryminer/metrics/nativeblob/halstead.py b/pyrepositoryminer/metrics/nativeblob/halstead.py index ad14576..cb1f71f 100644 --- a/pyrepositoryminer/metrics/nativeblob/halstead.py +++ b/pyrepositoryminer/metrics/nativeblob/halstead.py @@ -13,19 +13,19 @@ class Halstead(NativeBlobMetric): filter = NativeBlobFilter(NativeBlobFilter.endswith(".py")) - async def cache_hit(self, blob_tup: NativeBlobMetricInput) -> Iterable[Metric]: + async def cache_hit(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: return [ Metric( self.name, None, True, - ObjectIdentifier(blob_tup.blob.id, blob_tup.path), + ObjectIdentifier(tup.blob.id, tup.path), ) ] - async def analyze(self, blob_tup: NativeBlobMetricInput) -> Iterable[Metric]: + async def analyze(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: try: - h_data = h_visit(blob_tup.blob.data.decode()) + h_data = h_visit(tup.blob.data.decode()) except (SyntaxError, UnicodeDecodeError): return [] # TODO get an error output? result = [ @@ -33,7 +33,7 @@ async def analyze(self, blob_tup: NativeBlobMetricInput) -> Iterable[Metric]: self.name, fn_data._asdict(), False, - ObjectIdentifier(blob_tup.blob.id, blob_tup.path), + ObjectIdentifier(tup.blob.id, tup.path), fn_name, ) for fn_name, fn_data in h_data.functions @@ -43,7 +43,7 @@ async def analyze(self, blob_tup: NativeBlobMetricInput) -> Iterable[Metric]: self.name, h_data.total._asdict(), False, - ObjectIdentifier(blob_tup.blob.id, blob_tup.path), + ObjectIdentifier(tup.blob.id, tup.path), ) ) return result diff --git a/pyrepositoryminer/metrics/nativeblob/linecount.py b/pyrepositoryminer/metrics/nativeblob/linecount.py index 973f556..bda5f99 100644 --- a/pyrepositoryminer/metrics/nativeblob/linecount.py +++ b/pyrepositoryminer/metrics/nativeblob/linecount.py @@ -13,25 +13,25 @@ class Linecount(NativeBlobMetric): filter = NativeBlobFilter(NativeBlobFilter.is_binary()) - async def cache_hit(self, blob_tup: NativeBlobMetricInput) -> Iterable[Metric]: + async def cache_hit(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: return [ Metric( self.name, None, True, - ObjectIdentifier(blob_tup.blob.id, blob_tup.path), + ObjectIdentifier(tup.blob.id, tup.path), ) ] - async def analyze(self, blob_tup: NativeBlobMetricInput) -> Iterable[Metric]: + async def analyze(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: p = await create_subprocess_exec("wc", "-l", stdin=PIPE, stdout=PIPE) - stdout, _ = await p.communicate(blob_tup.blob.data) + stdout, _ = await p.communicate(tup.blob.data) result = [ Metric( self.name, int(stdout), False, - ObjectIdentifier(blob_tup.blob.id, blob_tup.path), + ObjectIdentifier(tup.blob.id, tup.path), ) ] return result diff --git a/pyrepositoryminer/metrics/nativeblob/linelength.py b/pyrepositoryminer/metrics/nativeblob/linelength.py index 5225fc0..6f9a823 100644 --- a/pyrepositoryminer/metrics/nativeblob/linelength.py +++ b/pyrepositoryminer/metrics/nativeblob/linelength.py @@ -11,25 +11,25 @@ class Linelength(NativeBlobMetric): filter = NativeBlobFilter(NativeBlobFilter.is_binary()) - async def cache_hit(self, blob_tup: NativeBlobMetricInput) -> Iterable[Metric]: + async def cache_hit(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: return [ Metric( self.name, None, True, - ObjectIdentifier(blob_tup.blob.id, blob_tup.path), + ObjectIdentifier(tup.blob.id, tup.path), ) ] - async def analyze(self, blob_tup: NativeBlobMetricInput) -> Iterable[Metric]: + async def analyze(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: result = [ Metric( self.name, len(line), False, - ObjectIdentifier(blob_tup.blob.id, blob_tup.path), + ObjectIdentifier(tup.blob.id, tup.path), f"L{i+1}", ) - for i, line in enumerate(blob_tup.blob.obj.data.split(b"\n")) + for i, line in enumerate(tup.blob.obj.data.split(b"\n")) ] return result diff --git a/pyrepositoryminer/metrics/nativeblob/maintainability.py b/pyrepositoryminer/metrics/nativeblob/maintainability.py index 4b9003d..5577719 100644 --- a/pyrepositoryminer/metrics/nativeblob/maintainability.py +++ b/pyrepositoryminer/metrics/nativeblob/maintainability.py @@ -13,19 +13,19 @@ class Maintainability(NativeBlobMetric): filter = NativeBlobFilter(NativeBlobFilter.endswith(".py")) - async def cache_hit(self, blob_tup: NativeBlobMetricInput) -> Iterable[Metric]: + async def cache_hit(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: return [ Metric( self.name, None, True, - ObjectIdentifier(blob_tup.blob.id, blob_tup.path), + ObjectIdentifier(tup.blob.id, tup.path), ) ] - async def analyze(self, blob_tup: NativeBlobMetricInput) -> Iterable[Metric]: + async def analyze(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: try: - mi_data = mi_visit(blob_tup.blob.data.decode(), multi=True) + mi_data = mi_visit(tup.blob.data.decode(), multi=True) except (SyntaxError, UnicodeDecodeError): return [] # TODO get an error output? result = [ @@ -33,7 +33,7 @@ async def analyze(self, blob_tup: NativeBlobMetricInput) -> Iterable[Metric]: self.name, float(mi_data), False, - ObjectIdentifier(blob_tup.blob.id, blob_tup.path), + ObjectIdentifier(tup.blob.id, tup.path), ) ] return result diff --git a/pyrepositoryminer/metrics/nativeblob/nesting.py b/pyrepositoryminer/metrics/nativeblob/nesting.py index 09490c6..25ef75b 100644 --- a/pyrepositoryminer/metrics/nativeblob/nesting.py +++ b/pyrepositoryminer/metrics/nativeblob/nesting.py @@ -27,23 +27,23 @@ class Nesting(NativeBlobMetric): filter = NativeBlobFilter(NativeBlobFilter.endswith(".py")) - async def cache_hit(self, blob_tup: NativeBlobMetricInput) -> Iterable[Metric]: + async def cache_hit(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: return [ Metric( self.name, None, True, - ObjectIdentifier(blob_tup.blob.id, blob_tup.path), + ObjectIdentifier(tup.blob.id, tup.path), ) ] - async def analyze(self, blob_tup: NativeBlobMetricInput) -> Iterable[Metric]: + async def analyze(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: result = [ Metric( self.name, - NestingASTVisitor().visit(parse(blob_tup.blob.obj.data)).result, + NestingASTVisitor().visit(parse(tup.blob.obj.data)).result, False, - ObjectIdentifier(blob_tup.blob.id, blob_tup.path), + ObjectIdentifier(tup.blob.id, tup.path), ) ] return result diff --git a/pyrepositoryminer/metrics/nativeblob/pylinecount.py b/pyrepositoryminer/metrics/nativeblob/pylinecount.py index 7016e4a..882935f 100644 --- a/pyrepositoryminer/metrics/nativeblob/pylinecount.py +++ b/pyrepositoryminer/metrics/nativeblob/pylinecount.py @@ -11,23 +11,23 @@ class Pylinecount(NativeBlobMetric): filter = NativeBlobFilter(NativeBlobFilter.is_binary()) - async def cache_hit(self, blob_tup: NativeBlobMetricInput) -> Iterable[Metric]: + async def cache_hit(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: return [ Metric( self.name, None, True, - ObjectIdentifier(blob_tup.blob.id, blob_tup.path), + ObjectIdentifier(tup.blob.id, tup.path), ) ] - async def analyze(self, blob_tup: NativeBlobMetricInput) -> Iterable[Metric]: + async def analyze(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: result = [ Metric( self.name, - blob_tup.blob.obj.data.count(b"\n") + 1, + tup.blob.obj.data.count(b"\n") + 1, False, - ObjectIdentifier(blob_tup.blob.id, blob_tup.path), + ObjectIdentifier(tup.blob.id, tup.path), ) ] return result diff --git a/pyrepositoryminer/metrics/nativeblob/raw.py b/pyrepositoryminer/metrics/nativeblob/raw.py index 82edbc7..dc97e6d 100644 --- a/pyrepositoryminer/metrics/nativeblob/raw.py +++ b/pyrepositoryminer/metrics/nativeblob/raw.py @@ -13,19 +13,19 @@ class Raw(NativeBlobMetric): filter = NativeBlobFilter(NativeBlobFilter.endswith(".py")) - async def cache_hit(self, blob_tup: NativeBlobMetricInput) -> Iterable[Metric]: + async def cache_hit(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: return [ Metric( self.name, None, True, - ObjectIdentifier(blob_tup.blob.id, blob_tup.path), + ObjectIdentifier(tup.blob.id, tup.path), ) ] - async def analyze(self, blob_tup: NativeBlobMetricInput) -> Iterable[Metric]: + async def analyze(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: try: - r_data = analyze(blob_tup.blob.data.decode()) + r_data = analyze(tup.blob.data.decode()) except (SyntaxError, UnicodeDecodeError): return [] # TODO get an error output? result = [ @@ -33,7 +33,7 @@ async def analyze(self, blob_tup: NativeBlobMetricInput) -> Iterable[Metric]: self.name, r_data._asdict(), False, - ObjectIdentifier(blob_tup.blob.id, blob_tup.path), + ObjectIdentifier(tup.blob.id, tup.path), ) ] return result diff --git a/pyrepositoryminer/metrics/nativetree/blobcount.py b/pyrepositoryminer/metrics/nativetree/blobcount.py index 09a40b7..f018464 100644 --- a/pyrepositoryminer/metrics/nativetree/blobcount.py +++ b/pyrepositoryminer/metrics/nativetree/blobcount.py @@ -6,9 +6,9 @@ class Blobcount(NativeTreeMetric): - async def analyze(self, tree_tup: NativeTreeMetricInput) -> Iterable[Metric]: + async def analyze(self, tup: NativeTreeMetricInput) -> Iterable[Metric]: n = 0 - q: List[Object] = [tree_tup.tree] + q: List[Object] = [tup.tree] while q: obj = q.pop(0) if isinstance(obj, Blob): diff --git a/pyrepositoryminer/metrics/nativetree/cacherate.py b/pyrepositoryminer/metrics/nativetree/cacherate.py index f2be29a..acd7e27 100644 --- a/pyrepositoryminer/metrics/nativetree/cacherate.py +++ b/pyrepositoryminer/metrics/nativetree/cacherate.py @@ -9,13 +9,13 @@ class CacheRate(NativeTreeMetric): def __init__(self) -> None: self.cache: Set[str] = set() - async def analyze(self, tree_tup: NativeTreeMetricInput) -> Iterable[Metric]: + async def analyze(self, tup: NativeTreeMetricInput) -> Iterable[Metric]: rate: Dict[str, Dict[bool, int]] = { "blobs": {True: 0, False: 0}, "trees": {True: 0, False: 0}, "other": {True: 0, False: 0}, } - q: List[Object] = [tree_tup.tree] + q: List[Object] = [tup.tree] while q: obj = q.pop(0) is_cached = obj.id in self.cache diff --git a/pyrepositoryminer/metrics/nativetree/loc.py b/pyrepositoryminer/metrics/nativetree/loc.py index 237db84..ab4b4fe 100644 --- a/pyrepositoryminer/metrics/nativetree/loc.py +++ b/pyrepositoryminer/metrics/nativetree/loc.py @@ -6,9 +6,9 @@ class Loc(NativeTreeMetric): - async def analyze(self, tree_tup: NativeTreeMetricInput) -> Iterable[Metric]: + async def analyze(self, tup: NativeTreeMetricInput) -> Iterable[Metric]: n = 0 - q: List[Object] = [tree_tup.tree] + q: List[Object] = [tup.tree] while q: obj = q.pop(0) if isinstance(obj, Blob): diff --git a/pyrepositoryminer/metrics/nativetree/touchedlines.py b/pyrepositoryminer/metrics/nativetree/touchedlines.py index ed471ad..65d8c5e 100644 --- a/pyrepositoryminer/metrics/nativetree/touchedlines.py +++ b/pyrepositoryminer/metrics/nativetree/touchedlines.py @@ -12,14 +12,14 @@ class TouchedLines(NativeTreeMetric): - async def analyze(self, tree_tup: NativeTreeMetricInput) -> Iterable[Metric]: - parent_trees = tuple(parent.tree.obj for parent in tree_tup.commit.parents) + async def analyze(self, tup: NativeTreeMetricInput) -> Iterable[Metric]: + parent_trees = tuple(parent.tree.obj for parent in tup.commit.parents) if not parent_trees: # orphan commit is diffed to empty tree - diffs = [tree_tup.tree.obj.diff_to_tree(swap=True)] + diffs = [tup.tree.obj.diff_to_tree(swap=True)] else: diffs = [ - tree_tup.tree.obj.diff_to_tree(parent_tree, swap=True) + tup.tree.obj.diff_to_tree(parent_tree, swap=True) for parent_tree in parent_trees ] touched_lines = [ diff --git a/pyrepositoryminer/pobjects.py b/pyrepositoryminer/pobjects.py index 13fb7a2..b5ba5ce 100644 --- a/pyrepositoryminer/pobjects.py +++ b/pyrepositoryminer/pobjects.py @@ -11,11 +11,11 @@ class Object: @classmethod def from_pobject(cls, obj: pObject) -> Object: + if isinstance(obj, pBlob): + return Blob(obj) if isinstance(obj, pTree): return Tree(obj) - elif isinstance(obj, pBlob): - return Blob(obj) - elif isinstance(obj, pCommit): + if isinstance(obj, pCommit): return Commit(obj) return Object(obj) diff --git a/setup.cfg b/setup.cfg index 01b255a..f730690 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,10 +1,13 @@ [flake8] max-line-length = 88 -extend-ignore = E203 +extend-ignore = E203,E501 [isort] profile = black [mypy] strict = True -disallow_untyped_decorators = False \ No newline at end of file +disallow_untyped_decorators = False + +[pylint.'MESSAGES CONTROL'] +disable=missing-module-docstring,missing-class-docstring,missing-function-docstring,no-name-in-module,fixme,invalid-overridden-method,invalid-name,too-many-arguments,duplicate-code \ No newline at end of file From 4552799c2c0ca76be9acdb1195d8a7fd819b2d3e Mon Sep 17 00:00:00 2001 From: fabianhe <39628987+fabianhe@users.noreply.github.com> Date: Fri, 16 Jul 2021 13:45:53 +0200 Subject: [PATCH 04/19] Change pylint cfg --- setup.cfg | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index f730690..3d75190 100644 --- a/setup.cfg +++ b/setup.cfg @@ -9,5 +9,8 @@ profile = black strict = True disallow_untyped_decorators = False +[pylint.MASTER] +ignore-paths=^scripts/.*\.py$ + [pylint.'MESSAGES CONTROL'] -disable=missing-module-docstring,missing-class-docstring,missing-function-docstring,no-name-in-module,fixme,invalid-overridden-method,invalid-name,too-many-arguments,duplicate-code \ No newline at end of file +disable=missing-module-docstring,missing-class-docstring,missing-function-docstring,no-name-in-module,fixme,invalid-overridden-method,invalid-name,too-many-arguments,duplicate-code From 3c60ee5fe15a91317518cd1956214ba7c2f65b84 Mon Sep 17 00:00:00 2001 From: fabianhe <39628987+fabianhe@users.noreply.github.com> Date: Mon, 26 Jul 2021 12:56:47 +0200 Subject: [PATCH 05/19] Change cache-hit default for nativeblobs --- .../metrics/nativeblob/complexity.py | 10 ---------- pyrepositoryminer/metrics/nativeblob/halstead.py | 10 ---------- .../metrics/nativeblob/linecount.py | 10 ---------- .../metrics/nativeblob/linelength.py | 10 ---------- pyrepositoryminer/metrics/nativeblob/main.py | 16 +++++++++++++++- .../metrics/nativeblob/maintainability.py | 10 ---------- pyrepositoryminer/metrics/nativeblob/nesting.py | 10 ---------- .../metrics/nativeblob/pylinecount.py | 10 ---------- pyrepositoryminer/metrics/nativeblob/raw.py | 10 ---------- 9 files changed, 15 insertions(+), 81 deletions(-) diff --git a/pyrepositoryminer/metrics/nativeblob/complexity.py b/pyrepositoryminer/metrics/nativeblob/complexity.py index 18178ba..a4774b6 100644 --- a/pyrepositoryminer/metrics/nativeblob/complexity.py +++ b/pyrepositoryminer/metrics/nativeblob/complexity.py @@ -13,16 +13,6 @@ class Complexity(NativeBlobMetric): filter = NativeBlobFilter(NativeBlobFilter.endswith(".py")) - async def cache_hit(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: - return [ - Metric( - self.name, - None, - True, - ObjectIdentifier(tup.blob.id, tup.path), - ) - ] - async def analyze(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: try: cc_data = cc_visit(tup.blob.data) diff --git a/pyrepositoryminer/metrics/nativeblob/halstead.py b/pyrepositoryminer/metrics/nativeblob/halstead.py index cb1f71f..386ff82 100644 --- a/pyrepositoryminer/metrics/nativeblob/halstead.py +++ b/pyrepositoryminer/metrics/nativeblob/halstead.py @@ -13,16 +13,6 @@ class Halstead(NativeBlobMetric): filter = NativeBlobFilter(NativeBlobFilter.endswith(".py")) - async def cache_hit(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: - return [ - Metric( - self.name, - None, - True, - ObjectIdentifier(tup.blob.id, tup.path), - ) - ] - async def analyze(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: try: h_data = h_visit(tup.blob.data.decode()) diff --git a/pyrepositoryminer/metrics/nativeblob/linecount.py b/pyrepositoryminer/metrics/nativeblob/linecount.py index bda5f99..5d038d0 100644 --- a/pyrepositoryminer/metrics/nativeblob/linecount.py +++ b/pyrepositoryminer/metrics/nativeblob/linecount.py @@ -13,16 +13,6 @@ class Linecount(NativeBlobMetric): filter = NativeBlobFilter(NativeBlobFilter.is_binary()) - async def cache_hit(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: - return [ - Metric( - self.name, - None, - True, - ObjectIdentifier(tup.blob.id, tup.path), - ) - ] - async def analyze(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: p = await create_subprocess_exec("wc", "-l", stdin=PIPE, stdout=PIPE) stdout, _ = await p.communicate(tup.blob.data) diff --git a/pyrepositoryminer/metrics/nativeblob/linelength.py b/pyrepositoryminer/metrics/nativeblob/linelength.py index 6f9a823..17cb6be 100644 --- a/pyrepositoryminer/metrics/nativeblob/linelength.py +++ b/pyrepositoryminer/metrics/nativeblob/linelength.py @@ -11,16 +11,6 @@ class Linelength(NativeBlobMetric): filter = NativeBlobFilter(NativeBlobFilter.is_binary()) - async def cache_hit(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: - return [ - Metric( - self.name, - None, - True, - ObjectIdentifier(tup.blob.id, tup.path), - ) - ] - async def analyze(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: result = [ Metric( diff --git a/pyrepositoryminer/metrics/nativeblob/main.py b/pyrepositoryminer/metrics/nativeblob/main.py index 864fc41..4d47e45 100644 --- a/pyrepositoryminer/metrics/nativeblob/main.py +++ b/pyrepositoryminer/metrics/nativeblob/main.py @@ -2,7 +2,11 @@ from typing import Callable, Iterable, List, Set, Tuple from pyrepositoryminer.metrics.main import BaseMetric, BaseVisitor -from pyrepositoryminer.metrics.structs import NativeBlobMetricInput +from pyrepositoryminer.metrics.structs import ( + Metric, + NativeBlobMetricInput, + ObjectIdentifier, +) from pyrepositoryminer.pobjects import Blob, Commit, Object, Tree @@ -56,6 +60,16 @@ def f(tup: NativeBlobMetricInput) -> bool: class NativeBlobMetric(BaseMetric[NativeBlobMetricInput], ABC): + async def cache_hit(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: + return [ + Metric( + self.name, + None, + True, + ObjectIdentifier(tup.blob.id, tup.path), + ) + ] + @staticmethod @abstractmethod def filter(tup: NativeBlobMetricInput) -> bool: diff --git a/pyrepositoryminer/metrics/nativeblob/maintainability.py b/pyrepositoryminer/metrics/nativeblob/maintainability.py index 5577719..619d6b0 100644 --- a/pyrepositoryminer/metrics/nativeblob/maintainability.py +++ b/pyrepositoryminer/metrics/nativeblob/maintainability.py @@ -13,16 +13,6 @@ class Maintainability(NativeBlobMetric): filter = NativeBlobFilter(NativeBlobFilter.endswith(".py")) - async def cache_hit(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: - return [ - Metric( - self.name, - None, - True, - ObjectIdentifier(tup.blob.id, tup.path), - ) - ] - async def analyze(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: try: mi_data = mi_visit(tup.blob.data.decode(), multi=True) diff --git a/pyrepositoryminer/metrics/nativeblob/nesting.py b/pyrepositoryminer/metrics/nativeblob/nesting.py index 25ef75b..41d9944 100644 --- a/pyrepositoryminer/metrics/nativeblob/nesting.py +++ b/pyrepositoryminer/metrics/nativeblob/nesting.py @@ -27,16 +27,6 @@ class Nesting(NativeBlobMetric): filter = NativeBlobFilter(NativeBlobFilter.endswith(".py")) - async def cache_hit(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: - return [ - Metric( - self.name, - None, - True, - ObjectIdentifier(tup.blob.id, tup.path), - ) - ] - async def analyze(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: result = [ Metric( diff --git a/pyrepositoryminer/metrics/nativeblob/pylinecount.py b/pyrepositoryminer/metrics/nativeblob/pylinecount.py index 882935f..cd41067 100644 --- a/pyrepositoryminer/metrics/nativeblob/pylinecount.py +++ b/pyrepositoryminer/metrics/nativeblob/pylinecount.py @@ -11,16 +11,6 @@ class Pylinecount(NativeBlobMetric): filter = NativeBlobFilter(NativeBlobFilter.is_binary()) - async def cache_hit(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: - return [ - Metric( - self.name, - None, - True, - ObjectIdentifier(tup.blob.id, tup.path), - ) - ] - async def analyze(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: result = [ Metric( diff --git a/pyrepositoryminer/metrics/nativeblob/raw.py b/pyrepositoryminer/metrics/nativeblob/raw.py index dc97e6d..e0ab73e 100644 --- a/pyrepositoryminer/metrics/nativeblob/raw.py +++ b/pyrepositoryminer/metrics/nativeblob/raw.py @@ -13,16 +13,6 @@ class Raw(NativeBlobMetric): filter = NativeBlobFilter(NativeBlobFilter.endswith(".py")) - async def cache_hit(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: - return [ - Metric( - self.name, - None, - True, - ObjectIdentifier(tup.blob.id, tup.path), - ) - ] - async def analyze(self, tup: NativeBlobMetricInput) -> Iterable[Metric]: try: r_data = analyze(tup.blob.data.decode()) From 281bccf2ab1529b2c5e42bdd3e78f1e487bf63a9 Mon Sep 17 00:00:00 2001 From: fabianhe <39628987+fabianhe@users.noreply.github.com> Date: Mon, 26 Jul 2021 12:57:38 +0200 Subject: [PATCH 06/19] Add utils --- pyrepositoryminer/metrics/diffdir/main.py | 16 ++------------ pyrepositoryminer/metrics/diffdir/seerene.py | 7 +------ pyrepositoryminer/metrics/utils.py | 22 ++++++++++++++++++++ 3 files changed, 25 insertions(+), 20 deletions(-) create mode 100644 pyrepositoryminer/metrics/utils.py diff --git a/pyrepositoryminer/metrics/diffdir/main.py b/pyrepositoryminer/metrics/diffdir/main.py index cfe2d10..ba8279d 100644 --- a/pyrepositoryminer/metrics/diffdir/main.py +++ b/pyrepositoryminer/metrics/diffdir/main.py @@ -1,27 +1,15 @@ from abc import ABC from tempfile import TemporaryDirectory -from typing import FrozenSet, Optional +from typing import Optional from pygit2 import GIT_CHECKOUT_FORCE, Repository -from pygit2._pygit2 import DiffFile from pyrepositoryminer.metrics.main import BaseMetric, BaseVisitor from pyrepositoryminer.metrics.structs import DirMetricInput +from pyrepositoryminer.metrics.utils import get_touchedfiles from pyrepositoryminer.pobjects import Commit, Object -def get_touchedfiles(commit: Commit) -> FrozenSet[DiffFile]: - if not commit.parents: - return frozenset( - delta.new_file for delta in commit.tree.obj.diff_to_tree(swap=True).deltas - ) - return frozenset( - delta.new_file - for parent in commit.parents - for delta in commit.tree.obj.diff_to_tree(parent.tree.obj, swap=True).deltas - ) - - class DiffDirVisitor(BaseVisitor): def __init__(self, repository: Repository, base_dir: Optional[str] = None) -> None: super().__init__() diff --git a/pyrepositoryminer/metrics/diffdir/seerene.py b/pyrepositoryminer/metrics/diffdir/seerene.py index f933a13..26e027c 100644 --- a/pyrepositoryminer/metrics/diffdir/seerene.py +++ b/pyrepositoryminer/metrics/diffdir/seerene.py @@ -1,7 +1,6 @@ from asyncio import create_subprocess_exec from asyncio.subprocess import PIPE from csv import DictReader -from functools import reduce from io import TextIOWrapper from json import dump from os import getenv @@ -12,11 +11,7 @@ from pyrepositoryminer.metrics.diffdir.main import DiffDirMetric from pyrepositoryminer.metrics.structs import DirMetricInput, Metric, ObjectIdentifier -from pyrepositoryminer.pobjects import Tree - - -def descend_tree(tree: Tree, obj_name: str) -> str: - return reduce(lambda a, b: a[b], obj_name.split("/"), tree).id # type: ignore +from pyrepositoryminer.metrics.utils import descend_tree class Seerene(DiffDirMetric): diff --git a/pyrepositoryminer/metrics/utils.py b/pyrepositoryminer/metrics/utils.py new file mode 100644 index 0000000..1fceb00 --- /dev/null +++ b/pyrepositoryminer/metrics/utils.py @@ -0,0 +1,22 @@ +from functools import reduce +from typing import FrozenSet + +from pygit2._pygit2 import DiffFile + +from pyrepositoryminer.pobjects import Commit, Tree + + +def get_touchedfiles(commit: Commit) -> FrozenSet[DiffFile]: + if not commit.parents: + return frozenset( + delta.new_file for delta in commit.tree.obj.diff_to_tree(swap=True).deltas + ) + return frozenset( + delta.new_file + for parent in commit.parents + for delta in commit.tree.obj.diff_to_tree(parent.tree.obj, swap=True).deltas + ) + + +def descend_tree(tree: Tree, obj_name: str) -> str: + return reduce(lambda a, b: a[b], obj_name.split("/"), tree).id # type: ignore From dc55259611e9fcd2ed51ec3bf75f66b9cd03603e Mon Sep 17 00:00:00 2001 From: fabianhe <39628987+fabianhe@users.noreply.github.com> Date: Mon, 26 Jul 2021 12:58:02 +0200 Subject: [PATCH 07/19] Change tokei metrics --- .../metrics/diffdir/difftokei.py | 48 +----------- pyrepositoryminer/metrics/dir/tokei.py | 78 +++++++++---------- 2 files changed, 40 insertions(+), 86 deletions(-) diff --git a/pyrepositoryminer/metrics/diffdir/difftokei.py b/pyrepositoryminer/metrics/diffdir/difftokei.py index e9d6602..41ed522 100644 --- a/pyrepositoryminer/metrics/diffdir/difftokei.py +++ b/pyrepositoryminer/metrics/diffdir/difftokei.py @@ -1,52 +1,10 @@ -from asyncio import create_subprocess_exec -from asyncio.subprocess import PIPE -from functools import reduce -from json import loads from typing import Iterable from pyrepositoryminer.metrics.diffdir.main import DiffDirMetric -from pyrepositoryminer.metrics.structs import DirMetricInput, Metric, ObjectIdentifier -from pyrepositoryminer.pobjects import Tree - - -def descend_tree(tree: Tree, obj_name: str) -> str: - return reduce(lambda a, b: a[b], obj_name.split("/"), tree).id # type: ignore +from pyrepositoryminer.metrics.dir.tokei import tokei +from pyrepositoryminer.metrics.structs import DirMetricInput, Metric class DiffTokei(DiffDirMetric): async def analyze(self, tup: DirMetricInput) -> Iterable[Metric]: - p = await create_subprocess_exec( - "tokei", "--output", "json", tup.path, stdout=PIPE - ) - stdout, _ = await p.communicate() - data = loads(bytes(stdout).decode("utf-8")) - result = [ - Metric( - "tokei", - { - "category": category_name, - "blanks": report["stats"]["blanks"], - "code": report["stats"]["code"], - "comments": report["stats"]["comments"], - }, - False, - ObjectIdentifier( - descend_tree(tup.tree, report["name"][len(tup.path) + 1 :]), - report["name"][len(tup.path) + 1 :], - ), - ) - for category_name, reports in data["Total"]["children"].items() - for report in reports - ] - result.append( - Metric( - self.name, - { - "blanks": data["Total"]["blanks"], - "code": data["Total"]["code"], - "comments": data["Total"]["comments"], - }, - False, - ) - ) - return result + return await tokei(self.name, tup.path, tup.tree) diff --git a/pyrepositoryminer/metrics/dir/tokei.py b/pyrepositoryminer/metrics/dir/tokei.py index be6f346..4bdb87a 100644 --- a/pyrepositoryminer/metrics/dir/tokei.py +++ b/pyrepositoryminer/metrics/dir/tokei.py @@ -5,50 +5,46 @@ from pyrepositoryminer.metrics.dir.main import DirMetric from pyrepositoryminer.metrics.structs import DirMetricInput, Metric, ObjectIdentifier -from pyrepositoryminer.pobjects import Object, Tree +from pyrepositoryminer.metrics.utils import descend_tree +from pyrepositoryminer.pobjects import Tree -def descend_tree(tree: Tree, obj_name: str) -> str: - item: Object = tree - for i in obj_name.split("/"): - item = item[i] # type: ignore - return item.id +async def tokei(name: str, path: str, tree: Tree) -> Iterable[Metric]: + p = await create_subprocess_exec("tokei", "--output", "json", path, stdout=PIPE) + stdout, _ = await p.communicate() + data = loads(bytes(stdout).decode("utf-8")) + result = [ + Metric( + name, + { + "category": category_name, + "blanks": report["stats"]["blanks"], + "code": report["stats"]["code"], + "comments": report["stats"]["comments"], + }, + False, + ObjectIdentifier( + descend_tree(tree, report["name"][len(path) + 1 :]), + report["name"][len(path) + 1 :], + ), + ) + for category_name, reports in data["Total"]["children"].items() + for report in reports + ] + result.append( + Metric( + name, + { + "blanks": data["Total"]["blanks"], + "code": data["Total"]["code"], + "comments": data["Total"]["comments"], + }, + False, + ) + ) + return result class Tokei(DirMetric): async def analyze(self, tup: DirMetricInput) -> Iterable[Metric]: - p = await create_subprocess_exec( - "tokei", "--output", "json", tup.path, stdout=PIPE - ) - stdout, _ = await p.communicate() - data = loads(bytes(stdout).decode("utf-8")) - result = [ - Metric( - "tokei", - { - "category": category_name, - "blanks": report["stats"]["blanks"], - "code": report["stats"]["code"], - "comments": report["stats"]["comments"], - }, - False, - ObjectIdentifier( - descend_tree(tup.tree, report["name"][len(tup.path) + 1 :]), - report["name"][len(tup.path) + 1 :], - ), - ) - for category_name, reports in data["Total"]["children"].items() - for report in reports - ] - result.append( - Metric( - self.name, - { - "blanks": data["Total"]["blanks"], - "code": data["Total"]["code"], - "comments": data["Total"]["comments"], - }, - False, - ) - ) - return result + return await tokei(self.name, tup.path, tup.tree) From dd4a2b66a0ac00e52c914ed4454c9fd636346892 Mon Sep 17 00:00:00 2001 From: fabianhe <39628987+fabianhe@users.noreply.github.com> Date: Mon, 26 Jul 2021 14:06:04 +0200 Subject: [PATCH 08/19] Add new metrics class diffblobmetric --- pyrepositoryminer/analyze.py | 61 +++++++++---------- pyrepositoryminer/commands/analyze.py | 10 ++- pyrepositoryminer/metrics/__init__.py | 5 ++ .../metrics/diffblob/__init__.py | 1 + pyrepositoryminer/metrics/diffblob/main.py | 31 ++++++++++ pyrepositoryminer/metrics/nativeblob/main.py | 31 +++++----- 6 files changed, 90 insertions(+), 49 deletions(-) create mode 100644 pyrepositoryminer/metrics/diffblob/__init__.py create mode 100644 pyrepositoryminer/metrics/diffblob/main.py diff --git a/pyrepositoryminer/analyze.py b/pyrepositoryminer/analyze.py index e3b16c3..8d06f06 100644 --- a/pyrepositoryminer/analyze.py +++ b/pyrepositoryminer/analyze.py @@ -11,6 +11,7 @@ from uvloop import install from pyrepositoryminer.metrics import all_metrics +from pyrepositoryminer.metrics.diffblob.main import DiffBlobMetric, DiffBlobVisitor from pyrepositoryminer.metrics.diffdir.main import DiffDirMetric, DiffDirVisitor from pyrepositoryminer.metrics.dir.main import DirMetric, DirVisitor from pyrepositoryminer.metrics.nativeblob.main import ( @@ -36,6 +37,8 @@ class InitArgs(NamedTuple): repo: Repository native_blob_metrics: Tuple[Any, ...] native_blob_visitor: NativeBlobVisitor +diff_blob_metrics: Tuple[Any, ...] +diff_blob_visitor: DiffBlobVisitor native_tree_metrics: Tuple[Any, ...] native_tree_visitor: NativeTreeVisitor dir_metrics: Tuple[Any, ...] @@ -62,7 +65,6 @@ async def categorize_metrics( async def analyze(commit_id: str) -> Optional[CommitOutput]: - global repo, native_blob_metrics try: commit = repo.get(commit_id) except ValueError: @@ -79,6 +81,13 @@ async def analyze(commit_id: str) -> Optional[CommitOutput]: for m in native_blob_metrics if not m.filter(blob_tup) ) + if diff_blob_metrics: + futures.extend( + m(blob_tup) + for blob_tup in diff_blob_visitor(root) + for m in diff_blob_metrics + if not m.filter(blob_tup) + ) if native_tree_metrics: tree_tup = native_tree_visitor(root) futures.extend(m(tree_tup) for m in native_tree_metrics) @@ -100,45 +109,31 @@ def initialize(init_args: InitArgs) -> None: install() global repo global native_blob_metrics, native_blob_visitor + global diff_blob_metrics, diff_blob_visitor global native_tree_metrics, native_tree_visitor global dir_metrics, dir_visitor global diffdir_metrics, diffdir_visitor + + def get_metrics(superclass) -> Tuple: # type: ignore + return tuple( + [ + all_metrics[m]() + for m in init_args.metrics + if issubclass(all_metrics[m], superclass) + ] + + [m() for m in init_args.custom_metrics if issubclass(m, superclass)] + ) + repo = Repository(init_args.repository) - native_blob_metrics = tuple( - [ - all_metrics[m]() - for m in init_args.metrics - if issubclass(all_metrics[m], NativeBlobMetric) - ] - + [m() for m in init_args.custom_metrics if issubclass(m, NativeBlobMetric)] - ) + native_blob_metrics = get_metrics(NativeBlobMetric) native_blob_visitor = NativeBlobVisitor() - native_tree_metrics = tuple( - [ - all_metrics[m]() - for m in init_args.metrics - if issubclass(all_metrics[m], NativeTreeMetric) - ] - + [m() for m in init_args.custom_metrics if issubclass(m, NativeTreeMetric)] - ) + diff_blob_metrics = get_metrics(DiffBlobMetric) + diff_blob_visitor = DiffBlobVisitor(repo) + native_tree_metrics = get_metrics(NativeTreeMetric) native_tree_visitor = NativeTreeVisitor() - dir_metrics = tuple( - [ - all_metrics[m]() - for m in init_args.metrics - if issubclass(all_metrics[m], DirMetric) - ] - + [m() for m in init_args.custom_metrics if issubclass(m, DirMetric)] - ) + dir_metrics = get_metrics(DirMetric) dir_visitor = DirVisitor(repo) - diffdir_metrics = tuple( - [ - all_metrics[m]() - for m in init_args.metrics - if issubclass(all_metrics[m], DiffDirMetric) - ] - + [m() for m in init_args.custom_metrics if issubclass(m, DiffDirMetric)] - ) + diffdir_metrics = get_metrics(DiffDirMetric) diffdir_visitor = DiffDirVisitor(repo) diff --git a/pyrepositoryminer/commands/analyze.py b/pyrepositoryminer/commands/analyze.py index e39e052..287e28f 100644 --- a/pyrepositoryminer/commands/analyze.py +++ b/pyrepositoryminer/commands/analyze.py @@ -12,6 +12,8 @@ from pyrepositoryminer.analyze import InitArgs, initialize, worker from pyrepositoryminer.metrics import all_metrics +from pyrepositoryminer.metrics.diffblob.main import DiffBlobMetric +from pyrepositoryminer.metrics.diffdir.main import DiffDirMetric from pyrepositoryminer.metrics.dir.main import DirMetric from pyrepositoryminer.metrics.nativeblob.main import NativeBlobMetric from pyrepositoryminer.metrics.nativetree.main import NativeTreeMetric @@ -43,7 +45,13 @@ def import_metric(import_str: str): # type: ignore # TODO make this a metric a if not isclass(instance): print(f'Instance "{instance}" must be a class') raise Abort() - parents = (NativeBlobMetric, NativeTreeMetric, DirMetric) + parents = ( + NativeBlobMetric, + DiffBlobMetric, + NativeTreeMetric, + DirMetric, + DiffDirMetric, + ) if not any(issubclass(instance, parent) for parent in parents): # type: ignore print(f'Instance "{instance}" must subclass a pyrepositoryminer metric class') raise Abort() diff --git a/pyrepositoryminer/metrics/__init__.py b/pyrepositoryminer/metrics/__init__.py index 004db32..9e16faa 100644 --- a/pyrepositoryminer/metrics/__init__.py +++ b/pyrepositoryminer/metrics/__init__.py @@ -1,5 +1,6 @@ from typing import Any, Dict +import pyrepositoryminer.metrics.diffblob as DiffBlobMetrics import pyrepositoryminer.metrics.diffdir as DiffDirMetrics import pyrepositoryminer.metrics.dir as DirMetrics import pyrepositoryminer.metrics.nativeblob as NativeBlobMetrics @@ -10,6 +11,10 @@ getattr(NativeBlobMetrics, m).name: getattr(NativeBlobMetrics, m) for m in NativeBlobMetrics.__all__ }, + **{ + getattr(DiffBlobMetrics, m).name: getattr(DiffBlobMetrics, m) + for m in DiffBlobMetrics.__all__ + }, **{ getattr(NativeTreeMetrics, m).name: getattr(NativeTreeMetrics, m) for m in NativeTreeMetrics.__all__ diff --git a/pyrepositoryminer/metrics/diffblob/__init__.py b/pyrepositoryminer/metrics/diffblob/__init__.py new file mode 100644 index 0000000..ea9b783 --- /dev/null +++ b/pyrepositoryminer/metrics/diffblob/__init__.py @@ -0,0 +1 @@ +__all__ = () diff --git a/pyrepositoryminer/metrics/diffblob/main.py b/pyrepositoryminer/metrics/diffblob/main.py new file mode 100644 index 0000000..d20d6e8 --- /dev/null +++ b/pyrepositoryminer/metrics/diffblob/main.py @@ -0,0 +1,31 @@ +from abc import ABC, abstractmethod +from typing import Iterable + +from pygit2 import Repository + +from pyrepositoryminer.metrics.main import BaseMetric, BaseVisitor +from pyrepositoryminer.metrics.structs import NativeBlobMetricInput +from pyrepositoryminer.metrics.utils import get_touchedfiles +from pyrepositoryminer.pobjects import Blob, Commit, Object + + +class DiffBlobVisitor(BaseVisitor): + def __init__(self, repository: Repository) -> None: + super().__init__() + self.repository = repository + + def __call__(self, visitable_object: Object) -> Iterable[NativeBlobMetricInput]: + if isinstance(visitable_object, Commit): + for file in get_touchedfiles(visitable_object): + blob = Blob(self.repository.get(file.id)) + yield NativeBlobMetricInput( + self.oid_is_cached(blob.id), str(file.path), blob + ) + self.cache_oid(blob.id) + + +class DiffBlobMetric(BaseMetric[NativeBlobMetricInput], ABC): + @staticmethod + @abstractmethod + def filter(tup: NativeBlobMetricInput) -> bool: + pass diff --git a/pyrepositoryminer/metrics/nativeblob/main.py b/pyrepositoryminer/metrics/nativeblob/main.py index 4d47e45..536c249 100644 --- a/pyrepositoryminer/metrics/nativeblob/main.py +++ b/pyrepositoryminer/metrics/nativeblob/main.py @@ -12,21 +12,22 @@ class NativeBlobVisitor(BaseVisitor): def __call__(self, visitable_object: Object) -> Iterable[NativeBlobMetricInput]: - visited_commit = False - q: List[Tuple[Object, str]] = [(visitable_object, "")] - while q: - vo, path = q.pop(0) - if isinstance(vo, Blob): - yield NativeBlobMetricInput( - self.oid_is_cached(vo.id), f"{path}/{vo.name}", vo - ) - elif isinstance(vo, Tree): - p = f"{f'{path}/' if path else ''}{vo.name if vo.name else ''}" - q.extend((sub_vo, p) for sub_vo in vo) - elif isinstance(vo, Commit) and not visited_commit: - q.append((vo.tree, "")) - visited_commit = False - self.cache_oid(vo.id) + if isinstance(visitable_object, Commit): + visited_commit = False + q: List[Tuple[Object, str]] = [(visitable_object, "")] + while q: + vo, path = q.pop(0) + if isinstance(vo, Blob): + yield NativeBlobMetricInput( + self.oid_is_cached(vo.id), f"{path}/{vo.name}", vo + ) + elif isinstance(vo, Tree): + p = f"{f'{path}/' if path else ''}{vo.name if vo.name else ''}" + q.extend((sub_vo, p) for sub_vo in vo) + elif isinstance(vo, Commit) and not visited_commit: + q.append((vo.tree, "")) + visited_commit = True + self.cache_oid(vo.id) class NativeBlobFilter: From a140a31351547490a8c0ed5fe20778f6bd2c6e7a Mon Sep 17 00:00:00 2001 From: fabianhe <39628987+fabianhe@users.noreply.github.com> Date: Mon, 26 Jul 2021 14:07:20 +0200 Subject: [PATCH 09/19] Add diffpylinecount --- DOCS.md | 4 ++-- pyrepositoryminer/metrics/diffblob/__init__.py | 4 +++- pyrepositoryminer/metrics/diffblob/diffpylinecount.py | 7 +++++++ 3 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 pyrepositoryminer/metrics/diffblob/diffpylinecount.py diff --git a/DOCS.md b/DOCS.md index 82d881c..366eb62 100644 --- a/DOCS.md +++ b/DOCS.md @@ -30,13 +30,13 @@ Either provide the commit ids to analyze on stdin or as a file argument. **Usage**: ```console -$ pyrepositoryminer analyze [OPTIONS] REPOSITORY [METRICS]:[blobcount|cacherate|complexity|difftokei|halstead|linecount|linelength|loc|maintainability|nesting|pylinecount|raw|seerene|tokei|touchedlines]... +$ pyrepositoryminer analyze [OPTIONS] REPOSITORY [METRICS]:[blobcount|cacherate|complexity|diffpylinecount|difftokei|halstead|linecount|linelength|loc|maintainability|nesting|pylinecount|raw|seerene|tokei|touchedlines]... ``` **Arguments**: * `REPOSITORY`: The path to the bare repository. [required] -* `[METRICS]:[blobcount|cacherate|complexity|difftokei|halstead|linecount|linelength|loc|maintainability|nesting|pylinecount|raw|seerene|tokei|touchedlines]...` +* `[METRICS]:[blobcount|cacherate|complexity|diffpylinecount|difftokei|halstead|linecount|linelength|loc|maintainability|nesting|pylinecount|raw|seerene|tokei|touchedlines]...` **Options**: diff --git a/pyrepositoryminer/metrics/diffblob/__init__.py b/pyrepositoryminer/metrics/diffblob/__init__.py index ea9b783..25538ea 100644 --- a/pyrepositoryminer/metrics/diffblob/__init__.py +++ b/pyrepositoryminer/metrics/diffblob/__init__.py @@ -1 +1,3 @@ -__all__ = () +from pyrepositoryminer.metrics.diffblob.diffpylinecount import Diffpylinecount + +__all__ = ("Diffpylinecount",) diff --git a/pyrepositoryminer/metrics/diffblob/diffpylinecount.py b/pyrepositoryminer/metrics/diffblob/diffpylinecount.py new file mode 100644 index 0000000..c7eb2e8 --- /dev/null +++ b/pyrepositoryminer/metrics/diffblob/diffpylinecount.py @@ -0,0 +1,7 @@ +from pyrepositoryminer.metrics.diffblob.main import DiffBlobMetric +from pyrepositoryminer.metrics.nativeblob.pylinecount import Pylinecount + + +class Diffpylinecount(DiffBlobMetric): + filter = Pylinecount.filter + analyze = Pylinecount.analyze From a78739667dbc653dc05ca64890a2ce3886209d10 Mon Sep 17 00:00:00 2001 From: fabianhe <39628987+fabianhe@users.noreply.github.com> Date: Mon, 26 Jul 2021 14:10:51 +0200 Subject: [PATCH 10/19] Change tokei --- .../metrics/diffdir/difftokei.py | 8 +- pyrepositoryminer/metrics/dir/tokei.py | 73 +++++++++---------- 2 files changed, 37 insertions(+), 44 deletions(-) diff --git a/pyrepositoryminer/metrics/diffdir/difftokei.py b/pyrepositoryminer/metrics/diffdir/difftokei.py index 41ed522..850eb61 100644 --- a/pyrepositoryminer/metrics/diffdir/difftokei.py +++ b/pyrepositoryminer/metrics/diffdir/difftokei.py @@ -1,10 +1,6 @@ -from typing import Iterable - from pyrepositoryminer.metrics.diffdir.main import DiffDirMetric -from pyrepositoryminer.metrics.dir.tokei import tokei -from pyrepositoryminer.metrics.structs import DirMetricInput, Metric +from pyrepositoryminer.metrics.dir.tokei import Tokei class DiffTokei(DiffDirMetric): - async def analyze(self, tup: DirMetricInput) -> Iterable[Metric]: - return await tokei(self.name, tup.path, tup.tree) + analyze = Tokei.analyze diff --git a/pyrepositoryminer/metrics/dir/tokei.py b/pyrepositoryminer/metrics/dir/tokei.py index 4bdb87a..f9233a9 100644 --- a/pyrepositoryminer/metrics/dir/tokei.py +++ b/pyrepositoryminer/metrics/dir/tokei.py @@ -6,45 +6,42 @@ from pyrepositoryminer.metrics.dir.main import DirMetric from pyrepositoryminer.metrics.structs import DirMetricInput, Metric, ObjectIdentifier from pyrepositoryminer.metrics.utils import descend_tree -from pyrepositoryminer.pobjects import Tree - - -async def tokei(name: str, path: str, tree: Tree) -> Iterable[Metric]: - p = await create_subprocess_exec("tokei", "--output", "json", path, stdout=PIPE) - stdout, _ = await p.communicate() - data = loads(bytes(stdout).decode("utf-8")) - result = [ - Metric( - name, - { - "category": category_name, - "blanks": report["stats"]["blanks"], - "code": report["stats"]["code"], - "comments": report["stats"]["comments"], - }, - False, - ObjectIdentifier( - descend_tree(tree, report["name"][len(path) + 1 :]), - report["name"][len(path) + 1 :], - ), - ) - for category_name, reports in data["Total"]["children"].items() - for report in reports - ] - result.append( - Metric( - name, - { - "blanks": data["Total"]["blanks"], - "code": data["Total"]["code"], - "comments": data["Total"]["comments"], - }, - False, - ) - ) - return result class Tokei(DirMetric): async def analyze(self, tup: DirMetricInput) -> Iterable[Metric]: - return await tokei(self.name, tup.path, tup.tree) + p = await create_subprocess_exec( + "tokei", "--output", "json", tup.path, stdout=PIPE + ) + stdout, _ = await p.communicate() + data = loads(bytes(stdout).decode("utf-8")) + result = [ + Metric( + self.name, + { + "category": category_name, + "blanks": report["stats"]["blanks"], + "code": report["stats"]["code"], + "comments": report["stats"]["comments"], + }, + False, + ObjectIdentifier( + descend_tree(tup.tree, report["name"][len(tup.path) + 1 :]), + report["name"][len(tup.path) + 1 :], + ), + ) + for category_name, reports in data["Total"]["children"].items() + for report in reports + ] + result.append( + Metric( + self.name, + { + "blanks": data["Total"]["blanks"], + "code": data["Total"]["code"], + "comments": data["Total"]["comments"], + }, + False, + ) + ) + return result From 8e8e05e1346b423c1e79c04c84f5eb3b6605b962 Mon Sep 17 00:00:00 2001 From: fabianhe <39628987+fabianhe@users.noreply.github.com> Date: Mon, 26 Jul 2021 14:13:28 +0200 Subject: [PATCH 11/19] Update dependencies --- poetry.lock | 60 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/poetry.lock b/poetry.lock index e3e1189..6a90bd1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -8,7 +8,7 @@ python-versions = "*" [[package]] name = "astroid" -version = "2.6.2" +version = "2.6.5" description = "An abstract syntax tree for Python with inference support." category = "dev" optional = false @@ -54,7 +54,7 @@ testing = ["pytest (>=4.6)", "pytest-flake8", "pytest-cov", "pytest-black (>=0.3 [[package]] name = "black" -version = "21.6b0" +version = "21.7b0" description = "The uncompromising code formatter." category = "dev" optional = false @@ -66,7 +66,7 @@ click = ">=7.1.2" mypy-extensions = ">=0.4.3" pathspec = ">=0.8.1,<1" regex = ">=2020.1.8" -toml = ">=0.10.1" +tomli = ">=0.2.6,<2.0.0" [package.extras] colorama = ["colorama (>=0.4.3)"] @@ -280,19 +280,23 @@ pyparsing = ">=2.0.2" [[package]] name = "pathspec" -version = "0.8.1" +version = "0.9.0" description = "Utility library for gitignore style pattern matching of file paths." category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [[package]] name = "platformdirs" -version = "2.0.2" +version = "2.1.0" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.6" + +[package.extras] +docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] +test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] [[package]] name = "pluggy" @@ -366,14 +370,14 @@ cffi = ">=1.4.0" [[package]] name = "pylint" -version = "2.9.3" +version = "2.9.5" description = "python code static checker" category = "dev" optional = false python-versions = "~=3.6" [package.dependencies] -astroid = ">=2.6.2,<2.7" +astroid = ">=2.6.5,<2.7" colorama = {version = "*", markers = "sys_platform == \"win32\""} isort = ">=4.2.5,<6" mccabe = ">=0.6,<0.7" @@ -463,6 +467,14 @@ category = "dev" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +[[package]] +name = "tomli" +version = "1.1.0" +description = "A lil' TOML parser" +category = "dev" +optional = false +python-versions = ">=3.6" + [[package]] name = "typed-ast" version = "1.4.3" @@ -527,7 +539,7 @@ test = ["aiohttp", "flake8 (>=3.8.4,<3.9.0)", "psutil", "pycodestyle (>=2.6.0,<2 [[package]] name = "virtualenv" -version = "20.5.0" +version = "20.6.0" description = "Virtual Python Environment builder" category = "dev" optional = false @@ -583,8 +595,8 @@ appdirs = [ {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, ] astroid = [ - {file = "astroid-2.6.2-py3-none-any.whl", hash = "sha256:606b2911d10c3dcf35e58d2ee5c97360e8477d7b9f3efc3f24811c93e6fc2cd9"}, - {file = "astroid-2.6.2.tar.gz", hash = "sha256:38b95085e9d92e2ca06cf8b35c12a74fa81da395a6f9e65803742e6509c05892"}, + {file = "astroid-2.6.5-py3-none-any.whl", hash = "sha256:7b963d1c590d490f60d2973e57437115978d3a2529843f160b5003b721e1e925"}, + {file = "astroid-2.6.5.tar.gz", hash = "sha256:83e494b02d75d07d4e347b27c066fd791c0c74fc96c613d1ea3de0c82c48168f"}, ] atomicwrites = [ {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, @@ -599,8 +611,8 @@ attrs = [ {file = "backports.entry_points_selectable-1.1.0.tar.gz", hash = "sha256:988468260ec1c196dab6ae1149260e2f5472c9110334e5d51adcb77867361f6a"}, ] black = [ - {file = "black-21.6b0-py3-none-any.whl", hash = "sha256:dfb8c5a069012b2ab1e972e7b908f5fb42b6bbabcba0a788b86dc05067c7d9c7"}, - {file = "black-21.6b0.tar.gz", hash = "sha256:dc132348a88d103016726fe360cb9ede02cecf99b76e3660ce6c596be132ce04"}, + {file = "black-21.7b0-py3-none-any.whl", hash = "sha256:1c7aa6ada8ee864db745b22790a32f94b2795c253a75d6d9b5e439ff10d23116"}, + {file = "black-21.7b0.tar.gz", hash = "sha256:c8373c6491de9362e39271630b65b964607bc5c79c83783547d76c839b3aa219"}, ] cffi = [ {file = "cffi-1.14.6-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:22b9c3c320171c108e903d61a3723b51e37aaa8c81255b5e7ce102775bd01e2c"}, @@ -760,12 +772,12 @@ packaging = [ {file = "packaging-21.0.tar.gz", hash = "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7"}, ] pathspec = [ - {file = "pathspec-0.8.1-py2.py3-none-any.whl", hash = "sha256:aa0cb481c4041bf52ffa7b0d8fa6cd3e88a2ca4879c533c9153882ee2556790d"}, - {file = "pathspec-0.8.1.tar.gz", hash = "sha256:86379d6b86d75816baba717e64b1a3a3469deb93bb76d613c9ce79edc5cb68fd"}, + {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, + {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, ] platformdirs = [ - {file = "platformdirs-2.0.2-py2.py3-none-any.whl", hash = "sha256:0b9547541f599d3d242078ae60b927b3e453f0ad52f58b4d4bc3be86aed3ec41"}, - {file = "platformdirs-2.0.2.tar.gz", hash = "sha256:3b00d081227d9037bbbca521a5787796b5ef5000faea1e43fd76f1d44b06fcfa"}, + {file = "platformdirs-2.1.0-py3-none-any.whl", hash = "sha256:b2b30ae52404f93e2024e85bba29329b85715d6b2f18ffe90ecd25a5c67553df"}, + {file = "platformdirs-2.1.0.tar.gz", hash = "sha256:1964be5aba107a7ccb7de0e6f1f1bfde0dee51641f0e733028121f8e02e2e16b"}, ] pluggy = [ {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, @@ -815,8 +827,8 @@ pygit2 = [ {file = "pygit2-1.6.1.tar.gz", hash = "sha256:c3303776f774d3e0115c1c4f6e1fc35470d15f113a7ae9401a0b90acfa1661ac"}, ] pylint = [ - {file = "pylint-2.9.3-py3-none-any.whl", hash = "sha256:5d46330e6b8886c31b5e3aba5ff48c10f4aa5e76cbf9002c6544306221e63fbc"}, - {file = "pylint-2.9.3.tar.gz", hash = "sha256:23a1dc8b30459d78e9ff25942c61bb936108ccbe29dd9e71c01dc8274961709a"}, + {file = "pylint-2.9.5-py3-none-any.whl", hash = "sha256:748f81e5776d6273a6619506e08f1b48ff9bcb8198366a56821cf11aac14fc87"}, + {file = "pylint-2.9.5.tar.gz", hash = "sha256:1f333dc72ef7f5ea166b3230936ebcfb1f3b722e76c980cb9fe6b9f95e8d3172"}, ] pyparsing = [ {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, @@ -916,6 +928,10 @@ toml = [ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, ] +tomli = [ + {file = "tomli-1.1.0-py3-none-any.whl", hash = "sha256:f4a182048010e89cbec0ae4686b21f550a7f2903f665e34a6de58ec15424f919"}, + {file = "tomli-1.1.0.tar.gz", hash = "sha256:33d7984738f8bb699c9b0a816eb646a8178a69eaa792d258486776a5d21b8ca5"}, +] typed-ast = [ {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6"}, {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c907f561b1e83e93fad565bac5ba9c22d96a54e7ea0267c708bffe863cbe4075"}, @@ -974,8 +990,8 @@ uvloop = [ {file = "uvloop-0.15.3.tar.gz", hash = "sha256:905f0adb0c09c9f44222ee02f6b96fd88b493478fffb7a345287f9444e926030"}, ] virtualenv = [ - {file = "virtualenv-20.5.0-py2.py3-none-any.whl", hash = "sha256:b7afa7f32abbf7dd4c24269a596cfbb0a422bb83c47215a785a7bf607cb88e1b"}, - {file = "virtualenv-20.5.0.tar.gz", hash = "sha256:6b0e3eeb6cb081c9c81ec85633785e29edcdf6ff271d70e0d1e2bd616495c08c"}, + {file = "virtualenv-20.6.0-py2.py3-none-any.whl", hash = "sha256:e4fc84337dce37ba34ef520bf2d4392b392999dbe47df992870dc23230f6b758"}, + {file = "virtualenv-20.6.0.tar.gz", hash = "sha256:51df5d8a2fad5d1b13e088ff38a433475768ff61f202356bb9812c454c20ae45"}, ] wcwidth = [ {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, From aa3b5c80a4933b2a84ee1f0778818d8c2dee3952 Mon Sep 17 00:00:00 2001 From: fabianhe <39628987+fabianhe@users.noreply.github.com> Date: Tue, 10 Aug 2021 12:00:28 +0200 Subject: [PATCH 12/19] Add scalene profiler --- poetry.lock | 130 ++++++++++++++++++++++++++++++++++++++++++++++++- pyproject.toml | 1 + 2 files changed, 130 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index 6a90bd1..ff4cdf3 100644 --- a/poetry.lock +++ b/poetry.lock @@ -101,6 +101,14 @@ category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +[[package]] +name = "cloudpickle" +version = "1.6.0" +description = "Extended pickling support for Python objects" +category = "dev" +optional = false +python-versions = ">=3.5" + [[package]] name = "colorama" version = "0.4.4" @@ -109,6 +117,17 @@ category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +[[package]] +name = "commonmark" +version = "0.9.1" +description = "Python parser for the CommonMark Markdown spec" +category = "dev" +optional = false +python-versions = "*" + +[package.extras] +test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"] + [[package]] name = "distlib" version = "0.3.2" @@ -267,6 +286,22 @@ category = "dev" optional = false python-versions = "*" +[[package]] +name = "numpy" +version = "1.21.1" +description = "NumPy is the fundamental package for array computing with Python." +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "nvidia-ml-py" +version = "11.450.51" +description = "Python Bindings for the NVIDIA Management Library" +category = "dev" +optional = false +python-versions = "*" + [[package]] name = "packaging" version = "21.0" @@ -368,6 +403,14 @@ python-versions = "*" [package.dependencies] cffi = ">=1.4.0" +[[package]] +name = "pygments" +version = "2.9.0" +description = "Pygments is a syntax highlighting package written in Python." +category = "dev" +optional = false +python-versions = ">=3.5" + [[package]] name = "pylint" version = "2.9.5" @@ -443,6 +486,36 @@ category = "dev" optional = false python-versions = "*" +[[package]] +name = "rich" +version = "10.7.0" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +category = "dev" +optional = false +python-versions = ">=3.6,<4.0" + +[package.dependencies] +colorama = ">=0.4.0,<0.5.0" +commonmark = ">=0.9.0,<0.10.0" +pygments = ">=2.6.0,<3.0.0" + +[package.extras] +jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"] + +[[package]] +name = "scalene" +version = "1.3.12" +description = "Scalene: A high-resolution, low-overhead CPU, GPU, and memory profiler for Python" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +cloudpickle = ">=1.5.0" +numpy = "*" +nvidia-ml-py = "11.450.51" +rich = ">=9.2.10" + [[package]] name = "shellingham" version = "1.4.0" @@ -587,7 +660,7 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytes [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "65c9408bb176660504dff5b1042eb8d261d8a0bc740e7cb18409ce8ded8472be" +content-hash = "9d1826bb458af750e6d7e8e14e6ad2f24c54d12f61939932ac0864b5e59b2776" [metadata.files] appdirs = [ @@ -664,10 +737,18 @@ click = [ {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"}, {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"}, ] +cloudpickle = [ + {file = "cloudpickle-1.6.0-py3-none-any.whl", hash = "sha256:3a32d0eb0bc6f4d0c57fbc4f3e3780f7a81e6fee0fa935072884d58ae8e1cc7c"}, + {file = "cloudpickle-1.6.0.tar.gz", hash = "sha256:9bc994f9e9447593bd0a45371f0e7ac7333710fcf64a4eb9834bf149f4ef2f32"}, +] colorama = [ {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, ] +commonmark = [ + {file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"}, + {file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"}, +] distlib = [ {file = "distlib-0.3.2-py2.py3-none-any.whl", hash = "sha256:23e223426b28491b1ced97dc3bbe183027419dfc7982b4fa2f05d5f3ff10711c"}, {file = "distlib-0.3.2.zip", hash = "sha256:106fef6dc37dd8c0e2c0a60d3fca3e77460a48907f335fa28420463a6f799736"}, @@ -767,6 +848,39 @@ nodeenv = [ {file = "nodeenv-1.6.0-py2.py3-none-any.whl", hash = "sha256:621e6b7076565ddcacd2db0294c0381e01fd28945ab36bcf00f41c5daf63bef7"}, {file = "nodeenv-1.6.0.tar.gz", hash = "sha256:3ef13ff90291ba2a4a7a4ff9a979b63ffdd00a464dbe04acf0ea6471517a4c2b"}, ] +numpy = [ + {file = "numpy-1.21.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38e8648f9449a549a7dfe8d8755a5979b45b3538520d1e735637ef28e8c2dc50"}, + {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:fd7d7409fa643a91d0a05c7554dd68aa9c9bb16e186f6ccfe40d6e003156e33a"}, + {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a75b4498b1e93d8b700282dc8e655b8bd559c0904b3910b144646dbbbc03e062"}, + {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1412aa0aec3e00bc23fbb8664d76552b4efde98fb71f60737c83efbac24112f1"}, + {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e46ceaff65609b5399163de5893d8f2a82d3c77d5e56d976c8b5fb01faa6b671"}, + {file = "numpy-1.21.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:c6a2324085dd52f96498419ba95b5777e40b6bcbc20088fddb9e8cbb58885e8e"}, + {file = "numpy-1.21.1-cp37-cp37m-win32.whl", hash = "sha256:73101b2a1fef16602696d133db402a7e7586654682244344b8329cdcbbb82172"}, + {file = "numpy-1.21.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7a708a79c9a9d26904d1cca8d383bf869edf6f8e7650d85dbc77b041e8c5a0f8"}, + {file = "numpy-1.21.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95b995d0c413f5d0428b3f880e8fe1660ff9396dcd1f9eedbc311f37b5652e16"}, + {file = "numpy-1.21.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:635e6bd31c9fb3d475c8f44a089569070d10a9ef18ed13738b03049280281267"}, + {file = "numpy-1.21.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4a3d5fb89bfe21be2ef47c0614b9c9c707b7362386c9a3ff1feae63e0267ccb6"}, + {file = "numpy-1.21.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8a326af80e86d0e9ce92bcc1e65c8ff88297de4fa14ee936cb2293d414c9ec63"}, + {file = "numpy-1.21.1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:791492091744b0fe390a6ce85cc1bf5149968ac7d5f0477288f78c89b385d9af"}, + {file = "numpy-1.21.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0318c465786c1f63ac05d7c4dbcecd4d2d7e13f0959b01b534ea1e92202235c5"}, + {file = "numpy-1.21.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a513bd9c1551894ee3d31369f9b07460ef223694098cf27d399513415855b68"}, + {file = "numpy-1.21.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:91c6f5fc58df1e0a3cc0c3a717bb3308ff850abdaa6d2d802573ee2b11f674a8"}, + {file = "numpy-1.21.1-cp38-cp38-win32.whl", hash = "sha256:978010b68e17150db8765355d1ccdd450f9fc916824e8c4e35ee620590e234cd"}, + {file = "numpy-1.21.1-cp38-cp38-win_amd64.whl", hash = "sha256:9749a40a5b22333467f02fe11edc98f022133ee1bfa8ab99bda5e5437b831214"}, + {file = "numpy-1.21.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d7a4aeac3b94af92a9373d6e77b37691b86411f9745190d2c351f410ab3a791f"}, + {file = "numpy-1.21.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d9e7912a56108aba9b31df688a4c4f5cb0d9d3787386b87d504762b6754fbb1b"}, + {file = "numpy-1.21.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:25b40b98ebdd272bc3020935427a4530b7d60dfbe1ab9381a39147834e985eac"}, + {file = "numpy-1.21.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8a92c5aea763d14ba9d6475803fc7904bda7decc2a0a68153f587ad82941fec1"}, + {file = "numpy-1.21.1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:05a0f648eb28bae4bcb204e6fd14603de2908de982e761a2fc78efe0f19e96e1"}, + {file = "numpy-1.21.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f01f28075a92eede918b965e86e8f0ba7b7797a95aa8d35e1cc8821f5fc3ad6a"}, + {file = "numpy-1.21.1-cp39-cp39-win32.whl", hash = "sha256:88c0b89ad1cc24a5efbb99ff9ab5db0f9a86e9cc50240177a571fbe9c2860ac2"}, + {file = "numpy-1.21.1-cp39-cp39-win_amd64.whl", hash = "sha256:01721eefe70544d548425a07c80be8377096a54118070b8a62476866d5208e33"}, + {file = "numpy-1.21.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2d4d1de6e6fb3d28781c73fbde702ac97f03d79e4ffd6598b880b2d95d62ead4"}, + {file = "numpy-1.21.1.zip", hash = "sha256:dff4af63638afcc57a3dfb9e4b26d434a7a602d225b42d746ea7fe2edf1342fd"}, +] +nvidia-ml-py = [ + {file = "nvidia-ml-py-11.450.51.tar.gz", hash = "sha256:5aa6dd23a140b1ef2314eee5ca154a45397b03e68fd9ebc4f72005979f511c73"}, +] packaging = [ {file = "packaging-21.0-py3-none-any.whl", hash = "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14"}, {file = "packaging-21.0.tar.gz", hash = "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7"}, @@ -826,6 +940,10 @@ pygit2 = [ {file = "pygit2-1.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:f90775afb11f69376e2af21ab56fcfbb52f6bc84117059ddf0355f81e5e36352"}, {file = "pygit2-1.6.1.tar.gz", hash = "sha256:c3303776f774d3e0115c1c4f6e1fc35470d15f113a7ae9401a0b90acfa1661ac"}, ] +pygments = [ + {file = "Pygments-2.9.0-py3-none-any.whl", hash = "sha256:d66e804411278594d764fc69ec36ec13d9ae9147193a1740cd34d272ca383b8e"}, + {file = "Pygments-2.9.0.tar.gz", hash = "sha256:a18f47b506a429f6f4b9df81bb02beab9ca21d0a5fee38ed15aef65f0545519f"}, +] pylint = [ {file = "pylint-2.9.5-py3-none-any.whl", hash = "sha256:748f81e5776d6273a6619506e08f1b48ff9bcb8198366a56821cf11aac14fc87"}, {file = "pylint-2.9.5.tar.gz", hash = "sha256:1f333dc72ef7f5ea166b3230936ebcfb1f3b722e76c980cb9fe6b9f95e8d3172"}, @@ -916,6 +1034,16 @@ regex = [ {file = "regex-2021.7.6-cp39-cp39-win_amd64.whl", hash = "sha256:4c9c3155fe74269f61e27617529b7f09552fbb12e44b1189cebbdb24294e6e1c"}, {file = "regex-2021.7.6.tar.gz", hash = "sha256:8394e266005f2d8c6f0bc6780001f7afa3ef81a7a2111fa35058ded6fce79e4d"}, ] +rich = [ + {file = "rich-10.7.0-py3-none-any.whl", hash = "sha256:517b4e0efd064dd1fe821ca93dd3095d73380ceac1f0a07173d507d9b18f1396"}, + {file = "rich-10.7.0.tar.gz", hash = "sha256:13ac80676e12cf528dc4228dc682c8402f82577c2aa67191e294350fa2c3c4e9"}, +] +scalene = [ + {file = "scalene-1.3.12-cp37-abi3-macosx_10_14_universal2.whl", hash = "sha256:85a033b4af6372662f3f328668d021ea1127a763746310244f500b88fb16c288"}, + {file = "scalene-1.3.12-cp37-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:4244cf794dd5e6520abac3ea0131f87b3fff595277a44dbe15296c61499c6421"}, + {file = "scalene-1.3.12-cp38-abi3-win_amd64.whl", hash = "sha256:da019fc9968c3e47b431b806a28dd157d919fe4db184022a0c73f0e720a2bfb3"}, + {file = "scalene-1.3.12.tar.gz", hash = "sha256:32139ea505601a44e3806431d09aee2c9e9c15d67f92a6f2857cf61f35d6f7fd"}, +] shellingham = [ {file = "shellingham-1.4.0-py2.py3-none-any.whl", hash = "sha256:536b67a0697f2e4af32ab176c00a50ac2899c5a05e0d8e2dadac8e58888283f9"}, {file = "shellingham-1.4.0.tar.gz", hash = "sha256:4855c2458d6904829bd34c299f11fdeed7cfefbf8a2c522e4caea6cd76b3171e"}, diff --git a/pyproject.toml b/pyproject.toml index 752408a..46feed7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,6 +28,7 @@ isort = "^5.8.0" pre-commit = "^2.12.1" typer-cli = "^0.0.11" pylint = "^2.9.3" +scalene = "^1.3.12" [build-system] requires = ["poetry-core>=1.0.0"] From e9dc2ad0a5e82e6035ce72d0edc93b24d474c643 Mon Sep 17 00:00:00 2001 From: fabianhe <39628987+fabianhe@users.noreply.github.com> Date: Tue, 10 Aug 2021 12:00:49 +0200 Subject: [PATCH 13/19] Use print instead of echo --- pyrepositoryminer/commands/analyze.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyrepositoryminer/commands/analyze.py b/pyrepositoryminer/commands/analyze.py index 287e28f..16c1a41 100644 --- a/pyrepositoryminer/commands/analyze.py +++ b/pyrepositoryminer/commands/analyze.py @@ -89,4 +89,4 @@ def analyze( ) as pool: results = (res for res in pool.imap(worker, ids) if res is not None) for result in results: - echo(result) + print(result) From cc64139580938c53f060ea0e3ef8216b0a58730d Mon Sep 17 00:00:00 2001 From: fabianhe <39628987+fabianhe@users.noreply.github.com> Date: Tue, 10 Aug 2021 12:01:14 +0200 Subject: [PATCH 14/19] Fix touchedfiles bug --- pyrepositoryminer/metrics/utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyrepositoryminer/metrics/utils.py b/pyrepositoryminer/metrics/utils.py index 1fceb00..b221b64 100644 --- a/pyrepositoryminer/metrics/utils.py +++ b/pyrepositoryminer/metrics/utils.py @@ -15,6 +15,7 @@ def get_touchedfiles(commit: Commit) -> FrozenSet[DiffFile]: delta.new_file for parent in commit.parents for delta in commit.tree.obj.diff_to_tree(parent.tree.obj, swap=True).deltas + if delta.status_char() != "D" ) From 9a953a9e99aeacace873a1ba4f686f04d824f64e Mon Sep 17 00:00:00 2001 From: fabianhe <39628987+fabianhe@users.noreply.github.com> Date: Tue, 10 Aug 2021 12:27:59 +0200 Subject: [PATCH 15/19] Defer imports --- pyrepositoryminer/commands/analyze.py | 105 ++++++++----------- pyrepositoryminer/commands/branch.py | 6 +- pyrepositoryminer/commands/clone.py | 4 +- pyrepositoryminer/commands/commits.py | 36 ++----- pyrepositoryminer/commands/utils/__init__.py | 0 pyrepositoryminer/commands/utils/commits.py | 28 +++++ pyrepositoryminer/commands/utils/metric.py | 53 ++++++++++ 7 files changed, 141 insertions(+), 91 deletions(-) create mode 100644 pyrepositoryminer/commands/utils/__init__.py create mode 100644 pyrepositoryminer/commands/utils/commits.py create mode 100644 pyrepositoryminer/commands/utils/metric.py diff --git a/pyrepositoryminer/commands/analyze.py b/pyrepositoryminer/commands/analyze.py index 16c1a41..d2ff39c 100644 --- a/pyrepositoryminer/commands/analyze.py +++ b/pyrepositoryminer/commands/analyze.py @@ -1,61 +1,48 @@ -from enum import Enum -from functools import reduce -from importlib import import_module -from inspect import isclass -from multiprocessing import Pool +from contextlib import contextmanager from pathlib import Path -from sys import stdin -from typing import List, Optional +from typing import TYPE_CHECKING, Iterator, List, Optional -from typer import Abort, Argument, Option, echo +from typer import Argument, Option from typer.models import FileText -from pyrepositoryminer.analyze import InitArgs, initialize, worker -from pyrepositoryminer.metrics import all_metrics -from pyrepositoryminer.metrics.diffblob.main import DiffBlobMetric -from pyrepositoryminer.metrics.diffdir.main import DiffDirMetric -from pyrepositoryminer.metrics.dir.main import DirMetric -from pyrepositoryminer.metrics.nativeblob.main import NativeBlobMetric -from pyrepositoryminer.metrics.nativetree.main import NativeTreeMetric +from pyrepositoryminer.commands.utils.metric import AvailableMetrics -AvailableMetrics = Enum( # type: ignore - # https://github.com/python/mypy/issues/5317 - "AvailableMetrics", - [(k, k) for k in sorted(all_metrics.keys())], -) +if TYPE_CHECKING: + from multiprocessing.pool import Pool as tcpool -def import_metric(import_str: str): # type: ignore # TODO make this a metric abc - module_str, _, attrs_str = import_str.partition(":") - if not module_str or not attrs_str: - echo(f'Import string "{import_str}" must be in format ":"') - raise Abort() - try: - module = import_module(module_str) - except ImportError as e: - if e.name != module_str: - raise e from None - echo(f'Could not import module "{module_str}"') - raise Abort() from e - try: - instance = reduce(getattr, (module, *attrs_str.split("."))) # type: ignore - except AttributeError as e: - print(f'Attribute "{attrs_str}" not found in module "{module_str}"') - raise Abort() from e - if not isclass(instance): - print(f'Instance "{instance}" must be a class') - raise Abort() - parents = ( - NativeBlobMetric, - DiffBlobMetric, - NativeTreeMetric, - DirMetric, - DiffDirMetric, +@contextmanager +def make_pool( + workers: int, + repository: Path, + metrics: List[AvailableMetrics], + custom_metrics: List[str], +) -> Iterator["tcpool"]: + from multiprocessing import Pool # pylint: disable=import-outside-toplevel + + from pyrepositoryminer.analyze import ( # pylint: disable=import-outside-toplevel + InitArgs, + initialize, + ) + from pyrepositoryminer.commands.utils.metric import ( # pylint: disable=import-outside-toplevel + import_metric, + ) + from pyrepositoryminer.metrics import ( # pylint: disable=import-outside-toplevel + all_metrics, ) - if not any(issubclass(instance, parent) for parent in parents): # type: ignore - print(f'Instance "{instance}" must subclass a pyrepositoryminer metric class') - raise Abort() - return instance + + with Pool( + max(workers, 1), + initialize, + ( + InitArgs( + repository, + tuple({metric.value for metric in metrics} & all_metrics.keys()), + tuple(map(import_metric, set(custom_metrics))), + ), + ), + ) as pool: + yield pool def analyze( @@ -71,22 +58,18 @@ def analyze( """Analyze commits of a repository. Either provide the commit ids to analyze on stdin or as a file argument.""" + from sys import stdin # pylint: disable=import-outside-toplevel + + from pyrepositoryminer.analyze import ( # pylint: disable=import-outside-toplevel + worker, + ) + metrics = metrics if metrics else [] ids = ( id.strip() for id in (commits if commits else stdin) # pylint: disable=superfluous-parens ) - with Pool( - max(workers, 1), - initialize, - ( - InitArgs( - repository, - tuple({metric.value for metric in metrics} & all_metrics.keys()), - tuple(map(import_metric, set(custom_metrics))), - ), - ), - ) as pool: + with make_pool(workers, repository, metrics, custom_metrics) as pool: results = (res for res in pool.imap(worker, ids) if res is not None) for result in results: print(result) diff --git a/pyrepositoryminer/commands/branch.py b/pyrepositoryminer/commands/branch.py index cc685f7..30b282d 100644 --- a/pyrepositoryminer/commands/branch.py +++ b/pyrepositoryminer/commands/branch.py @@ -1,8 +1,7 @@ from pathlib import Path from typing import Iterable -from pygit2 import Repository -from typer import Argument, echo +from typer import Argument def branch( @@ -11,6 +10,9 @@ def branch( remote: bool = False, ) -> None: """Get the branches of a repository.""" + from pygit2 import Repository # pylint: disable=import-outside-toplevel + from typer import echo # pylint: disable=import-outside-toplevel + repo = Repository(repository) branches: Iterable[str] if local and remote: diff --git a/pyrepositoryminer/commands/clone.py b/pyrepositoryminer/commands/clone.py index 784da07..4ec89e4 100644 --- a/pyrepositoryminer/commands/clone.py +++ b/pyrepositoryminer/commands/clone.py @@ -1,8 +1,8 @@ from pathlib import Path -from pygit2 import clone_repository - def clone(url: str, path: Path, bare: bool = True) -> None: "Clone a repository to a path." + from pygit2 import clone_repository # pylint: disable=import-outside-toplevel + clone_repository(url, path, bare=bare) diff --git a/pyrepositoryminer/commands/commits.py b/pyrepositoryminer/commands/commits.py index df12571..b05b033 100644 --- a/pyrepositoryminer/commands/commits.py +++ b/pyrepositoryminer/commands/commits.py @@ -1,8 +1,8 @@ from enum import Enum -from itertools import filterfalse, islice +from itertools import islice from pathlib import Path from sys import stdin -from typing import Hashable, Iterable, Optional, Set, TypeVar +from typing import Hashable, Iterable, Optional, TypeVar from pygit2 import ( GIT_SORT_NONE, @@ -10,9 +10,8 @@ GIT_SORT_TIME, GIT_SORT_TOPOLOGICAL, Repository, - Walker, ) -from typer import Argument, Option, echo +from typer import Argument, Option class Sort(str, Enum): @@ -36,28 +35,6 @@ def flag(self): # type: ignore T = TypeVar("T", bound=Hashable) -def iter_distinct(iterable: Iterable[T]) -> Iterable[T]: - seen: Set[T] = set() - for element in filterfalse(seen.__contains__, iterable): - seen.add(element) - yield element - - -def generate_walkers( - repo: Repository, - branch_names: Iterable[str], - simplify_first_parent: bool, - sorting: int, -) -> Iterable[Walker]: - walkers = tuple( - repo.walk(repo.branches[branch_name].peel().id, sorting) - for branch_name in branch_names - ) - for walker in walkers if simplify_first_parent else tuple(): - walker.simplify_first_parent() - yield from walkers - - def commits( repository: Path = Argument(..., help="The path to the bare repository."), branches: Path = Argument( @@ -79,6 +56,13 @@ def commits( """Get the commit ids of a repository. Either provide the branches to get the commit ids from on stdin or as a file argument.""" # pylint: disable=line-too-long + from typer import echo # pylint: disable=import-outside-toplevel + + from pyrepositoryminer.commands.utils.commits import ( # pylint: disable=import-outside-toplevel + generate_walkers, + iter_distinct, + ) + branch_names: Iterable[str] if branches != Path("-"): with open(branches) as f: diff --git a/pyrepositoryminer/commands/utils/__init__.py b/pyrepositoryminer/commands/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyrepositoryminer/commands/utils/commits.py b/pyrepositoryminer/commands/utils/commits.py new file mode 100644 index 0000000..bcd97f0 --- /dev/null +++ b/pyrepositoryminer/commands/utils/commits.py @@ -0,0 +1,28 @@ +from itertools import filterfalse +from typing import Hashable, Iterable, Set, TypeVar + +from pygit2 import Repository, Walker + +T = TypeVar("T", bound=Hashable) + + +def iter_distinct(iterable: Iterable[T]) -> Iterable[T]: + seen: Set[T] = set() + for element in filterfalse(seen.__contains__, iterable): + seen.add(element) + yield element + + +def generate_walkers( + repo: Repository, + branch_names: Iterable[str], + simplify_first_parent: bool, + sorting: int, +) -> Iterable[Walker]: + walkers = tuple( + repo.walk(repo.branches[branch_name].peel().id, sorting) + for branch_name in branch_names + ) + for walker in walkers if simplify_first_parent else tuple(): + walker.simplify_first_parent() + yield from walkers diff --git a/pyrepositoryminer/commands/utils/metric.py b/pyrepositoryminer/commands/utils/metric.py new file mode 100644 index 0000000..64ab953 --- /dev/null +++ b/pyrepositoryminer/commands/utils/metric.py @@ -0,0 +1,53 @@ +from enum import Enum +from functools import reduce +from inspect import isclass + +from typer import Abort, echo + +from pyrepositoryminer.metrics import all_metrics +from pyrepositoryminer.metrics.diffblob.main import DiffBlobMetric +from pyrepositoryminer.metrics.diffdir.main import DiffDirMetric +from pyrepositoryminer.metrics.dir.main import DirMetric +from pyrepositoryminer.metrics.nativeblob.main import NativeBlobMetric +from pyrepositoryminer.metrics.nativetree.main import NativeTreeMetric + +AvailableMetrics = Enum( # type: ignore + # https://github.com/python/mypy/issues/5317 + "AvailableMetrics", + [(k, k) for k in sorted(all_metrics.keys())], +) + + +def import_metric(import_str: str): # type: ignore # TODO make this a metric abc + from importlib import import_module # pylint: disable=import-outside-toplevel + + module_str, _, attrs_str = import_str.partition(":") + if not module_str or not attrs_str: + echo(f'Import string "{import_str}" must be in format ":"') + raise Abort() + try: + module = import_module(module_str) + except ImportError as e: + if e.name != module_str: + raise e from None + echo(f'Could not import module "{module_str}"') + raise Abort() from e + try: + instance = reduce(getattr, (module, *attrs_str.split("."))) # type: ignore + except AttributeError as e: + print(f'Attribute "{attrs_str}" not found in module "{module_str}"') + raise Abort() from e + if not isclass(instance): + print(f'Instance "{instance}" must be a class') + raise Abort() + parents = ( + NativeBlobMetric, + DiffBlobMetric, + NativeTreeMetric, + DirMetric, + DiffDirMetric, + ) + if not any(issubclass(instance, parent) for parent in parents): # type: ignore + print(f'Instance "{instance}" must subclass a pyrepositoryminer metric class') + raise Abort() + return instance From 4f1f0b69bc9e074b9900004299fe40cdc1890b0e Mon Sep 17 00:00:00 2001 From: fabianhe <39628987+fabianhe@users.noreply.github.com> Date: Tue, 10 Aug 2021 13:24:56 +0200 Subject: [PATCH 16/19] Fix analyze script --- scripts/profile_analyze.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/profile_analyze.py b/scripts/profile_analyze.py index b960ae9..f684d45 100644 --- a/scripts/profile_analyze.py +++ b/scripts/profile_analyze.py @@ -4,7 +4,8 @@ from typer import FileText -from pyrepositoryminer.commands.analyze import AvailableMetrics, analyze +from pyrepositoryminer.commands.analyze import analyze +from pyrepositoryminer.commands.utils.metric import AvailableMetrics def main() -> None: From 3121f2ec14d8f4c235ca2752f70cc896ef7bc845 Mon Sep 17 00:00:00 2001 From: fabianhe <39628987+fabianhe@users.noreply.github.com> Date: Tue, 10 Aug 2021 13:25:29 +0200 Subject: [PATCH 17/19] Add measure_pylinecount --- scripts/measure_pylinecount.sh | 1 + 1 file changed, 1 insertion(+) create mode 100644 scripts/measure_pylinecount.sh diff --git a/scripts/measure_pylinecount.sh b/scripts/measure_pylinecount.sh new file mode 100644 index 0000000..1a87637 --- /dev/null +++ b/scripts/measure_pylinecount.sh @@ -0,0 +1 @@ +hyperfine --warmup 1 --runs 3 --export-json out_02_01.json --parameter-list repo numpy,pandas,matplotlib,tensorflow 'pyrepositoryminer branch ./{repo}.git | pyrepositoryminer commits --limit 100 ./{repo}.git | pyrepositoryminer analyze ./{repo}.git pylinecount' \ No newline at end of file From fd3e893fde05e5d34c8b767b7c8a9cb61e964910 Mon Sep 17 00:00:00 2001 From: fabianhe <39628987+fabianhe@users.noreply.github.com> Date: Tue, 28 Sep 2021 18:32:03 +0200 Subject: [PATCH 18/19] Update dependencies --- poetry.lock | 224 ++++++++++++++++++++++++++-------------------------- 1 file changed, 112 insertions(+), 112 deletions(-) diff --git a/poetry.lock b/poetry.lock index ff4cdf3..e3ceb9b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,14 +1,6 @@ -[[package]] -name = "appdirs" -version = "1.4.4" -description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" -optional = false -python-versions = "*" - [[package]] name = "astroid" -version = "2.6.5" +version = "2.8.0" description = "An abstract syntax tree for Python with inference support." category = "dev" optional = false @@ -16,6 +8,7 @@ python-versions = "~=3.6" [package.dependencies] lazy-object-proxy = ">=1.4.0" +typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""} wrapt = ">=1.11,<1.13" [[package]] @@ -54,23 +47,28 @@ testing = ["pytest (>=4.6)", "pytest-flake8", "pytest-cov", "pytest-black (>=0.3 [[package]] name = "black" -version = "21.7b0" +version = "21.9b0" description = "The uncompromising code formatter." category = "dev" optional = false python-versions = ">=3.6.2" [package.dependencies] -appdirs = "*" click = ">=7.1.2" mypy-extensions = ">=0.4.3" -pathspec = ">=0.8.1,<1" +pathspec = ">=0.9.0,<1" +platformdirs = ">=2" regex = ">=2020.1.8" tomli = ">=0.2.6,<2.0.0" +typing-extensions = [ + {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}, + {version = "!=3.10.0.1", markers = "python_version >= \"3.10\""}, +] [package.extras] colorama = ["colorama (>=0.4.3)"] d = ["aiohttp (>=3.6.0)", "aiohttp-cors (>=0.4.0)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] python2 = ["typed-ast (>=1.4.2)"] uvloop = ["uvloop (>=0.15.2)"] @@ -87,7 +85,7 @@ pycparser = "*" [[package]] name = "cfgv" -version = "3.3.0" +version = "3.3.1" description = "Validate configuration and produce human readable error messages." category = "dev" optional = false @@ -103,11 +101,11 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "cloudpickle" -version = "1.6.0" +version = "2.0.0" description = "Extended pickling support for Python objects" category = "dev" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" [[package]] name = "colorama" @@ -130,7 +128,7 @@ test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"] [[package]] name = "distlib" -version = "0.3.2" +version = "0.3.3" description = "Distribution utilities" category = "dev" optional = false @@ -138,11 +136,15 @@ python-versions = "*" [[package]] name = "filelock" -version = "3.0.12" +version = "3.1.0" description = "A platform independent file lock." category = "dev" optional = false -python-versions = "*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" + +[package.extras] +docs = ["furo (>=2021.8.17b43)", "sphinx (>=4.1)", "sphinx-autodoc-typehints (>=1.12)"] +testing = ["coverage (>=4)", "pytest (>=4)", "pytest-cov"] [[package]] name = "flake8" @@ -178,7 +180,7 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "identify" -version = "2.2.11" +version = "2.2.15" description = "File identification library for Python" category = "dev" optional = false @@ -204,7 +206,7 @@ testing = ["packaging", "pep517", "unittest2", "importlib-resources (>=1.3)"] [[package]] name = "isort" -version = "5.9.2" +version = "5.9.3" description = "A Python utility / library to sort Python imports." category = "dev" optional = false @@ -248,7 +250,7 @@ python-versions = "*" [[package]] name = "more-itertools" -version = "8.8.0" +version = "8.10.0" description = "More routines for operating on iterables, beyond itertools" category = "dev" optional = false @@ -323,7 +325,7 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [[package]] name = "platformdirs" -version = "2.1.0" +version = "2.4.0" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false @@ -346,7 +348,7 @@ dev = ["pre-commit", "tox"] [[package]] name = "pre-commit" -version = "2.13.0" +version = "2.15.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." category = "dev" optional = false @@ -405,7 +407,7 @@ cffi = ">=1.4.0" [[package]] name = "pygments" -version = "2.9.0" +version = "2.10.0" description = "Pygments is a syntax highlighting package written in Python." category = "dev" optional = false @@ -413,18 +415,20 @@ python-versions = ">=3.5" [[package]] name = "pylint" -version = "2.9.5" +version = "2.11.1" description = "python code static checker" category = "dev" optional = false python-versions = "~=3.6" [package.dependencies] -astroid = ">=2.6.5,<2.7" +astroid = ">=2.8.0,<2.9" colorama = {version = "*", markers = "sys_platform == \"win32\""} isort = ">=4.2.5,<6" mccabe = ">=0.6,<0.7" +platformdirs = ">=2.2.0" toml = ">=0.7.1" +typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} [[package]] name = "pyparsing" @@ -480,7 +484,7 @@ mando = ">=0.6,<0.7" [[package]] name = "regex" -version = "2021.7.6" +version = "2021.9.24" description = "Alternative regular expression module, to replace re." category = "dev" optional = false @@ -488,7 +492,7 @@ python-versions = "*" [[package]] name = "rich" -version = "10.7.0" +version = "10.11.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" category = "dev" optional = false @@ -542,7 +546,7 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "tomli" -version = "1.1.0" +version = "1.2.1" description = "A lil' TOML parser" category = "dev" optional = false @@ -591,7 +595,7 @@ typer = ">=0.3.0,<0.4.0" [[package]] name = "typing-extensions" -version = "3.10.0.0" +version = "3.10.0.2" description = "Backported and Experimental Type Hints for Python 3.5+" category = "dev" optional = false @@ -612,7 +616,7 @@ test = ["aiohttp", "flake8 (>=3.8.4,<3.9.0)", "psutil", "pycodestyle (>=2.6.0,<2 [[package]] name = "virtualenv" -version = "20.6.0" +version = "20.8.1" description = "Virtual Python Environment builder" category = "dev" optional = false @@ -627,7 +631,7 @@ six = ">=1.9.0,<2" [package.extras] docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=19.9.0rc1)"] -testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)", "xonsh (>=0.9.16)"] +testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)"] [[package]] name = "wcwidth" @@ -663,13 +667,9 @@ python-versions = "^3.9" content-hash = "9d1826bb458af750e6d7e8e14e6ad2f24c54d12f61939932ac0864b5e59b2776" [metadata.files] -appdirs = [ - {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, - {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, -] astroid = [ - {file = "astroid-2.6.5-py3-none-any.whl", hash = "sha256:7b963d1c590d490f60d2973e57437115978d3a2529843f160b5003b721e1e925"}, - {file = "astroid-2.6.5.tar.gz", hash = "sha256:83e494b02d75d07d4e347b27c066fd791c0c74fc96c613d1ea3de0c82c48168f"}, + {file = "astroid-2.8.0-py3-none-any.whl", hash = "sha256:dcc06f6165f415220013801642bd6c9808a02967070919c4b746c6864c205471"}, + {file = "astroid-2.8.0.tar.gz", hash = "sha256:fe81f80c0b35264acb5653302ffbd935d394f1775c5e4487df745bf9c2442708"}, ] atomicwrites = [ {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, @@ -684,8 +684,8 @@ attrs = [ {file = "backports.entry_points_selectable-1.1.0.tar.gz", hash = "sha256:988468260ec1c196dab6ae1149260e2f5472c9110334e5d51adcb77867361f6a"}, ] black = [ - {file = "black-21.7b0-py3-none-any.whl", hash = "sha256:1c7aa6ada8ee864db745b22790a32f94b2795c253a75d6d9b5e439ff10d23116"}, - {file = "black-21.7b0.tar.gz", hash = "sha256:c8373c6491de9362e39271630b65b964607bc5c79c83783547d76c839b3aa219"}, + {file = "black-21.9b0-py3-none-any.whl", hash = "sha256:380f1b5da05e5a1429225676655dddb96f5ae8c75bdf91e53d798871b902a115"}, + {file = "black-21.9b0.tar.gz", hash = "sha256:7de4cfc7eb6b710de325712d40125689101d21d25283eed7e9998722cf10eb91"}, ] cffi = [ {file = "cffi-1.14.6-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:22b9c3c320171c108e903d61a3723b51e37aaa8c81255b5e7ce102775bd01e2c"}, @@ -730,16 +730,16 @@ cffi = [ {file = "cffi-1.14.6.tar.gz", hash = "sha256:c9a875ce9d7fe32887784274dd533c57909b7b1dcadcc128a2ac21331a9765dd"}, ] cfgv = [ - {file = "cfgv-3.3.0-py2.py3-none-any.whl", hash = "sha256:b449c9c6118fe8cca7fa5e00b9ec60ba08145d281d52164230a69211c5d597a1"}, - {file = "cfgv-3.3.0.tar.gz", hash = "sha256:9e600479b3b99e8af981ecdfc80a0296104ee610cab48a5ae4ffd0b668650eb1"}, + {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"}, + {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, ] click = [ {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"}, {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"}, ] cloudpickle = [ - {file = "cloudpickle-1.6.0-py3-none-any.whl", hash = "sha256:3a32d0eb0bc6f4d0c57fbc4f3e3780f7a81e6fee0fa935072884d58ae8e1cc7c"}, - {file = "cloudpickle-1.6.0.tar.gz", hash = "sha256:9bc994f9e9447593bd0a45371f0e7ac7333710fcf64a4eb9834bf149f4ef2f32"}, + {file = "cloudpickle-2.0.0-py3-none-any.whl", hash = "sha256:6b2df9741d06f43839a3275c4e6632f7df6487a1f181f5f46a052d3c917c3d11"}, + {file = "cloudpickle-2.0.0.tar.gz", hash = "sha256:5cd02f3b417a783ba84a4ec3e290ff7929009fe51f6405423cfccfadd43ba4a4"}, ] colorama = [ {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, @@ -750,12 +750,12 @@ commonmark = [ {file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"}, ] distlib = [ - {file = "distlib-0.3.2-py2.py3-none-any.whl", hash = "sha256:23e223426b28491b1ced97dc3bbe183027419dfc7982b4fa2f05d5f3ff10711c"}, - {file = "distlib-0.3.2.zip", hash = "sha256:106fef6dc37dd8c0e2c0a60d3fca3e77460a48907f335fa28420463a6f799736"}, + {file = "distlib-0.3.3-py2.py3-none-any.whl", hash = "sha256:c8b54e8454e5bf6237cc84c20e8264c3e991e824ef27e8f1e81049867d861e31"}, + {file = "distlib-0.3.3.zip", hash = "sha256:d982d0751ff6eaaab5e2ec8e691d949ee80eddf01a62eaa96ddb11531fe16b05"}, ] filelock = [ - {file = "filelock-3.0.12-py3-none-any.whl", hash = "sha256:929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836"}, - {file = "filelock-3.0.12.tar.gz", hash = "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59"}, + {file = "filelock-3.1.0-py2.py3-none-any.whl", hash = "sha256:d9e9c7d8191e915339843c81c90d3e44f7c84e5fb03bdc6b1b4d019025cf953b"}, + {file = "filelock-3.1.0.tar.gz", hash = "sha256:78925788ce8c8945fac28a68c1d05cf33a6a6c4fba14fe02835122c53268ceef"}, ] flake8 = [ {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"}, @@ -769,16 +769,16 @@ future = [ {file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"}, ] identify = [ - {file = "identify-2.2.11-py2.py3-none-any.whl", hash = "sha256:7abaecbb414e385752e8ce02d8c494f4fbc780c975074b46172598a28f1ab839"}, - {file = "identify-2.2.11.tar.gz", hash = "sha256:a0e700637abcbd1caae58e0463861250095dfe330a8371733a471af706a4a29a"}, + {file = "identify-2.2.15-py2.py3-none-any.whl", hash = "sha256:de83a84d774921669774a2000bf87ebba46b4d1c04775f4a5d37deff0cf39f73"}, + {file = "identify-2.2.15.tar.gz", hash = "sha256:528a88021749035d5a39fe2ba67c0642b8341aaf71889da0e1ed669a429b87f0"}, ] importlib-metadata = [ {file = "importlib_metadata-2.1.1-py2.py3-none-any.whl", hash = "sha256:c2d6341ff566f609e89a2acb2db190e5e1d23d5409d6cc8d2fe34d72443876d4"}, {file = "importlib_metadata-2.1.1.tar.gz", hash = "sha256:b8de9eff2b35fb037368f28a7df1df4e6436f578fa74423505b6c6a778d5b5dd"}, ] isort = [ - {file = "isort-5.9.2-py3-none-any.whl", hash = "sha256:eed17b53c3e7912425579853d078a0832820f023191561fcee9d7cae424e0813"}, - {file = "isort-5.9.2.tar.gz", hash = "sha256:f65ce5bd4cbc6abdfbe29afc2f0245538ab358c14590912df638033f157d555e"}, + {file = "isort-5.9.3-py3-none-any.whl", hash = "sha256:e17d6e2b81095c9db0a03a8025a957f334d6ea30b26f9ec70805411e5c7c81f2"}, + {file = "isort-5.9.3.tar.gz", hash = "sha256:9c2ea1e62d871267b78307fe511c0838ba0da28698c5732d54e2790bf3ba9899"}, ] lazy-object-proxy = [ {file = "lazy-object-proxy-1.6.0.tar.gz", hash = "sha256:489000d368377571c6f982fba6497f2aa13c6d1facc40660963da62f5c379726"}, @@ -813,8 +813,8 @@ mccabe = [ {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, ] more-itertools = [ - {file = "more-itertools-8.8.0.tar.gz", hash = "sha256:83f0308e05477c68f56ea3a888172c78ed5d5b3c282addb67508e7ba6c8f813a"}, - {file = "more_itertools-8.8.0-py3-none-any.whl", hash = "sha256:2cf89ec599962f2ddc4d568a05defc40e0a587fbc10d5989713638864c36be4d"}, + {file = "more-itertools-8.10.0.tar.gz", hash = "sha256:1debcabeb1df793814859d64a81ad7cb10504c24349368ccf214c664c474f41f"}, + {file = "more_itertools-8.10.0-py3-none-any.whl", hash = "sha256:56ddac45541718ba332db05f464bebfb0768110111affd27f66e0051f276fa43"}, ] mypy = [ {file = "mypy-0.812-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:a26f8ec704e5a7423c8824d425086705e381b4f1dfdef6e3a1edab7ba174ec49"}, @@ -890,16 +890,16 @@ pathspec = [ {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, ] platformdirs = [ - {file = "platformdirs-2.1.0-py3-none-any.whl", hash = "sha256:b2b30ae52404f93e2024e85bba29329b85715d6b2f18ffe90ecd25a5c67553df"}, - {file = "platformdirs-2.1.0.tar.gz", hash = "sha256:1964be5aba107a7ccb7de0e6f1f1bfde0dee51641f0e733028121f8e02e2e16b"}, + {file = "platformdirs-2.4.0-py3-none-any.whl", hash = "sha256:8868bbe3c3c80d42f20156f22e7131d2fb321f5bc86a2a345375c6481a67021d"}, + {file = "platformdirs-2.4.0.tar.gz", hash = "sha256:367a5e80b3d04d2428ffa76d33f124cf11e8fff2acdaa9b43d545f5c7d661ef2"}, ] pluggy = [ {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, ] pre-commit = [ - {file = "pre_commit-2.13.0-py2.py3-none-any.whl", hash = "sha256:b679d0fddd5b9d6d98783ae5f10fd0c4c59954f375b70a58cbe1ce9bcf9809a4"}, - {file = "pre_commit-2.13.0.tar.gz", hash = "sha256:764972c60693dc668ba8e86eb29654ec3144501310f7198742a767bec385a378"}, + {file = "pre_commit-2.15.0-py2.py3-none-any.whl", hash = "sha256:a4ed01000afcb484d9eb8d504272e642c4c4099bbad3a6b27e519bd6a3e928a6"}, + {file = "pre_commit-2.15.0.tar.gz", hash = "sha256:3c25add78dbdfb6a28a651780d5c311ac40dd17f160eb3954a0c59da40a505a7"}, ] py = [ {file = "py-1.10.0-py2.py3-none-any.whl", hash = "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"}, @@ -941,12 +941,12 @@ pygit2 = [ {file = "pygit2-1.6.1.tar.gz", hash = "sha256:c3303776f774d3e0115c1c4f6e1fc35470d15f113a7ae9401a0b90acfa1661ac"}, ] pygments = [ - {file = "Pygments-2.9.0-py3-none-any.whl", hash = "sha256:d66e804411278594d764fc69ec36ec13d9ae9147193a1740cd34d272ca383b8e"}, - {file = "Pygments-2.9.0.tar.gz", hash = "sha256:a18f47b506a429f6f4b9df81bb02beab9ca21d0a5fee38ed15aef65f0545519f"}, + {file = "Pygments-2.10.0-py3-none-any.whl", hash = "sha256:b8e67fe6af78f492b3c4b3e2970c0624cbf08beb1e493b2c99b9fa1b67a20380"}, + {file = "Pygments-2.10.0.tar.gz", hash = "sha256:f398865f7eb6874156579fdf36bc840a03cab64d1cde9e93d68f46a425ec52c6"}, ] pylint = [ - {file = "pylint-2.9.5-py3-none-any.whl", hash = "sha256:748f81e5776d6273a6619506e08f1b48ff9bcb8198366a56821cf11aac14fc87"}, - {file = "pylint-2.9.5.tar.gz", hash = "sha256:1f333dc72ef7f5ea166b3230936ebcfb1f3b722e76c980cb9fe6b9f95e8d3172"}, + {file = "pylint-2.11.1-py3-none-any.whl", hash = "sha256:0f358e221c45cbd4dad2a1e4b883e75d28acdcccd29d40c76eb72b307269b126"}, + {file = "pylint-2.11.1.tar.gz", hash = "sha256:2c9843fff1a88ca0ad98a256806c82c5a8f86086e7ccbdb93297d86c3f90c436"}, ] pyparsing = [ {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, @@ -992,51 +992,51 @@ radon = [ {file = "radon-4.5.2.tar.gz", hash = "sha256:63b863dd294fcc86f6aecace8d7cb4228acc2a16ab0b89c11ff60cb14182b488"}, ] regex = [ - {file = "regex-2021.7.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e6a1e5ca97d411a461041d057348e578dc344ecd2add3555aedba3b408c9f874"}, - {file = "regex-2021.7.6-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:6afe6a627888c9a6cfbb603d1d017ce204cebd589d66e0703309b8048c3b0854"}, - {file = "regex-2021.7.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ccb3d2190476d00414aab36cca453e4596e8f70a206e2aa8db3d495a109153d2"}, - {file = "regex-2021.7.6-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:ed693137a9187052fc46eedfafdcb74e09917166362af4cc4fddc3b31560e93d"}, - {file = "regex-2021.7.6-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:99d8ab206a5270c1002bfcf25c51bf329ca951e5a169f3b43214fdda1f0b5f0d"}, - {file = "regex-2021.7.6-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:b85ac458354165405c8a84725de7bbd07b00d9f72c31a60ffbf96bb38d3e25fa"}, - {file = "regex-2021.7.6-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:3f5716923d3d0bfb27048242a6e0f14eecdb2e2a7fac47eda1d055288595f222"}, - {file = "regex-2021.7.6-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5983c19d0beb6af88cb4d47afb92d96751fb3fa1784d8785b1cdf14c6519407"}, - {file = "regex-2021.7.6-cp36-cp36m-win32.whl", hash = "sha256:c92831dac113a6e0ab28bc98f33781383fe294df1a2c3dfd1e850114da35fd5b"}, - {file = "regex-2021.7.6-cp36-cp36m-win_amd64.whl", hash = "sha256:791aa1b300e5b6e5d597c37c346fb4d66422178566bbb426dd87eaae475053fb"}, - {file = "regex-2021.7.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:59506c6e8bd9306cd8a41511e32d16d5d1194110b8cfe5a11d102d8b63cf945d"}, - {file = "regex-2021.7.6-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:564a4c8a29435d1f2256ba247a0315325ea63335508ad8ed938a4f14c4116a5d"}, - {file = "regex-2021.7.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:59c00bb8dd8775473cbfb967925ad2c3ecc8886b3b2d0c90a8e2707e06c743f0"}, - {file = "regex-2021.7.6-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:9a854b916806c7e3b40e6616ac9e85d3cdb7649d9e6590653deb5b341a736cec"}, - {file = "regex-2021.7.6-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:db2b7df831c3187a37f3bb80ec095f249fa276dbe09abd3d35297fc250385694"}, - {file = "regex-2021.7.6-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:173bc44ff95bc1e96398c38f3629d86fa72e539c79900283afa895694229fe6a"}, - {file = "regex-2021.7.6-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:15dddb19823f5147e7517bb12635b3c82e6f2a3a6b696cc3e321522e8b9308ad"}, - {file = "regex-2021.7.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ddeabc7652024803666ea09f32dd1ed40a0579b6fbb2a213eba590683025895"}, - {file = "regex-2021.7.6-cp37-cp37m-win32.whl", hash = "sha256:f080248b3e029d052bf74a897b9d74cfb7643537fbde97fe8225a6467fb559b5"}, - {file = "regex-2021.7.6-cp37-cp37m-win_amd64.whl", hash = "sha256:d8bbce0c96462dbceaa7ac4a7dfbbee92745b801b24bce10a98d2f2b1ea9432f"}, - {file = "regex-2021.7.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:edd1a68f79b89b0c57339bce297ad5d5ffcc6ae7e1afdb10f1947706ed066c9c"}, - {file = "regex-2021.7.6-cp38-cp38-manylinux1_i686.whl", hash = "sha256:422dec1e7cbb2efbbe50e3f1de36b82906def93ed48da12d1714cabcd993d7f0"}, - {file = "regex-2021.7.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:cbe23b323988a04c3e5b0c387fe3f8f363bf06c0680daf775875d979e376bd26"}, - {file = "regex-2021.7.6-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:0eb2c6e0fcec5e0f1d3bcc1133556563222a2ffd2211945d7b1480c1b1a42a6f"}, - {file = "regex-2021.7.6-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:1c78780bf46d620ff4fff40728f98b8afd8b8e35c3efd638c7df67be2d5cddbf"}, - {file = "regex-2021.7.6-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:bc84fb254a875a9f66616ed4538542fb7965db6356f3df571d783f7c8d256edd"}, - {file = "regex-2021.7.6-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:598c0a79b4b851b922f504f9f39a863d83ebdfff787261a5ed061c21e67dd761"}, - {file = "regex-2021.7.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:875c355360d0f8d3d827e462b29ea7682bf52327d500a4f837e934e9e4656068"}, - {file = "regex-2021.7.6-cp38-cp38-win32.whl", hash = "sha256:e586f448df2bbc37dfadccdb7ccd125c62b4348cb90c10840d695592aa1b29e0"}, - {file = "regex-2021.7.6-cp38-cp38-win_amd64.whl", hash = "sha256:2fe5e71e11a54e3355fa272137d521a40aace5d937d08b494bed4529964c19c4"}, - {file = "regex-2021.7.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6110bab7eab6566492618540c70edd4d2a18f40ca1d51d704f1d81c52d245026"}, - {file = "regex-2021.7.6-cp39-cp39-manylinux1_i686.whl", hash = "sha256:4f64fc59fd5b10557f6cd0937e1597af022ad9b27d454e182485f1db3008f417"}, - {file = "regex-2021.7.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:89e5528803566af4df368df2d6f503c84fbfb8249e6631c7b025fe23e6bd0cde"}, - {file = "regex-2021.7.6-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:2366fe0479ca0e9afa534174faa2beae87847d208d457d200183f28c74eaea59"}, - {file = "regex-2021.7.6-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:f9392a4555f3e4cb45310a65b403d86b589adc773898c25a39184b1ba4db8985"}, - {file = "regex-2021.7.6-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:2bceeb491b38225b1fee4517107b8491ba54fba77cf22a12e996d96a3c55613d"}, - {file = "regex-2021.7.6-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:f98dc35ab9a749276f1a4a38ab3e0e2ba1662ce710f6530f5b0a6656f1c32b58"}, - {file = "regex-2021.7.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:319eb2a8d0888fa6f1d9177705f341bc9455a2c8aca130016e52c7fe8d6c37a3"}, - {file = "regex-2021.7.6-cp39-cp39-win32.whl", hash = "sha256:eaf58b9e30e0e546cdc3ac06cf9165a1ca5b3de8221e9df679416ca667972035"}, - {file = "regex-2021.7.6-cp39-cp39-win_amd64.whl", hash = "sha256:4c9c3155fe74269f61e27617529b7f09552fbb12e44b1189cebbdb24294e6e1c"}, - {file = "regex-2021.7.6.tar.gz", hash = "sha256:8394e266005f2d8c6f0bc6780001f7afa3ef81a7a2111fa35058ded6fce79e4d"}, + {file = "regex-2021.9.24-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0628ed7d6334e8f896f882a5c1240de8c4d9b0dd7c7fb8e9f4692f5684b7d656"}, + {file = "regex-2021.9.24-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3baf3eaa41044d4ced2463fd5d23bf7bd4b03d68739c6c99a59ce1f95599a673"}, + {file = "regex-2021.9.24-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c000635fd78400a558bd7a3c2981bb2a430005ebaa909d31e6e300719739a949"}, + {file = "regex-2021.9.24-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:295bc8a13554a25ad31e44c4bedabd3c3e28bba027e4feeb9bb157647a2344a7"}, + {file = "regex-2021.9.24-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0e3f59d3c772f2c3baaef2db425e6fc4149d35a052d874bb95ccfca10a1b9f4"}, + {file = "regex-2021.9.24-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:aea4006b73b555fc5bdb650a8b92cf486d678afa168cf9b38402bb60bf0f9c18"}, + {file = "regex-2021.9.24-cp310-cp310-win32.whl", hash = "sha256:09eb62654030f39f3ba46bc6726bea464069c29d00a9709e28c9ee9623a8da4a"}, + {file = "regex-2021.9.24-cp310-cp310-win_amd64.whl", hash = "sha256:8d80087320632457aefc73f686f66139801959bf5b066b4419b92be85be3543c"}, + {file = "regex-2021.9.24-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:7e3536f305f42ad6d31fc86636c54c7dafce8d634e56fef790fbacb59d499dd5"}, + {file = "regex-2021.9.24-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c31f35a984caffb75f00a86852951a337540b44e4a22171354fb760cefa09346"}, + {file = "regex-2021.9.24-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c7cb25adba814d5f419733fe565f3289d6fa629ab9e0b78f6dff5fa94ab0456"}, + {file = "regex-2021.9.24-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:85c61bee5957e2d7be390392feac7e1d7abd3a49cbaed0c8cee1541b784c8561"}, + {file = "regex-2021.9.24-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c94722bf403b8da744b7d0bb87e1f2529383003ceec92e754f768ef9323f69ad"}, + {file = "regex-2021.9.24-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6adc1bd68f81968c9d249aab8c09cdc2cbe384bf2d2cb7f190f56875000cdc72"}, + {file = "regex-2021.9.24-cp36-cp36m-win32.whl", hash = "sha256:2054dea683f1bda3a804fcfdb0c1c74821acb968093d0be16233873190d459e3"}, + {file = "regex-2021.9.24-cp36-cp36m-win_amd64.whl", hash = "sha256:7783d89bd5413d183a38761fbc68279b984b9afcfbb39fa89d91f63763fbfb90"}, + {file = "regex-2021.9.24-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b15dc34273aefe522df25096d5d087abc626e388a28a28ac75a4404bb7668736"}, + {file = "regex-2021.9.24-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10a7a9cbe30bd90b7d9a1b4749ef20e13a3528e4215a2852be35784b6bd070f0"}, + {file = "regex-2021.9.24-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb9f5844db480e2ef9fce3a72e71122dd010ab7b2920f777966ba25f7eb63819"}, + {file = "regex-2021.9.24-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:17310b181902e0bb42b29c700e2c2346b8d81f26e900b1328f642e225c88bce1"}, + {file = "regex-2021.9.24-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0bba1f6df4eafe79db2ecf38835c2626dbd47911e0516f6962c806f83e7a99ae"}, + {file = "regex-2021.9.24-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:821e10b73e0898544807a0692a276e539e5bafe0a055506a6882814b6a02c3ec"}, + {file = "regex-2021.9.24-cp37-cp37m-win32.whl", hash = "sha256:9c371dd326289d85906c27ec2bc1dcdedd9d0be12b543d16e37bad35754bde48"}, + {file = "regex-2021.9.24-cp37-cp37m-win_amd64.whl", hash = "sha256:1e8d1898d4fb817120a5f684363b30108d7b0b46c7261264b100d14ec90a70e7"}, + {file = "regex-2021.9.24-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8a5c2250c0a74428fd5507ae8853706fdde0f23bfb62ee1ec9418eeacf216078"}, + {file = "regex-2021.9.24-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8aec4b4da165c4a64ea80443c16e49e3b15df0f56c124ac5f2f8708a65a0eddc"}, + {file = "regex-2021.9.24-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:650c4f1fc4273f4e783e1d8e8b51a3e2311c2488ba0fcae6425b1e2c248a189d"}, + {file = "regex-2021.9.24-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2cdb3789736f91d0b3333ac54d12a7e4f9efbc98f53cb905d3496259a893a8b3"}, + {file = "regex-2021.9.24-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e61100200fa6ab7c99b61476f9f9653962ae71b931391d0264acfb4d9527d9c"}, + {file = "regex-2021.9.24-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8c268e78d175798cd71d29114b0a1f1391c7d011995267d3b62319ec1a4ecaa1"}, + {file = "regex-2021.9.24-cp38-cp38-win32.whl", hash = "sha256:658e3477676009083422042c4bac2bdad77b696e932a3de001c42cc046f8eda2"}, + {file = "regex-2021.9.24-cp38-cp38-win_amd64.whl", hash = "sha256:a731552729ee8ae9c546fb1c651c97bf5f759018fdd40d0e9b4d129e1e3a44c8"}, + {file = "regex-2021.9.24-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:86f9931eb92e521809d4b64ec8514f18faa8e11e97d6c2d1afa1bcf6c20a8eab"}, + {file = "regex-2021.9.24-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcbbc9cfa147d55a577d285fd479b43103188855074552708df7acc31a476dd9"}, + {file = "regex-2021.9.24-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:29385c4dbb3f8b3a55ce13de6a97a3d21bd00de66acd7cdfc0b49cb2f08c906c"}, + {file = "regex-2021.9.24-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c50a6379763c733562b1fee877372234d271e5c78cd13ade5f25978aa06744db"}, + {file = "regex-2021.9.24-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f74b6d8f59f3cfb8237e25c532b11f794b96f5c89a6f4a25857d85f84fbef11"}, + {file = "regex-2021.9.24-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6c4d83d21d23dd854ffbc8154cf293f4e43ba630aa9bd2539c899343d7f59da3"}, + {file = "regex-2021.9.24-cp39-cp39-win32.whl", hash = "sha256:95e89a8558c8c48626dcffdf9c8abac26b7c251d352688e7ab9baf351e1c7da6"}, + {file = "regex-2021.9.24-cp39-cp39-win_amd64.whl", hash = "sha256:835962f432bce92dc9bf22903d46c50003c8d11b1dc64084c8fae63bca98564a"}, + {file = "regex-2021.9.24.tar.gz", hash = "sha256:6266fde576e12357b25096351aac2b4b880b0066263e7bc7a9a1b4307991bb0e"}, ] rich = [ - {file = "rich-10.7.0-py3-none-any.whl", hash = "sha256:517b4e0efd064dd1fe821ca93dd3095d73380ceac1f0a07173d507d9b18f1396"}, - {file = "rich-10.7.0.tar.gz", hash = "sha256:13ac80676e12cf528dc4228dc682c8402f82577c2aa67191e294350fa2c3c4e9"}, + {file = "rich-10.11.0-py3-none-any.whl", hash = "sha256:44bb3f9553d00b3c8938abf89828df870322b9ba43caf3b12bb7758debdc6dec"}, + {file = "rich-10.11.0.tar.gz", hash = "sha256:016fa105f34b69c434e7f908bb5bd7fefa9616efdb218a2917117683a6394ce5"}, ] scalene = [ {file = "scalene-1.3.12-cp37-abi3-macosx_10_14_universal2.whl", hash = "sha256:85a033b4af6372662f3f328668d021ea1127a763746310244f500b88fb16c288"}, @@ -1057,8 +1057,8 @@ toml = [ {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, ] tomli = [ - {file = "tomli-1.1.0-py3-none-any.whl", hash = "sha256:f4a182048010e89cbec0ae4686b21f550a7f2903f665e34a6de58ec15424f919"}, - {file = "tomli-1.1.0.tar.gz", hash = "sha256:33d7984738f8bb699c9b0a816eb646a8178a69eaa792d258486776a5d21b8ca5"}, + {file = "tomli-1.2.1-py3-none-any.whl", hash = "sha256:8dd0e9524d6f386271a36b41dbf6c57d8e32fd96fd22b6584679dc569d20899f"}, + {file = "tomli-1.2.1.tar.gz", hash = "sha256:a5b75cb6f3968abb47af1b40c1819dc519ea82bcc065776a866e8d74c5ca9442"}, ] typed-ast = [ {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6"}, @@ -1101,9 +1101,9 @@ typer-cli = [ {file = "typer_cli-0.0.11-py3-none-any.whl", hash = "sha256:ecff43bc8c5d786deaa25b7d14ebfc59b32e40b07895259c3e86604af188f39b"}, ] typing-extensions = [ - {file = "typing_extensions-3.10.0.0-py2-none-any.whl", hash = "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497"}, - {file = "typing_extensions-3.10.0.0-py3-none-any.whl", hash = "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"}, - {file = "typing_extensions-3.10.0.0.tar.gz", hash = "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342"}, + {file = "typing_extensions-3.10.0.2-py2-none-any.whl", hash = "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7"}, + {file = "typing_extensions-3.10.0.2-py3-none-any.whl", hash = "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"}, + {file = "typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e"}, ] uvloop = [ {file = "uvloop-0.15.3-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:e71fb9038bfcd7646ca126c5ef19b17e48d4af9e838b2bcfda7a9f55a6552a32"}, @@ -1118,8 +1118,8 @@ uvloop = [ {file = "uvloop-0.15.3.tar.gz", hash = "sha256:905f0adb0c09c9f44222ee02f6b96fd88b493478fffb7a345287f9444e926030"}, ] virtualenv = [ - {file = "virtualenv-20.6.0-py2.py3-none-any.whl", hash = "sha256:e4fc84337dce37ba34ef520bf2d4392b392999dbe47df992870dc23230f6b758"}, - {file = "virtualenv-20.6.0.tar.gz", hash = "sha256:51df5d8a2fad5d1b13e088ff38a433475768ff61f202356bb9812c454c20ae45"}, + {file = "virtualenv-20.8.1-py2.py3-none-any.whl", hash = "sha256:10062e34c204b5e4ec5f62e6ef2473f8ba76513a9a617e873f1f8fb4a519d300"}, + {file = "virtualenv-20.8.1.tar.gz", hash = "sha256:bcc17f0b3a29670dd777d6f0755a4c04f28815395bca279cdcb213b97199a6b8"}, ] wcwidth = [ {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, From 9a2f7eb354ddac917a9a81d04703892c635f5303 Mon Sep 17 00:00:00 2001 From: fabianhe <39628987+fabianhe@users.noreply.github.com> Date: Tue, 28 Sep 2021 18:38:16 +0200 Subject: [PATCH 19/19] Fix pylint --- pyrepositoryminer/commands/commits.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyrepositoryminer/commands/commits.py b/pyrepositoryminer/commands/commits.py index b05b033..f1ce68d 100644 --- a/pyrepositoryminer/commands/commits.py +++ b/pyrepositoryminer/commands/commits.py @@ -65,7 +65,7 @@ def commits( branch_names: Iterable[str] if branches != Path("-"): - with open(branches) as f: + with open(branches, encoding="utf-8") as f: branch_names = list(f) else: branch_names = (line for line in stdin)