Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Tismer <tismer@stackless.com>2024-10-23 12:27:03 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2024-10-31 20:30:28 +0000
commit5ff2e48b114f566663893a4b8c9abb4ff892f2ff (patch)
treef410e77e57b898d2a5d83fd586167b9adc74bf35
parentc83e15fe6a52b2ce484f1e41f8306df2e5de1c7c (diff)
type hints: Add some mypy explanations to developer docs6.8.0
First attempt to explain a little how mypy errors were treated. Task-number: PYSIDE-2846 Change-Id: I13a0d2b8298d5fd1637d3bca9e2b979c7062b811 Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io> (cherry picked from commit c37642f241fb21ae81bb7ff8721deb8a423ef0c1) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> (cherry picked from commit 91c015fdc43bf58c829a043f54b50e3cebabce55)
-rw-r--r--sources/pyside6/doc/developer/index.rst1
-rw-r--r--sources/pyside6/doc/developer/mypy-correctness.rst186
-rw-r--r--sources/pyside6/doc/developer/signature_doc.rst57
3 files changed, 224 insertions, 20 deletions
diff --git a/sources/pyside6/doc/developer/index.rst b/sources/pyside6/doc/developer/index.rst
index d158b6690..bddd39d91 100644
--- a/sources/pyside6/doc/developer/index.rst
+++ b/sources/pyside6/doc/developer/index.rst
@@ -34,4 +34,5 @@ many features and implementation details that the project has:
enumfeatures_doc.rst
limited_api.rst
signature_doc.rst
+ mypy-correctness.rst
feature-motivation.rst
diff --git a/sources/pyside6/doc/developer/mypy-correctness.rst b/sources/pyside6/doc/developer/mypy-correctness.rst
new file mode 100644
index 000000000..8f0d63a1d
--- /dev/null
+++ b/sources/pyside6/doc/developer/mypy-correctness.rst
@@ -0,0 +1,186 @@
+.. mypy-correctness:
+
+Improving the Quality of Signatures with mypy
+=============================================
+
+Preliminary
+-----------
+
+The Python Interface files of PySide are generated by a few scripts.
+When ``.pyi`` files were started in 2017, a minimal syntax check was
+possible because these files could be run in ``Python`` itself.
+
+Some changes to the format of ``.pyi`` files made that impossible, leaving
+``PySide``'s ``.pyi`` files quite unchecked for years. Only correct parsing of
+all functions could be checked by the generator.
+
+The introduction of the ``mypy`` tool as a rigorous error checker for the
+generated files brought many improvements, but also some surprizes.
+
+
+Running the mypy Tests
+----------------------
+
+The ``mypy`` tests are automatically run by the Qt company CI framework (COIN).
+When you have ``mypy`` installed, the tests are run when building with tests.
+In debug mode, this can take more than 30 s, therefore we provide the
+translation option
+
+.. code-block:: shell
+
+ --skip-mypy-test
+
+which can be used when repeatedly translating. But note that ``mypy`` has a
+good cache that suppresses analysis of unchanged ``.pyi`` files.
+
+
+Types of mypy Errors
+--------------------
+
+Duplication Errors
+~~~~~~~~~~~~~~~~~~
+
+Many functions have multiple signatures, which are later translated to multiple
+``typing.overload`` versions in the ``.pyi`` file.
+Due to the mapping of ``C++`` functions to ``Python`` it sometimes happens
+that similar ``C++`` functions become ``Python`` duplicates. This was simple
+to filter out, but ``mypy`` still finds duplicates which differ only in parameter
+names. This is now handled by the function ``remove_ambiguous_signatures()``
+in module ``layout`` that compares the so-called ``annotations`` which ignore
+parameter names.
+
+
+Shadowing Errors
+~~~~~~~~~~~~~~~~
+
+A quite subtle error type is the shadowing of multiple signatures. This is due
+to the sequential nature of ``.pyi`` files::
+
+ * In ``C++``, the order of functions does not matter at all. The best fit is
+ automatically used.
+
+ * In Python stub files, the alternatives of multiple signatures are sequentially
+ checked in ``@typing.overload`` chains of functions.
+ This can produce shadowing when an annotation contains another.
+
+An Example: :class:`PySide6.QtCore.QCborSimpleType` is shadowed by int
+when int is listed first. That is due to the Method Resolution Order ``mro()``::
+
+ * int.mro() [<class 'int'>, <class 'object'>]
+
+ * QCborSimpleType.mro() [<enum 'QCborSimpleType'>, <enum 'IntEnum'>,
+ <class 'int'>, <enum 'ReprEnum'>,
+ <enum 'Enum'>, <class 'object'>]
+
+You see that the ``mro()`` has an ordering effect on the multiple signatures.
+The enum inherits from ``int`` and should come before the ``int`` entry.
+The whole task of bringing the multiple signatures into a conflict-free order
+is a sort of ``Topological Sorting``.
+
+We build a sorting key using the length of the ``mro`` of the argument annotations
+and some additional heuristics. They can be inspected in function ``get_ordering_key()``
+that is called by ``sort_by_inheritance()`` in module ``layout``.
+
+
+Unsolvable Errors
+-----------------
+
+Some errors are pointed out by mypy that we cannot solve. The only chance we have is
+to disable these errors partially or even completely. They are marked in the ``.pyi`` files,
+see below.
+
+
+Contradiction to Qt
+~~~~~~~~~~~~~~~~~~~
+
+Errors are found by mypy where Qt has a different opinion. The error types
+"override" and "overload-overlap" needed to be disabled because we cannot
+change what Qt thinks is right.
+
+Examples:
+
+::
+
+ Error code "override" cannot be fixed because the problem
+ is situated in Qt itself:
+
+ Signature of "open" incompatible with supertype "QFile"
+
+ Error code "overload-overlap" also cannot be fixed because
+ we have no chance to modify return-types:
+
+ Overloaded function signatures 1 and 6 overlap with
+ incompatible return types
+
+They are globally disabled by the comment::
+
+ # mypy: disable-error-code="override, overload-overlap"
+
+Other errors like "misc" are too broad to be prematurely disabled.
+See below how we handle them.
+
+
+Disagreement with __add__ and __iadd__
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+There are internal rules for ``Python`` which can only be recognized when
+``mypy`` points them out as "misc". There are functions which come in pairs:
+
+.. code-block:: python
+
+ __add__, __iadd__, __sub__, __isub__, __mul__, __imul__, ...
+
+and more. There is this rule::
+
+ if __add__ and __iadd__ exist in a type, the signatures must be the same.
+
+In 95 % this rule is fulfilled, but in a few cases it is not. There we have
+to compute these cases, and if they disagree we generate a disabling ``mypy``
+inline comment "# type: ignore[misc]". You can see this functionality in
+``ExactEnumerator.klass`` of module ``enum_sig``.
+
+
+Disagreement with inconsistent overloads
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If there is a mixed overloading of methods and static or class methods, mypy
+believes this is an error. In a few cases we have this situation, and since
+this is again treated as a "misc" error, we only disable this when it
+happens. See function ``is_inconsistent_overload()`` of module
+``pyi_generator`` which checks if "self" is always or never an argument.
+This is again marked by an inline comment "# type: ignore[misc]".
+
+
+Conclusion and Future
+---------------------
+
+This effort has brought the reported ``mypy`` errors from 601 down to zero, which
+is really an improvement. But there can be done more. Although we now know that we
+are generating syntactically and semantically quite correct files, we still do not know
+whether the real types really fulfil the requirements of ``mypy``.
+
+There is a ``stubtest`` module in ``mypy`` which we might perhaps use to do even
+more tests. These would check if the implementation and stub files agree.
+
+
+Literature
+----------
+
+* `mypy error codes <https://mypy.readthedocs.io/en/stable/error_code_list.html>`__
+ We use these by default enabled codes.
+
+* `typing — Support for type hints <https://docs.python.org/3/library/typing.html>`__
+ The Python documentation of the typing module
+
+* `Typing cheat sheet <https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html>`__
+ A quick overview of type hints (hosted at the mypy docs)
+
+* "Type System Reference" section of `the mypy docs <https://mypy.readthedocs.io/en/stable/index.html>`__
+ The Python typing system is standardised via PEPs, so this reference should
+ broadly apply to most Python type checkers. (Some parts may still be specific to mypy.)
+
+* `Static Typing with Python <https://typing.readthedocs.io/en/latest/>`__
+ Type-checker-agnostic documentation written by the community detailing type system features, useful typing related tools and typing best practices.
+
+* `Specification for the Python type system <https://typing.readthedocs.io/en/latest/spec/index.html>`__
+ The complete specification. Quite exhaustive.
diff --git a/sources/pyside6/doc/developer/signature_doc.rst b/sources/pyside6/doc/developer/signature_doc.rst
index a6c703dab..fa1127240 100644
--- a/sources/pyside6/doc/developer/signature_doc.rst
+++ b/sources/pyside6/doc/developer/signature_doc.rst
@@ -110,26 +110,26 @@ The C++ code involved with the signature module is completely in the file
shiboken6/libshiboken/signature.cpp . All other functionality is implemented in
the ``signature`` Python package. It has the following structure::
- sources/shiboken6/shibokenmodule/files.dir/shibokensupport
- ├── __init__.py
- ├── feature.py
- ├── fix-complaints.py
- ├── shibokensupport.pyproject
- └── signature
- ├── PSF-3.7.0.txt
- ├── __init__.py
- ├── errorhandler.py
- ├── importhandler.py
- ├── layout.py
- ├── lib
- │   ├── __init__.py
- │   ├── enum_sig.py
- │   ├── pyi_generator.py
- │   └── tool.py
- ├── loader.py
- ├── mapping.py
- ├── parser.py
- └── qt_attribution.json
+ sources/shiboken6/shibokenmodule/files.dir/shibokensupport
+ ├── __init__.py
+ ├── feature.py
+ ├── fix-complaints.py
+ ├── shibokensupport.pyproject
+ └── signature
+ ├── PSF-3.7.0.txt
+ ├── __init__.py
+ ├── errorhandler.py
+ ├── importhandler.py
+ ├── layout.py
+ ├── lib
+ │ ├── __init__.py
+ │ ├── enum_sig.py
+ │ ├── pyi_generator.py
+ │ └── tool.py
+ ├── loader.py
+ ├── mapping.py
+ ├── parser.py
+ └── qt_attribution.json
Really important are the **parser**, **mapping**, **errorhandler**, **enum_sig**,
**layout** and **loader** modules. The rest is needed to create Python 2 compatibility
@@ -350,6 +350,23 @@ as default content for docstrings.
This was implemented in ``Qt For Python 5.12.1``.
+Update and Future of the Signature Module
+-----------------------------------------
+
+.. code-block:: bash
+
+ PYSIDE-2101: The __signature__ attribute is gone due to rlcompleter.
+
+End of 2022, a change to the rlcompleter module made it impossible to further
+support an unofficial ``__signature__`` attribute in PySide. From then on,
+the functionality of signatures was kept by a ``get_signature`` function.
+
+Over the years, the requirements for the correctness of the generated pyi files
+have increased drastically, and a lot of effort went into making the generated
+``.pyi`` files correct for the current ``mypy`` tool. Mode information
+about the kind of errors corrected can be found in the :ref:`mypy-correctnes` section.
+
+
Literature
----------