diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..1d953f4 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use nix diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..16aa1b8 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,29 @@ +--- +name: Upload Python Package + +on: + release: + types: [created] + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: set up python + uses: actions/setup-python@v2 + with: + python-version: '3.x' + - name: install dependencies + run: | + python -m pip install --upgrade pip + pip install setuptools wheel twine + sed -i -E "s#VERSION#${GITHUB_REF/refs\/tags\//}#g" ./setup.py + sed -i -E "s#VERSION#${GITHUB_REF/refs\/tags\//}#g" ./archives/globals.py + - name: build and publish + env: + TWINE_USERNAME: ${{ secrets.PYPI_USER }} + TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} + run: | + python setup.py sdist bdist_wheel + twine upload dist/* diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a76b485..1bbeff0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,29 +1,49 @@ name: test -on: [push, pull_request] +on: [push] jobs: archives: - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - uses: jpetrucciani/archives-check@master with: path: 'archives/' prospector: - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - uses: jpetrucciani/prospector-check@master mypy: - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - uses: jpetrucciani/mypy-check@master black: - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - uses: jpetrucciani/black-check@master with: path: 'archives/' + tests: + runs-on: ubuntu-20.04 + needs: [archives, mypy, prospector, black] + strategy: + matrix: + python-version: ['3.6', '3.7', '3.8', '3.9'] + name: python ${{ matrix.python-version }} tests + steps: + - uses: actions/checkout@v2 + - name: setup python + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + architecture: x64 + - name: install requirements + run: | + pip install -r requirements.txt + pip install -r requirements.dev.txt + - name: run Tox + run: tox -e py diff --git a/.gitignore b/.gitignore index 4c9e7a8..144a5f2 100644 --- a/.gitignore +++ b/.gitignore @@ -107,4 +107,7 @@ ENV/ # End of https://www.gitignore.io/api/python old/ -test_credentials.json \ No newline at end of file +test_credentials.json + +.vscode/ +.direnv/ diff --git a/.prospector.yaml b/.prospector.yaml index bb7ebb4..5bb804b 100644 --- a/.prospector.yaml +++ b/.prospector.yaml @@ -21,6 +21,7 @@ pylint: - no-self-use - unused-argument - wrong-import-order + - unsubscriptable-object options: max-args: 20 @@ -44,6 +45,7 @@ pep8: - N802 - N807 - W503 + - E203 options: max-line-length: 100 single-line-if-stmt: n diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index fc24da4..0000000 --- a/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ -dist: xenial -sudo: false -language: python -matrix: - include: - - python: 3.6 - env: TOXENV=py36 - - python: 3.7 - env: TOXENV=py37 - - python: 3.8-dev - env: TOXENV=py38 -install: - - pip install tox pipenv - - pipenv install -script: tox -deploy: - provider: pypi - user: jacobi - skip_existing: true - on: - branch: master - tags: true - password: - secure: rkD5+1kP8WJRPtk4b9IUTOskEtVYB3XFpfveZYsN6rkHCf/7trb2B2R5BoUrM0a7MnnQDuV35xx5TESeS/xwB+F/pl44d9uEfDwGOxlnhb1xjGajL/k73cepvw4lzDq4H471UVCBVwD37nUgMI1rDmGajA2rgcTUb/6ZDASwSJ2GbK0E4A4SkgCHS6+frToQESccX9Ay35tYhRDrC8yYhD+hT4Mv3UUTnk4kS5VrmxxIC18eu09qHDDAgtYVkul8oZfxJ7SZBHQ4vGsxWwk9sNDDeDJag9jpBybnpLSLHEa1esnmXFvvUweOjOvYAVD7/yHubtRs0+240M5Qyvgn2AEhdhqMXURgVMMN/y36yXqi8oJDG9nOY4pdB1jnoHLIKzBZtVzLRUuDSMEbCZAEMYKS7KNsbcdGKDXJ5wV4kXn/Ez3Znav65B4Jfxar3ubQEeCe//yzyYEndpviqn4761YCeCJXvPWA4gycsyAsFIuLlL4N2dWBnzNr25rgi7AoUD0c3L3p0hwisVCWPvkYPtDH9oz5AELwRUujuIBEpVJvO7j+C9pqZpl/pGiqwUulpvfMpeqgEZ3Z5Zeg4WX4IOw3dfXSNKQHPOU58XdrAtgQfZKRN/nsHV3x5APfaKDL8CKlZUPAYu9i174GvINAsDbe46G8hmlbQsuYK5dXj+0= diff --git a/LICENSE b/LICENSE index c9deaf7..3fc25c4 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019 Jacobi Petrucciani +Copyright (c) 2021 Jacobi Petrucciani Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..8afbefe --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,2 @@ +include README.md +include requirements.txt diff --git a/Pipfile b/Pipfile deleted file mode 100644 index b90324c..0000000 --- a/Pipfile +++ /dev/null @@ -1,15 +0,0 @@ -[[source]] -url = "https://pypi.python.org/simple" -verify_ssl = true -name = "pypi" - -[packages] -click = ">=7.0" -typed-ast = ">=1.4.0" -radon = ">=3.0.3" -lizard = ">=1.16.6" - -[dev-packages] -tox = "*" -pytest = "*" -pytest-cov = "*" diff --git a/Pipfile.lock b/Pipfile.lock deleted file mode 100644 index 2419adb..0000000 --- a/Pipfile.lock +++ /dev/null @@ -1,294 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "b39d18743e5bdcc93f5ed95ea02aafb75d161d04a02ff3b05dcd4e775c1296f0" - }, - "pipfile-spec": 6, - "requires": {}, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.python.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "click": { - "hashes": [ - "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", - "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7" - ], - "index": "pypi", - "version": "==7.0" - }, - "colorama": { - "hashes": [ - "sha256:05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d", - "sha256:f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48" - ], - "version": "==0.4.1" - }, - "entrypoints": { - "hashes": [ - "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19", - "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451" - ], - "version": "==0.3" - }, - "flake8": { - "hashes": [ - "sha256:19241c1cbc971b9962473e4438a2ca19749a7dd002dd1a946eaba171b4114548", - "sha256:8e9dfa3cecb2400b3738a42c54c3043e821682b9c840b0448c0503f781130696" - ], - "version": "==3.7.8" - }, - "flake8-polyfill": { - "hashes": [ - "sha256:12be6a34ee3ab795b19ca73505e7b55826d5f6ad7230d31b18e106400169b9e9", - "sha256:e44b087597f6da52ec6393a709e7108b2905317d0c0b744cdca6208e670d8eda" - ], - "version": "==1.0.2" - }, - "future": { - "hashes": [ - "sha256:67045236dcfd6816dc439556d009594abf643e5eb48992e36beac09c2ca659b8" - ], - "version": "==0.17.1" - }, - "lizard": { - "hashes": [ - "sha256:77f8f17a9d42e70b22225f01ac48fea3de9ccc7d89331f7152f4a676c1c7e342", - "sha256:9e4565c676b2d2022b77fcddba565aea44e6097c8f3889a26bb6f4aa26c1fe3e" - ], - "index": "pypi", - "version": "==1.16.6" - }, - "mando": { - "hashes": [ - "sha256:4ce09faec7e5192ffc3c57830e26acba0fd6cd11e1ee81af0d4df0657463bd1c", - "sha256:79feb19dc0f097daa64a1243db578e7674909b75f88ac2220f1c065c10a0d960" - ], - "version": "==0.6.4" - }, - "mccabe": { - "hashes": [ - "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", - "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" - ], - "version": "==0.6.1" - }, - "pycodestyle": { - "hashes": [ - "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56", - "sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c" - ], - "version": "==2.5.0" - }, - "pyflakes": { - "hashes": [ - "sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0", - "sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2" - ], - "version": "==2.1.1" - }, - "radon": { - "hashes": [ - "sha256:0cde1953547a164d24420ed6ccdfa18b61f1457b96a2b99ff0de76b22d504a0f", - "sha256:ee20308ce8bae7a89b067425b63b141a0077632ab318d5288da649c830882b3d" - ], - "index": "pypi", - "version": "==3.0.3" - }, - "six": { - "hashes": [ - "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", - "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" - ], - "version": "==1.12.0" - }, - "typed-ast": { - "hashes": [ - "sha256:18511a0b3e7922276346bcb47e2ef9f38fb90fd31cb9223eed42c85d1312344e", - "sha256:262c247a82d005e43b5b7f69aff746370538e176131c32dda9cb0f324d27141e", - "sha256:2b907eb046d049bcd9892e3076c7a6456c93a25bebfe554e931620c90e6a25b0", - "sha256:354c16e5babd09f5cb0ee000d54cfa38401d8b8891eefa878ac772f827181a3c", - "sha256:4e0b70c6fc4d010f8107726af5fd37921b666f5b31d9331f0bd24ad9a088e631", - "sha256:630968c5cdee51a11c05a30453f8cd65e0cc1d2ad0d9192819df9978984529f4", - "sha256:66480f95b8167c9c5c5c87f32cf437d585937970f3fc24386f313a4c97b44e34", - "sha256:71211d26ffd12d63a83e079ff258ac9d56a1376a25bc80b1cdcdf601b855b90b", - "sha256:95bd11af7eafc16e829af2d3df510cecfd4387f6453355188342c3e79a2ec87a", - "sha256:bc6c7d3fa1325a0c6613512a093bc2a2a15aeec350451cbdf9e1d4bffe3e3233", - "sha256:cc34a6f5b426748a507dd5d1de4c1978f2eb5626d51326e43280941206c209e1", - "sha256:d755f03c1e4a51e9b24d899561fec4ccaf51f210d52abdf8c07ee2849b212a36", - "sha256:d7c45933b1bdfaf9f36c579671fec15d25b06c8398f113dab64c18ed1adda01d", - "sha256:d896919306dd0aa22d0132f62a1b78d11aaf4c9fc5b3410d3c666b818191630a", - "sha256:ffde2fbfad571af120fcbfbbc61c72469e72f550d676c3342492a9dfdefb8f12" - ], - "index": "pypi", - "version": "==1.4.0" - } - }, - "develop": { - "atomicwrites": { - "hashes": [ - "sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", - "sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6" - ], - "version": "==1.3.0" - }, - "attrs": { - "hashes": [ - "sha256:69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79", - "sha256:f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399" - ], - "version": "==19.1.0" - }, - "coverage": { - "hashes": [ - "sha256:08907593569fe59baca0bf152c43f3863201efb6113ecb38ce7e97ce339805a6", - "sha256:0be0f1ed45fc0c185cfd4ecc19a1d6532d72f86a2bac9de7e24541febad72650", - "sha256:141f08ed3c4b1847015e2cd62ec06d35e67a3ac185c26f7635f4406b90afa9c5", - "sha256:19e4df788a0581238e9390c85a7a09af39c7b539b29f25c89209e6c3e371270d", - "sha256:23cc09ed395b03424d1ae30dcc292615c1372bfba7141eb85e11e50efaa6b351", - "sha256:245388cda02af78276b479f299bbf3783ef0a6a6273037d7c60dc73b8d8d7755", - "sha256:331cb5115673a20fb131dadd22f5bcaf7677ef758741312bee4937d71a14b2ef", - "sha256:386e2e4090f0bc5df274e720105c342263423e77ee8826002dcffe0c9533dbca", - "sha256:3a794ce50daee01c74a494919d5ebdc23d58873747fa0e288318728533a3e1ca", - "sha256:60851187677b24c6085248f0a0b9b98d49cba7ecc7ec60ba6b9d2e5574ac1ee9", - "sha256:63a9a5fc43b58735f65ed63d2cf43508f462dc49857da70b8980ad78d41d52fc", - "sha256:6b62544bb68106e3f00b21c8930e83e584fdca005d4fffd29bb39fb3ffa03cb5", - "sha256:6ba744056423ef8d450cf627289166da65903885272055fb4b5e113137cfa14f", - "sha256:7494b0b0274c5072bddbfd5b4a6c6f18fbbe1ab1d22a41e99cd2d00c8f96ecfe", - "sha256:826f32b9547c8091679ff292a82aca9c7b9650f9fda3e2ca6bf2ac905b7ce888", - "sha256:93715dffbcd0678057f947f496484e906bf9509f5c1c38fc9ba3922893cda5f5", - "sha256:9a334d6c83dfeadae576b4d633a71620d40d1c379129d587faa42ee3e2a85cce", - "sha256:af7ed8a8aa6957aac47b4268631fa1df984643f07ef00acd374e456364b373f5", - "sha256:bf0a7aed7f5521c7ca67febd57db473af4762b9622254291fbcbb8cd0ba5e33e", - "sha256:bf1ef9eb901113a9805287e090452c05547578eaab1b62e4ad456fcc049a9b7e", - "sha256:c0afd27bc0e307a1ffc04ca5ec010a290e49e3afbe841c5cafc5c5a80ecd81c9", - "sha256:dd579709a87092c6dbee09d1b7cfa81831040705ffa12a1b248935274aee0437", - "sha256:df6712284b2e44a065097846488f66840445eb987eb81b3cc6e4149e7b6982e1", - "sha256:e07d9f1a23e9e93ab5c62902833bf3e4b1f65502927379148b6622686223125c", - "sha256:e2ede7c1d45e65e209d6093b762e98e8318ddeff95317d07a27a2140b80cfd24", - "sha256:e4ef9c164eb55123c62411f5936b5c2e521b12356037b6e1c2617cef45523d47", - "sha256:eca2b7343524e7ba246cab8ff00cab47a2d6d54ada3b02772e908a45675722e2", - "sha256:eee64c616adeff7db37cc37da4180a3a5b6177f5c46b187894e633f088fb5b28", - "sha256:ef824cad1f980d27f26166f86856efe11eff9912c4fed97d3804820d43fa550c", - "sha256:efc89291bd5a08855829a3c522df16d856455297cf35ae827a37edac45f466a7", - "sha256:fa964bae817babece5aa2e8c1af841bebb6d0b9add8e637548809d040443fee0", - "sha256:ff37757e068ae606659c28c3bd0d923f9d29a85de79bf25b2b34b148473b5025" - ], - "version": "==4.5.4" - }, - "filelock": { - "hashes": [ - "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59", - "sha256:929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836" - ], - "version": "==3.0.12" - }, - "importlib-metadata": { - "hashes": [ - "sha256:652234b6ab8f2506ae58e528b6fbcc668831d3cc758e1bc01ef438d328b68cdb", - "sha256:6f264986fb88042bc1f0535fa9a557e6a376cfe5679dc77caac7fe8b5d43d05f" - ], - "markers": "python_version < '3.8'", - "version": "==0.22" - }, - "more-itertools": { - "hashes": [ - "sha256:409cd48d4db7052af495b09dec721011634af3753ae1ef92d2b32f73a745f832", - "sha256:92b8c4b06dac4f0611c0729b2f2ede52b2e1bac1ab48f089c7ddc12e26bb60c4" - ], - "version": "==7.2.0" - }, - "packaging": { - "hashes": [ - "sha256:a7ac867b97fdc07ee80a8058fe4435ccd274ecc3b0ed61d852d7d53055528cf9", - "sha256:c491ca87294da7cc01902edbe30a5bc6c4c28172b5138ab4e4aa1b9d7bfaeafe" - ], - "version": "==19.1" - }, - "pluggy": { - "hashes": [ - "sha256:0db4b7601aae1d35b4a033282da476845aa19185c1e6964b25cf324b5e4ec3e6", - "sha256:fa5fa1622fa6dd5c030e9cad086fa19ef6a0cf6d7a2d12318e10cb49d6d68f34" - ], - "version": "==0.13.0" - }, - "py": { - "hashes": [ - "sha256:64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa", - "sha256:dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53" - ], - "version": "==1.8.0" - }, - "pyparsing": { - "hashes": [ - "sha256:6f98a7b9397e206d78cc01df10131398f1c8b8510a2f4d97d9abd82e1aacdd80", - "sha256:d9338df12903bbf5d65a0e4e87c2161968b10d2e489652bb47001d82a9b028b4" - ], - "version": "==2.4.2" - }, - "pytest": { - "hashes": [ - "sha256:95d13143cc14174ca1a01ec68e84d76ba5d9d493ac02716fd9706c949a505210", - "sha256:b78fe2881323bd44fd9bd76e5317173d4316577e7b1cddebae9136a4495ec865" - ], - "index": "pypi", - "version": "==5.1.2" - }, - "pytest-cov": { - "hashes": [ - "sha256:2b097cde81a302e1047331b48cadacf23577e431b61e9c6f49a1170bbe3d3da6", - "sha256:e00ea4fdde970725482f1f35630d12f074e121a23801aabf2ae154ec6bdd343a" - ], - "index": "pypi", - "version": "==2.7.1" - }, - "six": { - "hashes": [ - "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", - "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" - ], - "version": "==1.12.0" - }, - "toml": { - "hashes": [ - "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", - "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e" - ], - "version": "==0.10.0" - }, - "tox": { - "hashes": [ - "sha256:0bc216b6a2e6afe764476b4a07edf2c1dab99ed82bb146a1130b2e828f5bff5e", - "sha256:c4f6b319c20ba4913dbfe71ebfd14ff95d1853c4231493608182f66e566ecfe1" - ], - "index": "pypi", - "version": "==3.14.0" - }, - "virtualenv": { - "hashes": [ - "sha256:680af46846662bb38c5504b78bad9ed9e4f3ba2d54f54ba42494fdf94337fe30", - "sha256:f78d81b62d3147396ac33fc9d77579ddc42cc2a98dd9ea38886f616b33bc7fb2" - ], - "version": "==16.7.5" - }, - "wcwidth": { - "hashes": [ - "sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e", - "sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c" - ], - "version": "==0.1.7" - }, - "zipp": { - "hashes": [ - "sha256:3718b1cbcd963c7d4c5511a8240812904164b7f381b647143a89d3b98f9bcd8e", - "sha256:f06903e9f1f43b12d371004b4ac7b06ab39a44adc747266928ae6debfa7b3335" - ], - "version": "==0.6.0" - } - } -} diff --git a/README.md b/README.md index c19138d..1977a47 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # archives: a new way to do python code documentation -[![image](https://travis-ci.org/jpetrucciani/archives.svg?branch=master)](https://travis-ci.org/jpetrucciani/archives) [![PyPI version](https://badge.fury.io/py/archives.svg)](https://badge.fury.io/py/archives) [![Code style: @@ -27,13 +26,13 @@ incomplete](https://i.kym-cdn.com/entries/icons/original/000/023/967/obiwan.jpg) ### Installation -``` bash +```bash pip install archives ``` ### Run the Linter -``` bash +```bash # run archives (on itself!) archives archives/ @@ -72,7 +71,7 @@ archives --format pylint archives.py Tests can be run with tox\! -``` bash +```bash # run tests tox @@ -87,4 +86,4 @@ tox -e py36 - more output formats - potentially spell-checking inside desc? - documentation generator - - tests \ No newline at end of file + - tests diff --git a/archives/__init__.py b/archives/__init__.py index ec0bc76..fdeedc1 100644 --- a/archives/__init__.py +++ b/archives/__init__.py @@ -3,3 +3,4 @@ @desc the archives module """ from archives.archives import archives, parse_module # noqa +from archives.globals import __version__ # noqa diff --git a/archives/archives.py b/archives/archives.py index c08038e..6c54c5e 100644 --- a/archives/archives.py +++ b/archives/archives.py @@ -40,7 +40,7 @@ def parse_module(filename: str) -> Module: """ - @cc 3 + @cc 5 @desc parse a module into our archives' models @arg filename: the python file to parse @ret a parsed Module object of the given file @@ -66,7 +66,7 @@ def parse_module(filename: str) -> Module: def function_lint(function: Function) -> List: """ - @cc 8 + @cc 16 @desc function specific lint @arg function: the Function object to lint @ret a list of issues found in this function @@ -115,7 +115,7 @@ def function_lint(function: Function) -> List: def class_lint(class_def: Class) -> List: """ - @cc 5 + @cc 7 @desc class specific lint @arg class_def: the Class object to lint @ret a list of issues found in this class @@ -148,7 +148,7 @@ def class_lint(class_def: Class) -> List: def lint(module: Module) -> List: """ - @cc 5 + @cc 7 @desc lint the given module! @arg module: the module to lint @ret a list of issues found in this module @@ -178,7 +178,7 @@ def lint(module: Module) -> List: def archives_lint(ctx: click.Context, sources: Set[Path], state: State) -> None: """ - @cc 4 + @cc 20 @desc perform an archives documentation lint @arg ctx: the click context of the current run @arg sources: the source files to lint @@ -226,13 +226,11 @@ def archives_lint(ctx: click.Context, sources: Set[Path], state: State) -> None: if not state.quiet: if issues: trailing_s = "s" if len(issues) != 1 else "" - out(f"\nImpossible! Perhaps your archives are incomplete?", color="red") + out("\nImpossible! Perhaps your archives are incomplete?", color="red") out(f"{len(issues)} issue{trailing_s} found", color="red") else: - out( - f"Incredible! It appears that your archives are complete!", color="blue" - ) - out(f"0 issues found", color="blue") + out("Incredible! It appears that your archives are complete!", color="blue") + out("0 issues found", color="blue") if state.stats: _mods = state.module_count @@ -253,7 +251,7 @@ def archives_lint(ctx: click.Context, sources: Set[Path], state: State) -> None: def archives_doc(ctx: click.Context, sources: Set[Path], state: State) -> None: """ - @cc 1 + @cc 2 @desc perform archives documentation generation @arg ctx: the click context of the current run @arg sources: the source files to lint @@ -285,7 +283,7 @@ def archives_doc(ctx: click.Context, sources: Set[Path], state: State) -> None: ) @click.option( "--format", - type=click.Choice(FORMATS.keys()), + type=click.Choice(list(FORMATS.keys())), default="flake8", show_default=True, help="format of issue output messages", @@ -355,7 +353,7 @@ def archives( """ check if your code's archives are incomplete! \f - @cc 8 + @cc 15 @desc the main cli method for archives @arg ctx: the click context arg @arg quiet: the cli quiet flag diff --git a/archives/globals.py b/archives/globals.py index 532b952..b615b9f 100644 --- a/archives/globals.py +++ b/archives/globals.py @@ -3,20 +3,20 @@ @desc global vars for archives """ import sys -from typed_ast import ast3 # noqa -__version__ = "0.12" +__version__ = "VERSION" +PY_VER = sys.version_info +IS_38 = PY_VER[0] >= 3 and PY_VER[1] >= 8 -PY_VERSION = sys.version_info -# if PY_VERSION[0] >= 3 and PY_VERSION[1] >= 8: -# # we should use the built in ast if python 3.8 or higher -# # see https://github.com/python/typed_ast#python-38 -# import ast as ast3 -# else: -# # use the forked typed version -# from typed_ast import ast3 # type: ignore # noqa +if IS_38: + # we should use the built in ast if python 3.8 or higher + # see https://github.com/python/typed_ast#python-38 + import ast as ast3 +else: + # use the forked typed version + from typed_ast import ast3 # type: ignore # noqa DEFAULT_EXCLUDES_LIST = [ diff --git a/archives/models/python.py b/archives/models/python.py index eab2e6d..7ac6451 100644 --- a/archives/models/python.py +++ b/archives/models/python.py @@ -6,14 +6,14 @@ from radon.complexity import cc_visit_ast from radon.metrics import h_visit_ast from typing import Dict, Set, Union -from archives.globals import ast3, DEFAULT_ARG_IGNORE +from archives.globals import ast3, DEFAULT_ARG_IGNORE, IS_38 from archives.utils.text import debug from archives.models.tags import Tags def parse_elt(elt: Union[ast3.Name, ast3.Subscript]) -> str: """ - @cc 4 + @cc 10 @desc a function to help parse a type annotation into a string @arg elt: the element to attempt to parse @ret the string version of this type annotation @@ -21,9 +21,9 @@ def parse_elt(elt: Union[ast3.Name, ast3.Subscript]) -> str: if isinstance(elt, ast3.Name): return elt.id if isinstance(elt, ast3.NameConstant): - return elt.value + return elt.value # type: ignore if isinstance(elt, ast3.Subscript): - value = elt.slice.value # type: ignore + value = elt.slice if IS_38 else elt.slice.value # type: ignore name = elt.value.id # type: ignore if isinstance(value, ast3.Str): return f"{name}[{value.s}]" @@ -86,7 +86,7 @@ class Type(Enum): def __init__(self, doc_string: ast3.Expr, doc_type: Type) -> None: """ - @cc 1 + @cc 11 @desc easier to use version of the ast docstring def @arg doc_string: the expression used to represent a docstring @arg doc_type: the enum type of doc string this is used for @@ -199,7 +199,7 @@ class Function: def __init__(self, function: ast3.FunctionDef, module: "Module") -> None: """ - @cc 3 + @cc 14 @desc easier to use version of the ast function def @arg function: the AST functionDef to parse @arg module: the module this function resides in @@ -261,7 +261,7 @@ def __repr__(self) -> str: def serialize(self) -> Dict: """ - @cc 1 + @cc 6 @desc serialize method for saving to json @ret a dict of this arg's properties """ @@ -286,7 +286,7 @@ class Class: def __init__(self, cls: ast3.ClassDef, module: "Module") -> None: """ - @cc 2 + @cc 6 @desc easier to use version of a class @arg cls: the AST ClassDef to parse @arg module: the module this class resides in @@ -320,7 +320,7 @@ def __repr__(self) -> str: def serialize(self) -> Dict: """ - @cc 1 + @cc 5 @desc serialize method for saving to json @ret a dict of this arg's properties """ @@ -342,7 +342,7 @@ class Module: def __init__(self, module: ast3.Module, filename: str) -> None: """ - @cc 2 + @cc 6 @desc easier to use version of a module @arg module: the AST module to parse @arg filename: the filename of the module we're parsing @@ -371,7 +371,7 @@ def __repr__(self) -> str: def serialize(self) -> Dict: """ - @cc 1 + @cc 5 @desc serialize method for saving to json @ret a dict of this arg's properties """ diff --git a/archives/models/rules.py b/archives/models/rules.py index 9bea058..abd6d36 100644 --- a/archives/models/rules.py +++ b/archives/models/rules.py @@ -33,7 +33,7 @@ def __init__( self, rule: Rule, obj: Union[Class, Function, Module], extra: Dict = None ) -> None: """ - @cc 1 + @cc 4 @desc constructor for issue @arg rule: an instance of the rule being broken @arg obj: either a class, function, or module that breaks the rule diff --git a/archives/models/tags.py b/archives/models/tags.py index 788e88f..54463ee 100644 --- a/archives/models/tags.py +++ b/archives/models/tags.py @@ -85,15 +85,15 @@ class Tags: all_types = "module/class/function" # general tags - ARG = arg_tag("arg", f"describe an argument of a function") + ARG = arg_tag("arg", "describe an argument of a function") AUTHOR = str_tag("author", f"denote the author of a {all_types}") - CC = int_tag("cc", f"denote the complexity of a function") + CC = int_tag("cc", "denote the complexity of a function") DESC = str_tag("desc", f"describe a {all_types}") - RETURN = str_tag("ret", f"describe the return value of a function") - TODO = str_tag("todo", f"tag something as a todo") + RETURN = str_tag("ret", "describe the return value of a function") + TODO = str_tag("todo", "tag something as a todo") # documentation tags - LINK = arg_tag("link", f"add a link to the generated documentation") + LINK = arg_tag("link", "add a link to the generated documentation") NOTE = str_tag("note", f"add a note to a {all_types}") WARN = str_tag("warn", f"add a warning to a {all_types}") @@ -104,7 +104,7 @@ class Tags: @classmethod def all(cls) -> List[Tag]: """ - @cc 1 + @cc 4 @desc get all tags in this enum @ret a list of the tag objects """ diff --git a/archives/rules/__init__.py b/archives/rules/__init__.py index 210ec46..25037af 100644 --- a/archives/rules/__init__.py +++ b/archives/rules/__init__.py @@ -20,7 +20,7 @@ def no_docstring(obj: Union[Class, Function, Module]) -> bool: def no_desc(obj: Union[Class, Function, Module]) -> bool: """ - @cc 1 + @cc 2 @desc no description test @arg obj: a class, function, or module to check @ret true if the obj has no @desc tag @@ -30,7 +30,7 @@ def no_desc(obj: Union[Class, Function, Module]) -> bool: def no_author(module: "Module") -> bool: """ - @cc 1 + @cc 2 @desc no author test @arg module: a module to check @ret true if the module has no @author tag @@ -40,7 +40,7 @@ def no_author(module: "Module") -> bool: def no_cc(obj: "Function") -> bool: """ - @cc 1 + @cc 2 @desc no cyclomatic complexity test @arg obj: a function to check @ret true if the function does not have a @cc tag @@ -50,7 +50,7 @@ def no_cc(obj: "Function") -> bool: def wrong_cc(obj: "Function") -> bool: """ - @cc 1 + @cc 3 @desc incorrect cyclomatic complexity test @arg obj: a function to check @ret true if the function has an incorrect @cc tag @@ -60,7 +60,7 @@ def wrong_cc(obj: "Function") -> bool: def no_ret(function: "Function") -> bool: """ - @cc 2 + @cc 4 @desc no return tag test @arg function: a function to check @ret true if the function does not have a @ret tag @@ -83,7 +83,7 @@ def no_ret_type(function: "Function") -> bool: def unnecessary_ret(function: "Function") -> bool: """ - @cc 1 + @cc 5 @desc unnecessary return tag test @arg function: a function to check @ret true if the function has a @ret tag but doesn't need one @@ -121,7 +121,7 @@ def nop(obj: Union[Class, Function, Module]) -> bool: Rule("F102", "function '{name}' missing @cc tag (cc: {cc})", no_cc), Rule( "F103", - "function '{name}' mismatched @cc tag ({doc_cc}, expected {cc})", + "function '{name}' mismatched @cc tag (tag is {doc_cc}, calculated {cc})", wrong_cc, ), Rule("F104", "function '{name}' missing @ret tag", no_ret), diff --git a/archives/utils/files.py b/archives/utils/files.py index dd20bb7..9a873e7 100644 --- a/archives/utils/files.py +++ b/archives/utils/files.py @@ -16,7 +16,7 @@ def get_python_files( path: Path, root: Path, include: Pattern[str], exclude: Pattern[str] ) -> Iterator[Path]: """ - @cc 3 + @cc 11 @desc return the list of files in the path, including/excluding from args @arg path: the path to start with @arg root: the root of the overall path @@ -52,7 +52,7 @@ def get_python_files( @lru_cache() def find_project_root(sources: Iterable[str]) -> Path: """ - @cc 4 + @cc 6 @desc find the project root of the sources supplied @arg sources: a list of source files that we're parsing @ret the path pointing to the root of the python project @@ -73,7 +73,7 @@ def find_project_root(sources: Iterable[str]) -> Path: def path_empty(src: Tuple[str], ctx: click.Context) -> None: """ - @cc 2 + @cc 4 @desc Exit if there is no src provided for formatting @arg src: a list of source files to lint @arg ctx: the context of the click cli application @@ -87,7 +87,7 @@ def path_empty(src: Tuple[str], ctx: click.Context) -> None: def decode_bytes(src: bytes) -> Tuple[str, str, str]: """ - @cc 2 + @cc 3 @desc decode bytes passed in @arg src: source data @ret a tuple of (decoded_contents, encoding, newline) diff --git a/archives/utils/text.py b/archives/utils/text.py index e04c05d..5205b74 100644 --- a/archives/utils/text.py +++ b/archives/utils/text.py @@ -10,7 +10,7 @@ def debug(data: Union[str, Dict, List], force: bool = False) -> None: """ - @cc 2 + @cc 4 @desc only prints if verbose mode is on, formatting nicely if list/dict @arg data: either a string to print, or a list/dict to print nicely @arg force: force this debug to print, regardless of state/flags @@ -26,7 +26,7 @@ def out( data: Union[str, Dict, List], force: bool = False, color: str = "green" ) -> None: """ - @cc 2 + @cc 4 @desc prints something to standard out @arg data: either a string to print, or a list/dict to print nicely @arg color: what color to print in @@ -41,7 +41,7 @@ def out( def err(data: Union[str, Dict, List]) -> None: """ - @cc 2 + @cc 3 @desc prints something to standard error @arg data: either a string to print, or a list/dict to print nicely """ @@ -54,7 +54,7 @@ def err(data: Union[str, Dict, List]) -> None: def msg(data: Union[str, Dict, List]) -> None: """ - @cc 2 + @cc 3 @desc prints something to standard out in blue @arg data: either a string to print, or a list/dict to print nicely """ diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..3fe5894 --- /dev/null +++ b/default.nix @@ -0,0 +1,15 @@ +let + mach-nix = import ( + fetchTarball { + name = "mach-nix-3.3.0"; + url = "https://github.com/DavHau/mach-nix/archive/3.3.0.tar.gz"; + sha256 = "105d6b6kgvn8kll639vx5adh5hp4gjcl4bs9rjzzyqz7367wbxj6"; + } + ) { python = "python39"; }; +in +mach-nix.mkPythonShell { + requirements = '' + ${builtins.readFile ./requirements.txt} + ${builtins.readFile ./requirements-dev.txt} + ''; +} diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..91a5842 --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,4 @@ +pytest +pytest-cov +setuptools +tox diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..6aec064 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +click>=7.0 +lizard>=1.16.6 +radon>=3.0.3 +typed-ast>=1.4.0 diff --git a/setup.cfg b/setup.cfg index c53e25e..9ed0f44 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,12 +1,9 @@ [mypy] -python_version = 3.6 +python_version = 3.9 disallow_untyped_defs = False ignore_missing_imports = True [flake8] -ignore = N802,N807,W503 +ignore = N802,N807,W503,E203 max-line-length = 100 max-complexity = 20 - -[tool:pytest] -log_print = False diff --git a/setup.py b/setup.py index b6d5217..80af150 100755 --- a/setup.py +++ b/setup.py @@ -2,55 +2,40 @@ """ pip setup file """ -import os -import re from setuptools import setup, find_packages -REQUIRED = ["click>=7.0", "typed-ast>=1.4.0", "radon>=3.0.3"] -LIBRARY = "archives" +__library__ = "archives" +__version__ = "VERSION" with open("README.md") as readme: LONG_DESCRIPTION = readme.read() - -def find_version(*file_paths): - """ - This pattern was modeled on a method from the Python Packaging User Guide: - https://packaging.python.org/en/latest/single_source_version.html - We read instead of importing so we don't get import errors if our code - imports from dependencies listed in install_requires. - """ - base_module_file = os.path.join(*file_paths) - with open(base_module_file) as module_file: - base_module_data = module_file.read() - version_match = re.search( - r"^__version__ = ['\"]([^'\"]*)['\"]", base_module_data, re.M - ) - if version_match: - return version_match.group(1) - raise RuntimeError("Unable to find version string.") +with open("requirements.txt") as requirements: + INSTALL_REQUIRES = requirements.read().split("\n") + INSTALL_REQUIRES = [x.strip() for x in INSTALL_REQUIRES if x.strip()] setup( - name=LIBRARY, - version=find_version("archives", "globals.py"), + name=__library__, + version=__version__, description=("a new way to do python code documentation"), long_description=LONG_DESCRIPTION, long_description_content_type="text/markdown", author="Jacobi Petrucciani", author_email="jacobi@mimirhq.com", - url="https://github.com/jpetrucciani/{}.git".format(LIBRARY), - download_url="https://github.com/jpetrucciani/{}.git".format(LIBRARY), + url="https://github.com/jpetrucciani/{}.git".format(__library__), + download_url="https://github.com/jpetrucciani/{}.git".format(__library__), license="MIT", packages=find_packages(), - install_requires=REQUIRED, + install_requires=INSTALL_REQUIRES, classifiers=[ "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", ], diff --git a/tox.ini b/tox.ini index 3ece86c..4b1651f 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py{36,37,38} +envlist = py{36,37,38,39} [testenv] commands =