Lightning-AI / Lightning-AI/pytorch-lightning

Loose type annotations of hparams cause Pylint basic type checker false positives

Open
#18,972 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug code quality ver: 2.1.x
Dominant language
Python
Stars
31.4k
Forks
3.8k
Avg merge
6d 7h
Merged PRs (30d)
6

Description

### Bug description

Loose type annotation for `hparams` causes false positives in type checkers if hyperparameters are accessed as attributes.

I have identified the problem and will open a PR shortly.

### What version are you seeing the problem on?

v2.1
v2.0
master

### How to reproduce the bug

```python
Simple snippet:

import pytorch_lightning as pl

class TrivialModule(pl.LightningModule):
def __init__(self, arg: int = 1):
super().__init__()
self.save_hyperparameters()

def forward(self, x: T) -> T:
return x * self.hparams.arg
```

### Error messages and logs

Using VSCode, set the pylint basic type checker to "basic".
You will get the following false positive:

![image](https://github.com/Lightning-AI/lightning/assets/13602468/9f4fb268-e80e-416c-8a5f-f4bcf8961dc4)

This is because `self.hparams` should be annotated as `AttributeDict`, rather than `Union[AttributeDict, MutableMapping]`

### Environment

Current environment

* CUDA:
- GPU:
- NVIDIA A100-PCIE-40GB
- available: True
- version: 11.8
* Lightning:
- lightning-utilities: 0.9.0
- pytorch-lightning: 2.1.1
- torch: 2.0.1
- torch-cluster: 1.6.1
- torch-geometric: 2.3.0
- torchmetrics: 0.11.4
* Packages:
- aiohttp: 3.8.4
- aiohttp-cors: 0.7.0
- aiosignal: 1.3.1
- alembic: 1.11.1
- antlr4-python3-runtime: 4.9.3
- anyio: 3.6.2
- appdirs: 1.4.4
- argcomplete: 3.0.8
- argon2-cffi: 21.3.0
- argon2-cffi-bindings: 21.2.0
- asttokens: 2.2.1
- async-timeout: 4.0.2
- attrs: 23.1.0
- awkward: 2.2.4
- awkward-cpp: 17
- backcall: 0.2.0
- backports.functools-lru-cache: 1.6.4
- beautifulsoup4: 4.12.2
- bleach: 6.0.0
- blessed: 1.20.0
- bokeh: 2.4.3
- cachetools: 5.3.1
- certifi: 2023.5.7
- cffi: 1.15.1
- cfgv: 3.4.0
- charset-normalizer: 3.1.0
- click: 8.1.3
- cloudpickle: 2.2.1
- cmaes: 0.9.1
- colorama: 0.4.6
- colorful: 0.5.5
- colorlog: 6.7.0
- comm: 0.1.3
- configparser: 6.0.0
- contourpy: 1.0.7
- coolname: 2.2.0
- coverage: 7.2.7
- cubinlinker: 0.3.0
- cuda-python: 11.8.2
- cudf: 23.6.1
- cugraph: 23.6.2
- cuml: 23.6.0
- cupy: 12.1.0
- cycler: 0.11.0
- cytoolz: 0.12.0
- dask: 2023.3.2
- dask-cuda: 23.6.0
- dask-cudf: 23.6.1
- debugpy: 1.6.7
- decorator: 5.1.1
- defusedxml: 0.7.1
- distlib: 0.3.6
- distributed: 2023.3.2.1
- distro: 1.8.0
- docker-pycreds: 0.4.0
- docstring-parser: 0.15
- entrypoints: 0.4
- exceptiongroup: 1.1.1
- executing: 1.2.0
- fastjsonschema: 2.17.1
- fastrlock: 0.8
- filelock: 3.12.0
- flit-core: 3.9.0
- fonttools: 4.39.4
- frozenlist: 1.3.3
- fsspec: 2023.6.0
- gitdb: 4.0.10
- gitpython: 3.1.31
- gmpy2: 2.1.2
- gnn-tracking: 0.0.1
- gnn-tracking-hpo: 0.1.0
- gnntrack: 0.0.1
- google-api-core: 2.11.0
- google-auth: 2.19.0
- googleapis-common-protos: 1.59.0
- gpustat: 1.1
- gql: 0.2.0
- graphql-core: 1.1
- greenlet: 2.0.2
- grpcio: 1.51.3
- hpo2: 0.1.0
- hydra-core: 1.3.2
- identify: 2.5.27
- idna: 3.4
- importlib-metadata: 6.6.0
- importlib-resources: 5.12.0
- iniconfig: 2.0.0
- ipykernel: 6.23.1
- ipython: 8.13.2
- ipython-genutils: 0.2.0
- ipywidgets: 8.0.6
- jedi: 0.18.2
- jinja2: 3.1.2
- joblib: 1.2.0
- jsonargparse: 4.22.0
- jsonschema: 4.17.3
- jupyter: 1.0.0
- jupyter-client: 8.2.0
- jupyter-console: 6.6.3
- jupyter-core: 5.3.0
- jupyter-events: 0.6.3
- jupyter-server: 2.6.0
- jupyter-server-terminals: 0.4.4
- jupyterlab-pygments: 0.2.2
- jupyterlab-widgets: 3.0.7
- jupytext: 1.15.1
- kiwisolver: 1.4.4
- lightning-utilities: 0.9.0
- llvmlite: 0.40.1
- locket: 1.0.0
- lstcondensation: 0.0.1
- lz4: 4.3.2
- mako: 1.2.4
- markdown-it-py: 3.0.0
- markupsafe: 2.1.2
- matplotlib: 3.7.1
- matplotlib-inline: 0.1.6
- mdit-py-plugins: 0.4.0
- mdmm: 0.1.3
- mdurl: 0.1.2
- mistune: 2.0.5
- mplhep: 0.3.28
- mplhep-data: 0.0.3
- mpmath: 1.3.0
- msgpack: 1.0.5
- multidict: 6.0.4
- nbclassic: 1.0.0
- nbclient: 0.8.0
- nbconvert: 7.4.0
- nbformat: 5.8.0
- nest-asyncio: 1.5.6
- networkx: 3.1
- nodeenv: 1.8.0
- notebook: 6.5.4
- notebook-shim: 0.2.3
- numba: 0.57.1
- numpy: 1.24.3
- nvidia-ml-py: 11.525.112
- nvidia-ml-py3: 7.352.0
- nvtx: 0.2.5
- object-condensation: 0.1.dev30+g1e5e4df
- ocpaper231: 0.1.0
- omegaconf: 2.3.0
- opencensus: 0.11.2
- opencensus-context: 0.1.3
- optuna: 3.1.1
- overrides: 7.3.1
- packaging: 23.1
- pandas: 1.5.3
- pandocfilters: 1.5.0
- parso: 0.8.3
- partd: 1.4.0
- pathtools: 0.1.2
- pexpect: 4.8.0
- pickleshare: 0.7.5
- pillow: 10.0.0
- pip: 23.1.2
- pipx: 1.2.0
- pkgutil-resolve-name: 1.3.10
- platformdirs: 3.5.1
- pluggy: 1.0.0
- ply: 3.11
- pooch: 1.7.0
- pre-commit: 3.3.3
- prometheus-client: 0.17.0
- promise: 2.3
- prompt-toolkit: 3.0.38
- protobuf: 3.20.0
- psutil: 5.9.5
- ptxcompiler: 0.8.1
- ptyprocess: 0.7.0
- pure-eval: 0.2.2
- py-spy: 0.3.14
- pyarrow: 11.0.0
- pyasn1: 0.5.0
- pyasn1-modules: 0.3.0
- pycparser: 2.21
- pydantic: 1.10.8
- pygments: 2.15.1
- pylibcugraph: 23.6.2
- pylibraft: 23.6.1
- pynvml: 11.4.1
- pyparsing: 3.0.9
- pyperclip: 1.8.2
- pyqt5: 5.15.7
- pyqt5-sip: 12.11.0
- pyrsistent: 0.19.3
- pysocks: 1.7.1
- pytest: 7.3.1
- pytest-cov: 4.1.0
- python-dateutil: 2.8.2
- python-json-logger: 2.0.7
- pytimeparse: 1.1.8
- pytorch-lightning: 2.1.1
- pytz: 2023.3
- pyyaml: 6.0
- pyzmq: 25.0.2
- qtconsole: 5.4.3
- qtpy: 2.3.1
- raft-dask: 23.6.1
- ranger-fm: 1.9.3
- ray: 2.4.0
- requests: 2.31.0
- rfc3339-validator: 0.1.4
- rfc3986-validator: 0.1.1
- rich: 13.4.2
- rmm: 23.6.0
- rsa: 4.9
- rt-stoppers-contrib: 1.1.2
- scienceplots: 2.1.0
- scikit-learn: 1.2.2
- scipy: 1.10.1
- seaborn: 0.12.2
- send2trash: 1.8.2
- sentry-sdk: 1.26.0
- setproctitle: 1.3.2
- setuptools: 68.0.0
- shortuuid: 1.0.11
- sip: 6.7.9
- six: 1.16.0
- smart-open: 6.3.0
- smmap: 5.0.0
- sniffio: 1.3.0
- sortedcontainers: 2.4.0
- soupsieve: 2.3.2.post1
- sqlalchemy: 2.0.15
- stack-data: 0.6.2
- subprocess32: 3.5.4
- sympy: 1.12
- tabulate: 0.9.0
- tblib: 1.7.0
- tensorboardx: 2.6
- terminado: 0.17.1
- threadpoolctl: 3.1.0
- tinycss2: 1.2.1
- toml: 0.10.2
- tomli: 2.0.1
- toolz: 0.12.0
- torch: 2.0.1
- torch-cluster: 1.6.1
- torch-geometric: 2.3.0
- torchmetrics: 0.11.4
- tornado: 6.3.2
- tqdm: 4.65.0
- trackml: 3
- traitlets: 5.9.0
- treelite: 3.2.0
- treelite-runtime: 3.2.0
- triton: 2.0.0
- typeshed-client: 2.3.0
- typing-extensions: 4.6.2
- typing-utils: 0.1.0
- ucx-py: 0.32.0
- uhi: 0.3.3
- ujson: 5.8.0
- uproot: 5.0.9
- urllib3: 2.0.3
- userpath: 1.8.0
- virtualenv: 20.21.0
- wandb: 0.15.11
- wandb-osh: 1.1.2
- watchdog: 3.0.0
- wcwidth: 0.2.6
- webencodings: 0.5.1
- websocket-client: 1.5.2
- wheel: 0.40.0
- widgetsnbextension: 4.0.7
- xonsh: 0.14.1
- yarl: 1.9.2
- zict: 3.0.0
- zipp: 3.15.0
* System:
- OS: Linux
- architecture:
- 64bit
- ELF
- processor: x86_64
- python: 3.10.11
- release: 4.18.0-477.27.1.el8_8.x86_64
- version: #1 SMP Sun Sep 24 11:46:42 EDT 2023

### More info

A workaround for the linter errors is to just access hyperparameters via the dictionary interface.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating the LightningModule hparams annotation and the self.hparams access shown in the reproduction. Verify the behavior with Pylint's basic type checker using the provided snippet; done means attribute-style hyperparameter access no longer produces the reported false positive.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
machine-learning, tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.