diff --git a/.flake8 b/.flake8 index e61de53c0..1f2218ec9 100644 --- a/.flake8 +++ b/.flake8 @@ -1,2 +1,7 @@ [flake8] +exclude = .eggs,build,docs,.venv* ignore = E203 E501 W503 W504 +per-file-ignores = + asyncpraw/models/__init__.py:F401 + asyncpraw/models/listing/mixins/__init__.py:F401 + asyncpraw/models/reddit/mixins/__init__.py:F401 diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 7689e0414..9279f8caf 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -26,30 +26,38 @@ One of the simplest ways to help with Async PRAW is by answering others' questions. When responding, always be positive. While something may be obvious to you, it likely is not to the person asking the question. -## Pull Request Creation +## Creating Pull Requests 0. If you are fixing an already filed issue, please indicate your intentions by commenting on the issue. This act will hopefully minimize any duplicate work. -1. Prior to creating a pull request run the `pre_push.py` script. This script - depends on the tools `black` `flake8`, `pylint`, `pydocstyle`, `sphinx`, `sphinx_rtd_theme`, and `sphinxcontrib-trio`. They can - be installed via `pip install black flake8 pydocstyle pylint sphinx sphinx_rtd_theme sphinxcontrib-trio` or via - `pip install asyncpraw[lint]`. +1. Before committing, make sure to install [Pre-Commit](https://pre-commit.com/) + and the pre-commit hooks, which ensure any new code conforms to Async PRAW's + quality and style guidelines. To do so, install the linting dependencies + with `pip install asyncpraw[lint]`, then by the hooks with `pre-commit install`. + They will now run automatically every time you commit. If one of the formatters + (e.g. Black, isort) changes one or more files, the commit will automatically abort + so you can double-check the changes. If everything looks good, just `git add .` and + commit again. -2. Add yourself as a contributor to the ``AUTHORS.rst``. +2. Prior to creating a pull request, run the `pre_push.py` script. + This runs the pre-commit suite on all files, as well as builds the docs. + You'll need to have installed the linting dependencies first (see previous). -3. Once pushed, ensure that your Github Actions build succeeds. Actions will error +3. Add yourself as a contributor to the ``AUTHORS.rst``. + +4. Once pushed, ensure that your GitHub Actions build succeeds. Actions will error before running any tests if there are _any_ `flake8` or `pydocstyle` issues. Resolve any issues by updating your pull request. -4. Ensure that your change has complete test coverage. Tests on methods that do +5. Ensure that your change has complete test coverage. Tests on methods that do not require fetching data from Reddit, e.g., method argument validation, should be saved as a unit test. Tests that hit Reddit's servers should be an integration test and all network activity should be recorded via vcrpy. The required packages can be installed with `pip install asyncpraw[test]`. -5. Feel free to check on the status of your pull request periodically by adding +6. Feel free to check on the status of your pull request periodically by adding a comment. ## Becoming a Team Member diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 82dcc9fc5..198e35396 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,24 +25,10 @@ jobs: v0-${{ runner.os }}-pip- - name: Install dependencies run: | - python -m pip install --upgrade pip + python -m pip install --upgrade pip setuptools wheel pip install .[lint] - - name: Check other phrase usages - run: python ./tools/static_word_checks.py - - name: Check documentation - run: python ./tools/check_documentation.py - - name: Run black - run: black --check --verbose . - - name: Run docstrfmt - run: docstrfmt -cvp pyproject.toml -e "docs/examples/*" . - - name: Run flake8 - run: flake8 --exclude docs --statistics - - name: Run flynt - run: flynt -vdf -tc -ll 1000 . - - name: Run isort - run: isort -cv . - - name: Run pydocstyle - run: pydocstyle asyncpraw + - name: Run pre-commit hooks + uses: pre-commit/action@v2.0.3 - name: Run sphinx run: sphinx-build -W --keep-going docs/ /tmp/foo strategy: diff --git a/.github/workflows/pre-commit_autoupdate.yml b/.github/workflows/pre-commit_autoupdate.yml new file mode 100644 index 000000000..79ec9ddb9 --- /dev/null +++ b/.github/workflows/pre-commit_autoupdate.yml @@ -0,0 +1,19 @@ +jobs: + auto-update: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + - uses: browniebroke/pre-commit-autoupdate-action@main + - uses: peter-evans/create-pull-request@v3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + branch: update/pre-commit-hooks + title: Update pre-commit hooks + commit-message: "Update pre-commit hooks" + body: Update versions of pre-commit hooks to the latest version. +name: 'Update pre-commit hooks' +on: + schedule: + - cron: '0 15 * * 1' + workflow_dispatch: diff --git a/.github/workflows/set_active_versions.yml b/.github/workflows/set_active_versions.yml index cf1673a38..9c92a322c 100644 --- a/.github/workflows/set_active_versions.yml +++ b/.github/workflows/set_active_versions.yml @@ -16,4 +16,4 @@ jobs: name: Set Active Docs on: release: - types: [published] \ No newline at end of file + types: [published] diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7329d7594..947356aaa 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,7 +1,60 @@ -fail_fast: true repos: -- hooks: - - id: black - language_version: python3 - repo: https://github.com/psf/black - rev: 20.8b1 + + - repo: https://github.com/pre-commit/pre-commit-hooks + hooks: + - id: end-of-file-fixer + exclude: .*\.txt + rev: v4.0.1 + + - repo: local + hooks: + - id: static_word_checks + args: + - '--replace' + entry: python -m tools.static_word_checks + language: system + name: Static Word Checks + pass_filenames: false + types: [ python ] + + - id: check_documentation + entry: python -m tools.check_documentation + language: system + name: Check Documentation + pass_filenames: false + types: [ python ] + + - repo: https://github.com/psf/black + hooks: + - id: black + rev: 21.10b0 + + - repo: https://github.com/LilSpazJoekp/docstrfmt + hooks: + - id: docstrfmt + require_serial: true + rev: v1.4.1 + + - repo: https://github.com/pycqa/flake8 + hooks: + - id: flake8 + rev: 4.0.1 + + - repo: https://github.com/ikamensh/flynt/ + hooks: + - id: flynt + args: + - '-ll' + - '1000' + rev: '0.69' + + - repo: https://github.com/pycqa/isort + hooks: + - id: isort + rev: 5.9.3 + + - repo: https://github.com/pycqa/pydocstyle + hooks: + - id: pydocstyle + files: asyncpraw/.* + rev: 6.1.1 diff --git a/docs/conf.py b/docs/conf.py index 5d54b4b35..9effff95b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -6,7 +6,7 @@ sys.path.insert(0, ".") sys.path.insert(1, "..") -from asyncpraw import __version__ +from asyncpraw import __version__ # noqa: E402 copyright = datetime.today().strftime("%Y, Joel Payne") exclude_patterns = ["_build"] diff --git a/docs/package_info/contributing.rst b/docs/package_info/contributing.rst index a4f8baa2a..87c90a2a2 100644 --- a/docs/package_info/contributing.rst +++ b/docs/package_info/contributing.rst @@ -5,22 +5,21 @@ Async PRAW gladly welcomes new contributions. As with most larger projects, we h established consistent way of doing things. A consistent style increases readability, decreases bug-potential and makes it faster to understand how everything works together. -Async PRAW follows :PEP:`8` and :PEP:`257`. The ``pre_push.py`` script can be used to -test for compliance with these PEPs in addition to providing a few other checks. The -following are Async PRAW-specific guidelines in addition to those PEP's. +Async PRAW follows :PEP:`8` and :PEP:`257`. `Pre-Commit ` is +used to manage a suite of pre-commit hooks that enforce conformance with these PEPs +along with several other checks. Additionally, the ``pre_push.py`` script can be used to +run the full pre-commit suite and the docs build prior to submitting a Pull Request. The +following are Async PRAW-specific guidelines in addition to those PEPs. .. note:: - Python 3.6+ is needed to run the script. - -.. note:: - - In order to install the dependencies needed to run the script, you can install the - ``[dev]`` package of asyncpraw, like so: + In order to use the pre-commit hooks and the ``pre_push.py`` dependencies, install + Async PRAW's ``[lint]`` extra, followed by the appropriate Pre-Commit command: .. code-block:: bash - pip install asyncpraw[dev] + pip install asyncpraw[lint] + pre-commit install Code ---- @@ -87,9 +86,9 @@ cassettes. The environment variables are (listed in bash export format): export prawtest_username=myusername export prawtest_user_agent=praw_pytest -By setting these environment variables prior to running ``python setup.py test``, when -adding or updating cassettes, instances of ``mypassword`` will be replaced by the -placeholder text ```` and similar for the other environment variables. +By setting these environment variables prior to running ``pytest``, when adding or +updating cassettes, instances of ``mypassword`` will be replaced by the placeholder text +```` and similar for the other environment variables. To use tokens instead of username/password set ``prawtest_refresh_token`` instead of ``prawtest_password`` and ``prawtest_username``. @@ -114,7 +113,8 @@ Static Checker Async PRAW's test suite comes with a checker tool that can warn you of using incorrect documentation styles (using ``.. code::`` instead of ``.. code-block::``, using ``/r/`` -instead of ``r/``, etc.). +instead of ``r/``, etc.). This is run automatically by the pre-commit hooks and the +``pre_push.py`` script. .. autoclass:: tools.static_word_checks.StaticChecker :inherited-members: diff --git a/pre_push.py b/pre_push.py index 2e0facde0..c927cd98f 100755 --- a/pre_push.py +++ b/pre_push.py @@ -3,12 +3,8 @@ import argparse import sys -from os import path -from shutil import rmtree from subprocess import CalledProcessError, check_call -from tempfile import mkdtemp - -current_directory = path.abspath(path.join(__file__, "..")) +from tempfile import TemporaryDirectory def do_process(args, shell=False): @@ -41,35 +37,10 @@ def run_static(): """ success = True - # Formatters - success &= do_process( - [ - sys.executable, - path.join(current_directory, "tools", "static_word_checks.py"), - "--replace", - ] - ) - success &= do_process(["flynt", "-q", "-tc", "-ll", "1000", "."]) - # needs to be first because flynt is not black compliant - success &= do_process(["black", "."]) - success &= do_process(["docstrfmt", "-e", "docs/examples/*", "."]) - success &= do_process(["isort", "."]) - # Linters - success &= do_process( - [ - sys.executable, - path.join(current_directory, "tools", "check_documentation.py"), - ] - ) - success &= do_process(["flake8", "--exclude=.eggs,build,docs,.venv*"]) - success &= do_process(["pydocstyle", "asyncpraw"]) - # success &= do_process(["pylint", "--rcfile=.pylintrc", "asyncpraw"]) + success &= do_process(["pre-commit", "run", "--all-files"]) - tmp_dir = mkdtemp() - try: + with TemporaryDirectory() as tmp_dir: success &= do_process(["sphinx-build", "-W", "--keep-going", "docs", tmp_dir]) - finally: - rmtree(tmp_dir) return success diff --git a/pyproject.toml b/pyproject.toml index 86b737e05..1bd8d753f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,10 @@ [tool.black] -exclude = '/(\.eggs|\.git|\.hg|\.mypy_cache|\.nox|\.tox|\.venv.*|_build|buck-out|build|dist)/' +extend_exclude = '/(\.venv.*)/' line-length = 88 +[tool.docstrfmt] +extend_exclude = ['./docs/examples/'] + [tool.isort] -profile = "black" -skip_glob = '.venv*' \ No newline at end of file +profile = 'black' +skip_glob = '.venv*' diff --git a/setup.cfg b/setup.cfg index 74d861f9a..31ad82b6a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,9 +1,2 @@ [aliases] test = pytest - -[flake8] -ignore = E203 W503 -per-file-ignores = - asyncpraw/models/__init__.py:F401 - asyncpraw/models/listing/mixins/__init__.py:F401 - asyncpraw/models/reddit/mixins/__init__.py:F401 diff --git a/setup.py b/setup.py index 3fcc04a69..c24810005 100644 --- a/setup.py +++ b/setup.py @@ -15,14 +15,9 @@ extras = { "ci": ["coveralls"], - "dev": ["packaging", "pre-commit"], + "dev": ["packaging"], "lint": [ - "black", - "docstrfmt", - "flake8", - "flynt", - "isort", - "pydocstyle", + "pre-commit", "sphinx", "sphinx_rtd_theme", "sphinxcontrib-trio", diff --git a/tests/integration/cassettes/TestAuthImplicit.test_implicit__with_invalid_token.json b/tests/integration/cassettes/TestAuthImplicit.test_implicit__with_invalid_token.json index f9d093011..6d71c61ac 100644 --- a/tests/integration/cassettes/TestAuthImplicit.test_implicit__with_invalid_token.json +++ b/tests/integration/cassettes/TestAuthImplicit.test_implicit__with_invalid_token.json @@ -54,4 +54,4 @@ ], "recorded_at": "2020-07-04T18:07:23", "version": 1 -} \ No newline at end of file +} diff --git a/tests/integration/cassettes/TestAuthImplicit.test_scopes__read_only.json b/tests/integration/cassettes/TestAuthImplicit.test_scopes__read_only.json index ddf2f8015..c33652cd8 100644 --- a/tests/integration/cassettes/TestAuthImplicit.test_scopes__read_only.json +++ b/tests/integration/cassettes/TestAuthImplicit.test_scopes__read_only.json @@ -64,4 +64,4 @@ ], "recorded_at": "2020-07-04T18:07:24", "version": 1 -} \ No newline at end of file +} diff --git a/tests/integration/cassettes/TestAuthScript.test_scopes.json b/tests/integration/cassettes/TestAuthScript.test_scopes.json index 6646f63e3..542460840 100644 --- a/tests/integration/cassettes/TestAuthScript.test_scopes.json +++ b/tests/integration/cassettes/TestAuthScript.test_scopes.json @@ -60,4 +60,4 @@ ], "recorded_at": "2020-07-04T18:12:48", "version": 1 -} \ No newline at end of file +} diff --git a/tests/integration/cassettes/TestAuthWeb.test_authorize.json b/tests/integration/cassettes/TestAuthWeb.test_authorize.json index 76c53a9ab..4096ac3c1 100644 --- a/tests/integration/cassettes/TestAuthWeb.test_authorize.json +++ b/tests/integration/cassettes/TestAuthWeb.test_authorize.json @@ -67,4 +67,4 @@ ], "recorded_at": "2020-07-04T18:07:23", "version": 1 -} \ No newline at end of file +} diff --git a/tests/integration/cassettes/TestAuthWeb.test_scopes__read_only.json b/tests/integration/cassettes/TestAuthWeb.test_scopes__read_only.json index 7718705ab..ea89b1ae3 100644 --- a/tests/integration/cassettes/TestAuthWeb.test_scopes__read_only.json +++ b/tests/integration/cassettes/TestAuthWeb.test_scopes__read_only.json @@ -60,4 +60,4 @@ ], "recorded_at": "2020-07-04T18:07:23", "version": 1 -} \ No newline at end of file +}