Skip to content

dev-tools replace deprecated typing aliases with those from collections#1851

Merged
mhucka merged 18 commits into
quantumlib:mainfrom
micpap25:typing-update-dev-tools
Jun 15, 2026
Merged

dev-tools replace deprecated typing aliases with those from collections#1851
mhucka merged 18 commits into
quantumlib:mainfrom
micpap25:typing-update-dev-tools

Conversation

@micpap25

@micpap25 micpap25 commented May 8, 2026

Copy link
Copy Markdown
Contributor

Partial on #1653
As suggested by @mhucka isolate the changes from #1677 to smaller subsets of the codebase so that the review process is easier.
This PR removes compatibility with pre-3.10 python versions, but Qualtran isn't intended to target those anymore.

Remove pre-3.10 python version targeting, and for the dev-tools folder, update typing classes to modern standards.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates type annotations across the codebase to use built-in collection types and collections.abc equivalents, replacing the older typing module generics. It also simplifies imports in protocol buffer interface files by removing conditional typing_extensions logic in favor of the standard typing module. I have no feedback to provide as there were no review comments.

@mhucka mhucka left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this work! It's quite thorough.

I found one place where there's a subtle bug, and a few suggestions for minor tweaks elsewhere, but otherwise this is almost done!

Comment thread qualtran/protos/bloq_pb2.pyi
if annot['ssa'] != 'SympySymbolAllocator':
print(f"{bc}.build_call_graph `ssa: 'SympySymbolAllocator'`")
if annot['return'] != Set[ForwardRef('BloqCountT')]: # type: ignore[misc]
if annot['return'] != set[ForwardRef('BloqCountT')]: # type: ignore[misc]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is incorrect. The typing.Set and the built-in set are not considered equal when used in type annotations, even if they contain the same arguments. Here is a small test program to demonstrate:

from typing import ForwardRef, Set

# Original annotation using typing.Set
original = Set[ForwardRef('BloqCountT')]

# PEP 585 annotation using built-in set
pep585 = set[ForwardRef('BloqCountT')]

print(f"Is {original} == {pep585}?")
print(f"Result: {original == pep585}")

In the typing module, parameterizing a type with a string automatically wraps that string in a ForwardRef object. That meant that typing.Set['BloqCountT'] was identical to typing.Set[typing.ForwardRef('BloqCountT')] in the previous version of the code. However, PEP 585's built-in collections do not auto-convert strings to ForwardRef objects. When it evaluates set['BloqCountT'], Python directly creates a types.GenericAlias containing the literal string 'BloqCountT'.

The fix in this particular case turns out to be easy: get rid of the ForwardRef completely and do:

    if annot['return'] != set['BloqCountT']:  # type: ignore[misc]

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to know, because I replace typing.Set with set throughout the other parts of the code; I could go and fix that as well / remove the ForwardRef usage there too? I will make the suggested fix, though.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding this bug, it seems that making the change you recommended causes an issue in the dev-tools CI about BloqCountT being undefined. It seems fixing this for every type typing.Set is changed to the built-in set will require a lot of TYPE_CHECKING imports?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh. Let me look at it over the weekend.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding this bug, it seems that making the change you recommended causes an issue in the dev-tools CI about BloqCountT being undefined. It seems fixing this for every type typing.Set is changed to the built-in set will require a lot of TYPE_CHECKING imports?

I don't have an answer to this yet, but I see all the other comments have been resolved (thank you), so what's left is this question and the .pyi files question above.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just following up to see if you've had a chance to test this? Thanks!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@micpap25 Finally got back to this.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding this bug, it seems that making the change you recommended causes an issue in the dev-tools CI about BloqCountT being undefined. It seems fixing this for every type typing.Set is changed to the built-in set will require a lot of TYPE_CHECKING imports?

In the current PR, the change does not seem to be that bad. I did it locally to test:

diff --git a/dev_tools/bloq-method-overrides-report.py b/dev_tools/bloq-method-overrides-report.py
index 77f51231..836f342a 100644
--- a/dev_tools/bloq-method-overrides-report.py
+++ b/dev_tools/bloq-method-overrides-report.py
@@ -11,7 +11,7 @@
 #  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 #  See the License for the specific language governing permissions and
 #  limitations under the License.
