diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml index 203c0fb846..3e2f296226 100644 --- a/.github/workflows/code-formatting.yml +++ b/.github/workflows/code-formatting.yml @@ -22,70 +22,21 @@ jobs: - name: Run isort run: isort --settings-path=./pyproject.toml --check-only --diff . - code-black: - name: Check code formatting with Black - runs-on: ubuntu-20.04 - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Python 3.8 - uses: actions/setup-python@v2 - with: - python-version: 3.8 - - name: Install Black - run: pip install black==19.10b0 - - name: Run Black - run: echo "LGTM" - # run black --skip-string-normalization --config=pyproject.toml --check . # TODO, uncomment - - python-types: - name: Python static type checking with Pyright - runs-on: ubuntu-20.04 - - # Timeout: https://stackoverflow.com/a/59076067/4521646 - timeout-minutes: 15 - steps: - - name: Checkout - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 - with: - python-version: 3.7 - - # Note: This uses an internal pip API and may not always work - # https://github.com/actions/cache/blob/master/examples.md#multiple-oss-in-a-workflow - - name: Cache pip - uses: actions/cache@v2 - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-extras-${{ hashFiles('requirements.txt') }}-${{ hashFiles('requirements/extra.txt') }} - restore-keys: | - ${{ runner.os }}-pip-extras- - - - name: Install dependencies - env: - HOROVOD_BUILD_ARCH_FLAGS: "-mfma" - HOROVOD_WITHOUT_MXNET: 1 - HOROVOD_WITHOUT_TENSORFLOW: 1 - run: | - # python -m pip install --upgrade --user pip - pip install --requirement requirements.txt --upgrade-strategy only-if-needed --find-links https://download.pytorch.org/whl/cpu/torch_stable.html --quiet - pip install --requirement ./requirements/devel.txt --quiet - # pip install tox coverage - python --version ; pip --version ; pip list - shell: bash - - - name: Set up node - uses: actions/setup-node@v1 - with: - node-version: '12' - - - name: Install pyright - run: | - npm install pyright - - - name: Run type checking - run: | - $(npm bin)/pyright --project .pyrightconfig.json + #code-black: + # name: Check code formatting with Black + # runs-on: ubuntu-20.04 + # steps: + # - name: Checkout + # uses: actions/checkout@v2 + # - name: Set up Python 3.8 + # uses: actions/setup-python@v2 + # with: + # python-version: 3.8 + # - name: Install Black + # run: pip install black==19.10b0 + # - name: Run Black + # run: echo "LGTM" + # run black --skip-string-normalization --config=pyproject.toml --check . # TODO, uncomment python-pep8: name: Python formatting PEP8 @@ -107,3 +58,19 @@ jobs: - name: Run checking run: | flake8 . + + python-typing-mypy: + name: Python typing check [mypy] + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@master + - uses: actions/setup-python@v2 + with: + python-version: 3.8 + - name: Install mypy + run: | + pip install mypy + pip list + - name: mypy check + run: | + mypy diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9b481e9ecf..78684a2ab7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -30,3 +30,7 @@ repos: args: [--settings-path, ./pyproject.toml] language: system types: [python] + + - repo: https://github.com/pre-commit/mirrors-mypy + hooks: + - id: mypy diff --git a/.pyrightconfig.json b/.pyrightconfig.json deleted file mode 100644 index 416b33f6ad..0000000000 --- a/.pyrightconfig.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "include": [ - "pytorch_lightning" - ], - - "ignore": [ - "pytorch_lightning/__init__.py", - "pytorch_lightning/callbacks", - "pytorch_lightning/core", - "pytorch_lightning/accelerators", - "pytorch_lightning/loggers", - "pytorch_lightning/logging", - "pytorch_lightning/metrics", - "pytorch_lightning/overrides", - "pytorch_lightning/profiler", - "pytorch_lightning/pt_overrides", - "pytorch_lightning/root_module", - "pytorch_lightning/utilities", - "pytorch_lightning/trainer/data_loading.py", - "pytorch_lightning/trainer/deprecated_api.py", - "pytorch_lightning/trainer/distrib_parts.py", - "pytorch_lightning/trainer/evaluation_loop.py", - "pytorch_lightning/trainer/logging.py", - "pytorch_lightning/trainer/lr_finder.py", - "pytorch_lightning/trainer/optimizers.py", - "pytorch_lightning/trainer/supporters.py", - "pytorch_lightning/trainer/trainer.py", - "pytorch_lightning/trainer/training_io.py", - "pytorch_lightning/trainer/training_loop.py", - "pytorch_lightning/trainer/training_tricks.py", - "pytorch_lightning/trainer/batch_size_scaling.py", - "pytorch_lightning/trainer/distrib_data_parallel.py", - "pytorch_lightning/trainer/properties.py", - "pytorch_lightning/trainer/lr_scheduler_connector.py", - "pytorch_lightning/trainer/training_loop_temp.py", - "pytorch_lightning/trainer/connectors/checkpoint_connector.py", - "pytorch_lightning/trainer/connectors/data_connector.py", - "pytorch_lightning/trainer/connectors/logger_connector.py", - "pytorch_lightning/trainer/connectors/slurm_connector.py", - "pytorch_lightning/distributed/dist.py", - "pytorch_lightning/tuner", - "pytorch_lightning/plugins" - ], - - "reportMissingImports": false -} diff --git a/pytorch_lightning/__init__.py b/pytorch_lightning/__init__.py index f543e4382c..2a73974223 100644 --- a/pytorch_lightning/__init__.py +++ b/pytorch_lightning/__init__.py @@ -47,9 +47,9 @@ try: # This variable is injected in the __builtins__ by the build # process. It used to enable importing subpackages of skimage when # the binaries are not built - __LIGHTNING_SETUP__ + _ = None if __LIGHTNING_SETUP__ else None except NameError: - __LIGHTNING_SETUP__ = False + __LIGHTNING_SETUP__: bool = False if __LIGHTNING_SETUP__: import sys # pragma: no-cover diff --git a/pytorch_lightning/setup_tools.py b/pytorch_lightning/setup_tools.py index c29076c41f..590d2d396b 100644 --- a/pytorch_lightning/setup_tools.py +++ b/pytorch_lightning/setup_tools.py @@ -15,6 +15,7 @@ import os import re import warnings +from typing import Iterable, List from urllib.error import HTTPError, URLError from urllib.request import Request, urlopen @@ -37,7 +38,7 @@ _DEFAULT_BADGES = [ ] -def _load_requirements(path_dir, file_name='requirements.txt', comment_char='#'): +def _load_requirements(path_dir: str , file_name: str = 'requirements.txt', comment_char: str = '#') -> List[str]: """Load requirements from a file >>> _load_requirements(PROJECT_ROOT) # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE @@ -58,7 +59,7 @@ def _load_requirements(path_dir, file_name='requirements.txt', comment_char='#') return reqs -def _parse_for_badge(text: str, path_badges: str = _PATH_BADGES, badge_names: list = _DEFAULT_BADGES): +def _parse_for_badge(text: str, path_badges: str = _PATH_BADGES, badge_names: Iterable = _DEFAULT_BADGES) -> str: """ Returns the new parsed text with url change with local downloaded files >>> _parse_for_badge('Some text here... ' # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE @@ -90,12 +91,12 @@ def _parse_for_badge(text: str, path_badges: str = _PATH_BADGES, badge_names: li return text -def _save_file(url_badge, save, extension, headers): +def _save_file(url_badge: str, save_path: str, extension: str, headers: dict) -> None: """function for saving the badge either in `.png` or `.svg`""" # because there are two badge with name `PyPI Status` the second one is download if 'https://pepy.tech/badge/pytorch-lightning' in url_badge: - save += '_downloads' + save_path += '_downloads' try: req = Request(url=url_badge, headers=headers) @@ -103,12 +104,12 @@ def _save_file(url_badge, save, extension, headers): except URLError: warnings.warn("Error while downloading the badge", UserWarning) else: - save += extension - with open(save, 'wb') as download_file: + save_path += extension + with open(save_path, 'wb') as download_file: download_file.write(resp.read()) -def _download_badge(url_badge, badge_name, target_dir): +def _download_badge(url_badge: str, badge_name: str, target_dir: str) -> str: """Download badge from url >>> path_img = _download_badge('https://img.shields.io/pypi/pyversions/pytorch-lightning', @@ -143,9 +144,10 @@ def _download_badge(url_badge, badge_name, target_dir): url_badge = url_badge.replace('.png', '.svg') _save_file(url_badge, save_path, extension='.svg', headers=headers) return save_path + '.svg' + return '' -def _load_long_description(path_dir): +def _load_long_description(path_dir: str) -> str: """Load readme as decribtion >>> _load_long_description(PROJECT_ROOT) # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE diff --git a/requirements/test.txt b/requirements/test.txt index 74c62f82c7..3cb538a98d 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -12,6 +12,7 @@ scikit-learn>=0.22.2 scikit-image>=0.17.2 black>=20.8b1 isort>=5.6.4 +mypy>=0.720 pre-commit>=1.0 cloudpickle>=1.3 diff --git a/setup.cfg b/setup.cfg index 2802806f60..b0c2c8640b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -93,3 +93,88 @@ convention = pep257 # D202: Ignore a blank line after docstring (collision with Python Black in decorators) add-ignore = D104,D107,D202 max-line-length = 120 + + +[mypy] +# Typing tests is low priority, but enabling type checking on the +# untyped test functions (using `--check-untyped-defs`) is still +# high-value because it helps test the typing. +files = pytorch_lightning, pl_examples, benchmarks, tests +disallow_untyped_defs = True +ignore_missing_imports = True + +# todo: add proper typing to this module... +[mypy-pytorch_lightning.callbacks.*] +ignore_errors = True + +# todo: add proper typing to this module... +[mypy-pytorch_lightning.core.*] +ignore_errors = True + +# todo: add proper typing to this module... +[mypy-pytorch_lightning.accelerators.*] +ignore_errors = True + +# todo: add proper typing to this module... +[mypy-pytorch_lightning.cluster_environments.*] +ignore_errors = True + +# todo: add proper typing to this module... +[mypy-pytorch_lightning.loggers.*] +ignore_errors = True + +# todo: add proper typing to this module... +[mypy-pytorch_lightning.logging.*] +ignore_errors = True + +# todo: add proper typing to this module... +[mypy-pytorch_lightning.metrics.*] +ignore_errors = True + +# todo: add proper typing to this module... +[mypy-pytorch_lightning.overrides.*] +ignore_errors = True + +# todo: add proper typing to this module... +[mypy-pytorch_lightning.profiler.*] +ignore_errors = True + +# todo: add proper typing to this module... +[mypy-pytorch_lightning.pt_overrides.*] +ignore_errors = True + +# todo: add proper typing to this module... +[mypy-pytorch_lightning.plugins.*] +ignore_errors = True + +# todo: add proper typing to this module... +[mypy-pytorch_lightning.root_module.*] +ignore_errors = True + +# todo: add proper typing to this module... +[mypy-pytorch_lightning.trainer.*] +ignore_errors = True + +# todo: add proper typing to this module... +[mypy-pytorch_lightning.distributed.*] +ignore_errors = True + +# todo: add proper typing to this module... +[mypy-pytorch_lightning.tuner.*] +ignore_errors = True + +# todo: add proper typing to this module... +[mypy-pytorch_lightning.utilities.*] +ignore_errors = True + +# todo: add proper typing to this module... +[mypy-pl_examples.*] +ignore_errors = True + +# todo: add proper typing to this module... +[mypy-benchmarks.*] +ignore_errors = True + +# todo: add proper typing to this module... +[mypy-tests.*] +ignore_errors = True