Skip to content

Commit f4c2a22

Browse files
authored
Merge branch 'main' into patch-1
2 parents 3fbf466 + 857d6b5 commit f4c2a22

163 files changed

Lines changed: 6367 additions & 193 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gemini/config.yaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Summary: configure Gemini Code Assist (https://codeassist.google/).
16+
# See https://github.com/marketplace/gemini-code-assist for more info.
17+
18+
have_fun: false
19+
code_review:
20+
disable: false
21+
comment_severity_threshold: HIGH
22+
max_review_comments: -1
23+
pull_request_opened:
24+
help: false
25+
summary: false
26+
code_review: true
27+
include_drafts: false
28+
ignore_patterns: []

check/format-incremental

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,13 @@ if (( ${#format_files[@]} == 0 )); then
9595
exit 0
9696
fi
9797

98-
flynt_args=("--quiet" "-f")
99-
if (( only_print == 1 )); then
100-
flynt_args+=("--dry-run")
101-
fi
102-
103-
flynt "${format_files[@]}" "${flynt_args[@]}"
104-
FLYNTSTATUS=$?
98+
#flynt_args=("--quiet" "-f")
99+
#if (( only_print == 1 )); then
100+
# flynt_args+=("--dry-run")
101+
#fi
102+
#
103+
#flynt "${format_files[@]}" "${flynt_args[@]}"
104+
FLYNTSTATUS=0
105105

106106
isort_args=()
107107
if (( only_print == 1 )); then

dev_tools/dump-bloq-manifest.py

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""
16+
Script to dump a manifest of all bloq classes and bloq examples.
17+
18+
This script finds all Bloq classes and examples in the library, serializes the examples
19+
to their objectstring representation, and writes the list of class names and
20+
example objectstrings to `qualtran/bloqs/manifest.py`.
21+
22+
See `qualtran.l1.load_objectstring()` to load bloq objects from these strings.
23+
"""
24+
25+
from functools import cached_property
26+
from typing import List, Tuple
27+
28+
from attrs import frozen
29+
from qualtran_dev_tools.bloq_finder import get_bloq_classes, get_bloq_examples
30+
from qualtran_dev_tools.git_tools import get_git_root
31+
32+
from qualtran import Bloq
33+
from qualtran.l1 import eval_cvalue_node, parse_objectstring, to_cobject_node
34+
from qualtran.l1.nodes import CArgNode, CObjectNode, LiteralNode
35+
36+
MAXLEN = 300
37+
"""If the objectstring is too long, we make the executive decision to truncate it."""
38+
39+
COPYRIGHT_NOTICE = """# Copyright 2026 Google LLC
40+
#
41+
# Licensed under the Apache License, Version 2.0 (the "License");
42+
# you may not use this file except in compliance with the License.
43+
# You may obtain a copy of the License at
44+
#
45+
# https://www.apache.org/licenses/LICENSE-2.0
46+
#
47+
# Unless required by applicable law or agreed to in writing, software
48+
# distributed under the License is distributed on an "AS IS" BASIS,
49+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
50+
# See the License for the specific language governing permissions and
51+
# limitations under the License."""
52+
53+
54+
@frozen
55+
class BloqExampleListItem:
56+
"""Formatting a bloq example and its serialized form.
57+
58+
Attributes:
59+
bloq: The bloq instance from the example.
60+
bloq_example_name: The name of the bloq example.
61+
cobject_node: The CObjectNode representing the serialized bloq.
62+
"""
63+
64+
bloq: Bloq
65+
bloq_example_name: str
66+
cobject_node: CObjectNode
67+
68+
@cached_property
69+
def objectstring(self) -> str:
70+
"""Returns the canonical string representation of the CObjectNode."""
71+
return self.cobject_node.canonical_str()
72+
73+
def maybe_commented_out(self, be_column_width: int = 30) -> Tuple[str, str, str]:
74+
"""Generates a string representation for the manifest, potentially commented out.
75+
76+
This method checks if the object string is too long, unparsable, unloadable, or
77+
if the re-loaded bloq is unequal to the original. If any of these conditions are met,
78+
it returns a commented-out string with a reason. Otherwise, it returns the
79+
executable string representation.
80+
81+
Args:
82+
be_column_width: The width of the column for the bloq example name for nicer formatting.
83+
84+
Returns:
85+
manifest_entry_str: The string to be written to the manifest (possibly commented out).
86+
reason: A reason string if it was commented out (empty otherwise).
87+
reason_details: Detailed error message if applicable (empty otherwise).
88+
"""
89+
quoted_be = f"'{self.bloq_example_name}',"
90+
be = f'{quoted_be:{be_column_width}}'
91+
be2 = f'{quoted_be:{be_column_width+2}}'
92+
93+
if len(self.objectstring) > MAXLEN:
94+
trunc = repr(self.objectstring)[:120] + '...'
95+
return f'# ({be}{trunc}', 'too long', ''
96+
97+
try:
98+
node = parse_objectstring(self.objectstring)
99+
except Exception as e: # pylint: disable=broad-except
100+
return f'# ({be}{self.objectstring!r}),', 'unparsable', str(e)
101+
102+
try:
103+
bloq = eval_cvalue_node(node, safe=False)
104+
except Exception as e: # pylint: disable=broad-except
105+
return f'# ({be}{self.objectstring!r}),', 'unloadable', str(e)
106+
107+
if bloq != self.bloq:
108+
return f'# ({be}{self.objectstring!r}),', 'unequal', ''
109+
110+
return f'({be2}{self.objectstring!r}),', '', ''
111+
112+
113+
def main():
114+
"""Main entry point for the script.
115+
116+
Finds all bloq classes and examples, processes them, and writes the
117+
`BLOQ_CLASS_NAMES` and `BLOQ_EXAMPLE_OBJECTSTRINGS` lists to
118+
`qualtran/bloqs/manifest.py`.
119+
"""
120+
bcs = get_bloq_classes()
121+
names = sorted(bc._class_name_in_pkg_() for bc in bcs)
122+
123+
bes = get_bloq_examples()
124+
items: List[BloqExampleListItem] = []
125+
for be in bes:
126+
bloq = be.make()
127+
try:
128+
cobject_node = to_cobject_node(bloq)
129+
assert isinstance(cobject_node, CObjectNode)
130+
except Exception as e: # pylint: disable=broad-except
131+
cobject_node = CObjectNode(
132+
name=bloq._class_name_in_pkg_(), cargs=[CArgNode(None, LiteralNode(str(e)))]
133+
)
134+
items.append(
135+
BloqExampleListItem(bloq=bloq, bloq_example_name=be.name, cobject_node=cobject_node)
136+
)
137+
138+
items = sorted(items, key=lambda x: x.objectstring)
139+
include_commented_out = True
140+
be_objectstrings = []
141+
for item in items:
142+
serstr, reason, details = item.maybe_commented_out()
143+
144+
if (not reason) or include_commented_out:
145+
be_objectstrings.append(serstr)
146+
147+
if reason:
148+
reason = f'({reason})'
149+
print(f"Skipping {reason:20s} {serstr}")
150+
151+
if details:
152+
print(f' {"":20s} ->', details)
153+
154+
reporoot = get_git_root()
155+
with (reporoot / 'qualtran/bloqs/manifest.py').open('w') as f:
156+
f.write(COPYRIGHT_NOTICE)
157+
f.write('\n\n')
158+
f.write('# This file is autogenerated\n')
159+
f.write('# See dev_tools/dump-bloq-manifest.py\n')
160+
f.write('# fmt: off\n\n')
161+
f.write('BLOQ_CLASS_NAMES = [\n')
162+
f.write('\n'.join([f' "{name}",' for name in names]))
163+
f.write('\n]\n')
164+
165+
f.write('\n')
166+
167+
f.write('BLOQ_EXAMPLE_OBJECTSTRINGS = [\n')
168+
f.write('\n'.join([f' {objstr}' for objstr in be_objectstrings]))
169+
f.write('\n]\n')
170+
171+
172+
if __name__ == '__main__':
173+
main()

dev_tools/qualtran_dev_tools/all_call_graph.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414

1515
"""Generate the library-wide call graph from all bloq examples."""
16+
1617
import logging
1718
import warnings
1819
from typing import Iterable

dev_tools/qualtran_dev_tools/make_reference_docs/_components/render_docstring.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ def _write_yields(f, part: DocstringSectionYields, level: int):
167167
f.write('\n')
168168

169169
else:
170-
subpart: DocstringYield
170+
param: DocstringYield
171171
for param in part.value:
172172
pname = param.name if param.name else 'yld'
173173
f.write(f'{pname}\n')

dev_tools/qualtran_dev_tools/make_reference_docs/_make.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14+
15+
# ruff: noqa: E402
1416
import ast
1517
import warnings
1618
from collections import defaultdict
@@ -76,7 +78,12 @@
7678
]
7779
MINIMAL = True
7880

79-
DEFINED_IN_CONTAINER_EXCEPTIONS = ['qualtran.dtype', 'qualtran.exception', 'qualtran.cirq_interop']
81+
DEFINED_IN_CONTAINER_EXCEPTIONS = [
82+
'qualtran.dtype',
83+
'qualtran.exception',
84+
'qualtran.cirq_interop',
85+
'qualtran.l1.nodes',
86+
]
8087

8188

8289
def _get_all_aliases(obj: Union[griffe.Object, griffe.Alias]) -> Set[str]:

dev_tools/qualtran_dev_tools/notebook_execution.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ def __call__(self, nb_rel_path: Path, sourceroot: Path) -> _NotebookRunResult:
215215
start = time.time()
216216
err = execute_and_export_notebook(paths)
217217
end = time.time()
218-
print(f"Exported {nb_rel_path} in {end-start:.2f} seconds.")
218+
print(f"Exported {nb_rel_path} in {end - start:.2f} seconds.")
219219
return _NotebookRunResult(paths.nb_in, err, duration_s=end - start)
220220

221221

dev_tools/qualtran_dev_tools/shell_tools.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,9 @@ def run(
9191
if abbreviate_non_option_arguments:
9292
cmd_desc = abbreviate_command_arguments_after_switches(cmd_desc)
9393
print("run:", cmd_desc, file=sys.stderr)
94-
return subprocess.run(args, **subprocess_run_kwargs) # pylint: disable=subprocess-run-check
94+
return subprocess.run( # pylint: disable=subprocess-run-check # noqa: PLW1510
95+
args, **subprocess_run_kwargs
96+
)
9597

9698

9799
def output_of(args: Union[str, List[str]], **kwargs) -> str:

docs/bloq_infra.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,5 @@ types (``Register``), and algorithms (``CompositeBloq``).
5555
drawing/musical_score.ipynb
5656
drawing/drawing_call_graph.ipynb
5757
simulation/xcheck_classical_quimb.ipynb
58+
l1/L1-Objectstring.ipynb
5859
Autodoc.ipynb

pyproject.toml

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ typing = [
9393
]
9494

9595
lint = [
96-
"pylint~=3.3.1",
96+
"pylint~=3.3.1",
97+
"ruff~=0.15.0",
9798

9899
# for checking _test.py files
99100
"pytest",
@@ -111,6 +112,7 @@ format = [
111112
"flynt~=0.60",
112113
"black~=24.8.0",
113114
"isort~=5.10.1",
115+
"ruff~=0.15.0",
114116
]
115117

116118
doc = [
@@ -131,6 +133,72 @@ skip-string-normalization = true
131133
skip-magic-trailing-comma = true
132134
exclude = "qualtran/protos/*"
133135

136+
[tool.ruff]
137+
line-length = 100
138+
target-version = "py311"
139+
exclude = [
140+
"qualtran/protos/*",
141+
"*_pb2.py",
142+
"*.ipynb",
143+
]
144+
145+
[tool.ruff.lint]
146+
select = [
147+
"E", # pycodestyle
148+
"F", # pyflakes
149+
# "I", # isort (disabled until we switch formatters)
150+
"W", # pycodestyle warnings
151+
"PL", # pylint
152+
]
153+
ignore = [
154+
# From the default ruleset:
155+
"E741", # ambiguous variable name 'l', 'O', or 'I'
156+
"E743", # ambiguous function definition
157+
"E731", # assigning a lambda expression to a variable
158+
159+
# Handled by the formatter
160+
"E501", # line too long (let ruff format handle this)
161+
"W291", # trailing whitespace
162+
"W293", # blank line contains whitespace
163+
164+
# We productively use these
165+
"PLC0415", # import outside top-level
166+
"PLW2901", # loop variable overwritten
167+
"PLC0206", # Extracting value from dictionary without calling .items()
168+
"PLW0406", # Module import itself
169+
170+
# Pylint 'refactor' rules
171+
"PLR0913", # Too many arguments
172+
"PLR0912", # Too many branches
173+
"PLR0915", # Too many statements
174+
"PLR0914", # Too many local variables
175+
"PLR2004", # Magic value used in comparison
176+
"PLR0911", # Too many return statements
177+
"PLR1704", # Redefining argument with the local name
178+
"PLR1714", # Consider merging multiple comparisons
179+
"PLR1730", # replace if with min, max. Can be enabled.
180+
181+
# Might be enabled at some point
182+
"PLR0402" # Prevalent in the rotation_synthesis submodule.
183+
]
184+
185+
[tool.ruff.lint.per-file-ignores]
186+
"__init__.py" = [
187+
# Ruff wants us to redundantly re-export symbols in __init__.py files, but the
188+
# automated fix isn't in the stable release yet.
189+
"F401", # Unused import
190+
]
191+
192+
193+
[tool.ruff.lint.isort]
194+
order-by-type = false
195+
force-to-top = []
196+
split-on-trailing-comma = false
197+
198+
[tool.ruff.format]
199+
quote-style = "preserve"
200+
skip-magic-trailing-comma = true
201+
134202
[tool.isort]
135203
profile = 'black'
136204
order_by_type = false

0 commit comments

Comments
 (0)