-from typing import TYPE_CHECKING
+from typing import TYPE_CHECKING, Set
 
 from qualtran_dev_tools.bloq_finder import get_bloq_classes
 
@@ -45,7 +45,7 @@ def _call_graph(bc: type[Bloq]):
         )
     if annot['ssa'] != 'SympySymbolAllocator':
         print(f"{bc}.build_call_graph `ssa: 'SympySymbolAllocator'`")
-    if annot['return'] != set['BloqCountT']:  # type: ignore[misc]
+    if annot['return'] != Set['BloqCountT']:  # type: ignore[misc]
         print(f"{bc}.build_call_graph -> 'BloqCountT'")
 
 
diff --git a/dev_tools/bloq-quickstarter.html b/dev_tools/bloq-quickstarter.html
index 7ae2240a..d7f16cad 100644
--- a/dev_tools/bloq-quickstarter.html
+++ b/dev_tools/bloq-quickstarter.html
@@ -215,7 +215,7 @@
       signature += "\n        ])"
 
       const template = `from functools import cached_property
-from typing import Optional, Union
+from typing import Optional, Union, Set
 
 from attrs import frozen

Comment thread dev_tools/qualtran_dev_tools/reference_docs.py Outdated
Comment thread dev_tools/qualtran_dev_tools/bloq_report_card.py Outdated
Comment thread dev_tools/qualtran_dev_tools/bloq_report_card.py Outdated
Comment thread dev_tools/qualtran_dev_tools/make_reference_docs/_components/render_docstring.py Outdated

@mhucka mhucka left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@micpap25 Sorry for the delay in getting back to this. I tested it and mypy and pytest are all happy in my Python 3.12 environment.

To make the code cleaner and avoid having to wrap type annotations in string quotes like 'Writable', we should add from __future__ import annotations to the top of the files that use Writable.

By putting that as the first instruction in the files, Python postpones evaluation of all type annotations at runtime. This allows you to write unquoted type hints. Illustration:

from __future__ import annotations
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from .._linking_writer import Writable

# Note that Writable now does not need to be quoted.
def _write_text(f: Writable, part: DocstringSectionText, level: int) -> None:

Comment thread qualtran/protos/bloq_pb2.pyi
@mhucka

mhucka commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

@micpap25 Thank you for your patience with this. I think we have a possible path forward; I'm just waiting for confirmation from the others, which I hope we'll have in 24 hrs.

mhucka added 2 commits June 12, 2026 18:39
To make the code cleaner and avoid having to wrap type annotations in
string quotes like `'Writable'``, we can add `from __future__ import
annotations` to the top of the files that use `Writable`. By putting
that as the first instruction in the files, Python postpones evaluation
of all type annotations at runtime. This allows us to write unquoted
type hints.
@mhucka

mhucka commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Update: we'll do a separate PR to run the proto building script after this one is merged.

mhucka added 3 commits June 13, 2026 03:56
Parameterizing the built-in set with a string (e.g. `set['BloqCountT']`)
evaluates to a `types.GenericAlias(set, 'BloqCountT')` which contains
the literal string, rather than wrapping it with a `ForwardRef` object
like `typing.Set` does.
There is a separate script for checking dev_tools.
@mhucka

mhucka commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

@micpap25 I hope you don't mind; I went ahead and pushed changes directly to your branch with the change to Set as well as with the latest changes from the main branch from the upstream Qualtran repo.

If you are satisfied with the changes, I can merge the PR.

@micpap25

Copy link
Copy Markdown
Contributor Author

Yep, thank you for finishing it off!

@mhucka mhucka merged commit d7550a4 into quantumlib:main Jun 15, 2026
21 of 22 checks passed
@mhucka

mhucka commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Update: PR #1886 is a follow-up to the comment above about doing a separate PR to run the build-protos.sh script.

mhucka added a commit that referenced this pull request Jun 22, 2026
This is a follow-up to PR #1851. This PR consists solely of the results
of running `dev_tools/build-protos.sh`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants