Skip to content

Commit f17a33a

Browse files
authored
Merge branch 'main' into parallel-pytest
2 parents ce25da7 + a041f67 commit f17a33a

5 files changed

Lines changed: 270 additions & 11 deletions

File tree

.pre-commit-config.yaml

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
# Copyright 2026 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+
# http://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: config for setting up git hooks using the pre-commit framework. This
16+
# is optional and NOT set up by default nor used by the scripts in check/. Here
17+
# is a suggested installation approach; after doing this, the pre-commit hooks
18+
# will be called automatically by git at the appropriate times:
19+
#
20+
# pip install pre-commit
21+
# pre-commit install -t pre-commit -t commit-msg -t pre-push
22+
# pre-commit run
23+
24+
default_stages:
25+
- pre-commit
26+
27+
# Note: these are Python regular expressions matched with re.search.
28+
exclude: |
29+
(?x)^(
30+
.*\.egg-info/.* |
31+
.*\.h5 |
32+
.*\.ipynb_checkpoints(/.*)? |
33+
.*\.log |
34+
.*\.out |
35+
.*\.pytest_cache/.* |
36+
.*__pycache__/.* |
37+
.env/.* |
38+
.venv/.* |
39+
\.([^/]*cache/.*) |
40+
\.coverage(\..*)? |
41+
docs/_build/.* |
42+
venv/.*
43+
)$
44+
45+
fail_fast: true
46+
47+
minimum_pre_commit_version: '4.4.0'
48+
49+
repos:
50+
# ~~~~ Pre-commit hooks ~~~~
51+
52+
- repo: https://github.com/pre-commit/pre-commit-hooks
53+
rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # frozen: v6.0.0
54+
hooks:
55+
# Note: don't use check-yaml bc it doesn't read the yamllint config.
56+
# Use separate yamllint hook later in this file.
57+
58+
- id: no-commit-to-branch
59+
name: 'Check that the commit is not made to the main branch'
60+
args: [--branch, main, --branch, master]
61+
62+
- id: check-merge-conflict
63+
name: "Check that files are free of merge git conflict strings"
64+
65+
- id: check-illegal-windows-names
66+
name: "Check that file names can be used on Windows"
67+
68+
- id: check-case-conflict
69+
name: "Check that file names won't conflict on case-insensitive systems"
70+
71+
- id: name-tests-test
72+
name: 'Verify test files are named correctly'
73+
74+
- id: check-symlinks
75+
name: 'Check for symlinks that do not point to anything'
76+
77+
- id: destroyed-symlinks
78+
name: 'Check that symlinks are not turned into regular files'
79+
80+
- id: check-shebang-scripts-are-executable
81+
name: 'Check that shell script files are executable'
82+
83+
- id: debug-statements
84+
name: 'Check that Python files are free of debug statements'
85+
86+
- id: check-toml
87+
name: 'Check TOML files for valid syntax'
88+
89+
- id: check-xml
90+
name: 'Check XML files for valid syntax'
91+
92+
- repo: https://github.com/adrienverge/yamllint
93+
rev: cba56bcde1fdd01c1deb3f945e69764c291a6530 # frozen: v1.38.0
94+
hooks:
95+
- id: yamllint
96+
name: 'Run YAML linter'
97+
files: \.(yaml|yml|cff)$
98+
args: [--format=colored, --no-warnings]
99+
100+
- repo: https://github.com/python-jsonschema/check-jsonschema
101+
rev: 'ed81924a8b1cecdaa570b072528fa80c9c4d6ccd' # frozen: 0.37.1
102+
hooks:
103+
- id: check-jsonschema
104+
name: 'Check that Jupyter notebooks are valid JSON'
105+
types: [jupyter]
106+
files: '.*\.ipynb$'
107+
# Note: pre-commit will download & cache this file automatically.
108+
# yamllint disable rule:line-length
109+
args: [--schemafile, https://raw.githubusercontent.com/jupyter/nbformat/refs/heads/main/nbformat/v4/nbformat.v4.0.schema.json]
110+
111+
- repo: https://github.com/jumanjihouse/pre-commit-hooks
112+
rev: '38980559e3a605691d6579f96222c30778e5a69e' # frozen: 3.0.0
113+
hooks:
114+
- id: shellcheck
115+
name: 'Check shell scripts'
116+
files: '(\.sh$|^check/[^.]+$)'
117+
118+
- repo: https://github.com/hadolint/hadolint
119+
rev: v2.14.0
120+
hooks:
121+
- id: hadolint
122+
name: 'Check Docker files'
123+
files: (?i)dockerfile$
124+
args: [--failure-threshold, error]
125+
126+
# Note this is used for YAML files, despite that it's named "jsonschema".
127+
- repo: https://github.com/python-jsonschema/check-jsonschema
128+
rev: 'ed81924a8b1cecdaa570b072528fa80c9c4d6ccd' # frozen: 0.37.1
129+
hooks:
130+
- id: check-github-workflows
131+
name: 'Check GitHub workflow files'
132+
133+
# ~~~~ Commit message hooks ~~~~
134+
135+
- repo: https://github.com/crate-ci/typos
136+
rev: c96c46fae465ab9e3607401d9ce93d75e7998023 # frozen: v1
137+
hooks:
138+
- id: typos
139+
name: 'Check commit message for typos'
140+
stages: [commit-msg]
141+
# Important: add "args: []" to prevent typos from autofixing your files.
142+
# C.f. https://github.com/crate-ci/typos/blob/master/docs/pre-commit.md
143+
args: []
144+
145+
# ~~~~ Pre-push hooks ~~~~
146+
147+
- repo: local
148+
hooks:
149+
- id: format-incremental
150+
name: 'Run check/format-incremental'
151+
entry: check/format-incremental
152+
language: script
153+
pass_filenames: false
154+
files: \.(cc|h|cu|py)$
155+
stages: [pre-push]
156+
157+
- repo: https://github.com/Pierre-Sassoulas/copyright_notice_precommit
158+
rev: 'd9215b6b2a028d1614c92cf43a9fcff3b1dd889e' # frozen: 0.1.2
159+
hooks:
160+
- id: copyright-notice
161+
name: 'Check that files have a copyright notice'
162+
types: [python]
163+
stages: [pre-push]
164+
args: [--notice=dev_tools/apache-license-header.txt]
165+
166+
- repo: https://github.com/tcort/markdown-link-check
167+
rev: ffc61540dea52bad1c41cfeedcf26c53ad9447ba # frozen: v3.14.2
168+
hooks:
169+
- id: markdown-link-check
170+
name: 'Check Markdown file lint'
171+
types: [markdown]
172+
stages: [pre-push]
173+
174+
- repo: https://github.com/pre-commit/pygrep-hooks
175+
rev: 3a6eb0fadf60b3cccfd80bad9dbb6fae7e47b316 # frozen: v1.10.0
176+
hooks:
177+
- id: python-check-blanket-noqa
178+
name: 'Check that "# noqa" annotations include error codes'
179+
stages: [pre-push]
180+
181+
- id: python-check-blanket-type-ignore
182+
name: 'Check that "# type: ignore" comments include error codes'
183+
stages: [pre-push]
184+
185+
- id: python-check-mock-methods
186+
name: 'Check for common mistakes when using unittest.mock'
187+
stages: [pre-push]

CONTRIBUTING.md

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,15 @@ Hamiltonians.
4040

4141
### Main subdirectories
4242

43-
**check/**: contains scripts for testing
43+
* `check/`: contains scripts for testing
4444

45-
**docker/**: contains a Docker configuration
45+
* `docker/`: contains a Docker configuration
4646

47-
**docs/**: contains OpenFermion documentation
47+
* `docs/`: contains OpenFermion documentation
4848

49-
**src/**: contains the main code
49+
* `src/`: contains the main code
5050

51-
**dev_tools/**: contains programs and configuration files used during development
51+
* `dev_tools/`: contains programs and configuration files used during development
5252

5353
The legacy subdirectories `cloud_library/` and `rtd_docs/` should be ignored.
5454

@@ -180,14 +180,46 @@ ready, create a pull request from your branch to the main project repository.
180180

181181
where `YOUR_BRANCH_NAME` is the name of your new branch.
182182

183-
### `git` configuration
183+
### Git configuration
184184

185185
The following command will set up large refactoring revisions to be ignored by `git blame`:
186186

187187
```bash
188188
git config blame.ignoreRevsFile .git-blame-ignore-revs
189189
```
190190

191+
### Git hooks configuration (optional)
192+
193+
This project includes a `.pre-commit-config.yaml` file for [pre-commit](https://pre-commit.com), an
194+
open-source utility that configures git hook functions to run when triggered by git operations such
195+
as committing changes, pushing changes, or writing commit messages. These hooks perform various
196+
checks that can help you meet project conventions automatically, at the cost of introducing small
197+
delays in those git operations. If you want to use `pre-commit`, you can install and configure it
198+
like this:
199+
200+
```shell
201+
pip install pre-commit
202+
pre-commit install -t pre-commit -t pre-push -t commit-msg
203+
```
204+
205+
Next, run it once after installation to download the hook environments and verify your setup:
206+
207+
```shell
208+
pre-commit run --all-files
209+
```
210+
211+
After that, the hooks will run automatically when triggered by the corresponding git operations.
212+
213+
### Type annotation conventions
214+
215+
Code should have [type annotations](https://www.python.org/dev/peps/pep-0484/). We use
216+
[mypy](http://mypy-lang.org/) to check that type annotations are correct, and the following script
217+
to run it:
218+
219+
```shell
220+
check/mypy
221+
```
222+
191223
### Python setup
192224

193225
1. Create a Python virtual environment. To use Python's built-in `venv` package, run:
@@ -224,7 +256,8 @@ make Mypy run in parallel for a substantial speed increase.
224256
### Linting and formatting
225257
226258
Code should meet common style standards for Python and be free of error-prone constructs. We use
227-
[Pylint](https://www.pylint.org/) to check for code lint and [Black](https://github.com/psf/black) for formatting code.
259+
[Pylint](https://www.pylint.org/) to check for code lint and [Black](https://github.com/psf/black)
260+
for formatting code.
228261
229262
* To check that code is formatted properly after editing Python files:
230263
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License");
2+
# you may not use this file except in compliance with the License.
3+
# You may obtain a copy of the License at
4+
#
5+
# https://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS,
9+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
# See the License for the specific language governing permissions and
11+
# limitations under the License.

src/openfermion/contrib/representability/_multitensor.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def __iter__(self):
2323

2424

2525
class MultiTensor(object):
26-
def __init__(self, tensors, dual_basis=DualBasis()):
26+
def __init__(self, tensors, dual_basis=None):
2727
"""
2828
A collection of tensor objects with maps from name to tensor
2929
@@ -46,6 +46,8 @@ def __init__(self, tensors, dual_basis=DualBasis()):
4646
self.off_set_map = self.make_offset_dict(self.tensors)
4747

4848
# An iterable object that provides access to the dual basis elements
49+
if dual_basis is None:
50+
dual_basis = DualBasis()
4951
self.dual_basis = dual_basis
5052
self.vec_dim = sum([vec.size for vec in self.tensors])
5153

@@ -81,8 +83,7 @@ def add_dual_elements(self, dual_element):
8183
if not isinstance(dual_element, DualBasisElement):
8284
raise TypeError("dual_element variable needs to be a DualBasisElement type")
8385

84-
# we should extend TMap to add
85-
self.dual_basis.elements.extend(dual_element)
86+
self.dual_basis.elements.append(dual_element)
8687

8788
def synthesize_dual_basis(self):
8889
"""
@@ -93,7 +94,7 @@ def synthesize_dual_basis(self):
9394
9495
:returns: sparse matrix
9596
"""
96-
# go throught the dual basis list and synthesize each element
97+
# go through the dual basis list and synthesize each element
9798
dual_row_indices = []
9899
dual_col_indices = []
99100
dual_data_values = []

src/openfermion/contrib/representability/_multitensor_test.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,33 @@ def test_add_dualelement():
9494
mt.add_dual_elements(dbe)
9595
assert len(mt.dual_basis) == 1
9696

97+
dbe2 = DualBasisElement()
98+
dbe2.add_element('b', (0, 1, 2), 5)
99+
mt.add_dual_elements(dbe2)
100+
assert len(mt.dual_basis) == 2
101+
102+
A, bias, scalar = mt.synthesize_dual_basis()
103+
assert A.shape[0] == 2
104+
# Verify that the elements are correctly added as DualBasisElements
105+
# and not as their internal tuples (which would cause synthesis to fail).
106+
assert isinstance(mt.dual_basis[0], DualBasisElement)
107+
assert isinstance(mt.dual_basis[1], DualBasisElement)
108+
109+
110+
def test_multitensor_init_isolation():
111+
# Test that different MultiTensor instances don't share the same dual_basis.
112+
a = np.random.random((2, 2))
113+
at = Tensor(tensor=a, name='a')
114+
mt1 = MultiTensor([at])
115+
mt2 = MultiTensor([at])
116+
117+
dbe = DualBasisElement()
118+
dbe.add_element('a', (0, 0), 1.0)
119+
mt1.add_dual_elements(dbe)
120+
121+
assert len(mt1.dual_basis) == 1
122+
assert len(mt2.dual_basis) == 0
123+
97124

98125
def test_synthesis_element():
99126
a = np.random.random((5, 5))

0 commit comments

Comments
 (0)