From 2cdf8c61cfbb5c0cfac9952c9682f54f89c78d0d Mon Sep 17 00:00:00 2001 From: Toon Verstraelen Date: Wed, 22 May 2024 10:56:57 +0200 Subject: [PATCH] Enable flake8-bugbear linting --- iodata/docstrings.py | 32 +++++++++---- iodata/formats/gamess.py | 2 +- iodata/formats/gaussianlog.py | 2 +- iodata/formats/json.py | 37 ++++++++------ iodata/formats/wfx.py | 4 +- iodata/test/test_orbitals.py | 90 +++++++++++++++++------------------ iodata/utils.py | 2 +- pyproject.toml | 2 +- 8 files changed, 97 insertions(+), 74 deletions(-) diff --git a/iodata/docstrings.py b/iodata/docstrings.py index fd6505b6..95f6366b 100644 --- a/iodata/docstrings.py +++ b/iodata/docstrings.py @@ -33,9 +33,11 @@ def _document_load( fmt: str, guaranteed: list[str], ifpresent: list[str] = None, - kwdocs: dict[str, str] = {}, + kwdocs: dict[str, str] = None, notes: str = None, ): + if kwdocs is None: + kwdocs = {} ifpresent = ifpresent or [] def decorator(func): @@ -91,7 +93,7 @@ def document_load_one( fmt: str, guaranteed: list[str], ifpresent: list[str] = None, - kwdocs: dict[str, str] = {}, + kwdocs: dict[str, str] = None, notes: str = None, ): """Decorate a load_one function to generate a docstring. @@ -117,6 +119,8 @@ def document_load_one( A decorator function. """ + if kwdocs is None: + kwdocs = {} return _document_load(LOAD_ONE_DOC_TEMPLATE, fmt, guaranteed, ifpresent, kwdocs, notes) @@ -146,7 +150,7 @@ def document_load_many( fmt: str, guaranteed: list[str], ifpresent: list[str] = None, - kwdocs: dict[str, str] = {}, + kwdocs: dict[str, str] = None, notes: str = None, ): """Decorate a load_many function to generate a docstring. @@ -172,6 +176,8 @@ def document_load_many( A decorator function. """ + if kwdocs is None: + kwdocs = {} return _document_load(LOAD_MANY_DOC_TEMPLATE, fmt, guaranteed, ifpresent, kwdocs, notes) @@ -180,9 +186,11 @@ def _document_dump( fmt: str, required: list[str], optional: list[str] = None, - kwdocs: dict[str, str] = {}, + kwdocs: dict[str, str] = None, notes: str = None, ): + if kwdocs is None: + kwdocs = {} optional = optional or [] def decorator(func): @@ -236,7 +244,7 @@ def document_dump_one( fmt: str, required: list[str], optional: list[str] = None, - kwdocs: dict[str, str] = {}, + kwdocs: dict[str, str] = None, notes: str = None, ): """Decorate a dump_one function to generate a docstring. @@ -262,6 +270,8 @@ def document_dump_one( A decorator function. """ + if kwdocs is None: + kwdocs = {} return _document_dump(DUMP_ONE_DOC_TEMPLATE, fmt, required, optional, kwdocs, notes) @@ -288,7 +298,7 @@ def document_dump_many( fmt: str, required: list[str], optional: list[str] = None, - kwdocs: dict[str, str] = {}, + kwdocs: dict[str, str] = None, notes: str = None, ): """Decorate a dump_many function to generate a docstring. @@ -314,6 +324,8 @@ def document_dump_many( A decorator function. """ + if kwdocs is None: + kwdocs = {} return _document_dump(DUMP_MANY_DOC_TEMPLATE, fmt, required, optional, kwdocs, notes) @@ -322,9 +334,11 @@ def _document_write( fmt: str, required: list[str], optional: list[str] = None, - kwdocs: dict[str, str] = {}, + kwdocs: dict[str, str] = None, notes: str = None, ): + if kwdocs is None: + kwdocs = {} optional = optional or [] def decorator(func): @@ -381,7 +395,7 @@ def document_write_input( fmt: str, required: list[str], optional: list[str] = None, - kwdocs: dict[str, str] = {}, + kwdocs: dict[str, str] = None, notes: str = None, ): """Decorate a write_input function to generate a docstring. @@ -407,4 +421,6 @@ def document_write_input( A decorator function. """ + if kwdocs is None: + kwdocs = {} return _document_write(WRITE_INPUT_DOC_TEMPLATE, fmt, required, optional, kwdocs, notes) diff --git a/iodata/formats/gamess.py b/iodata/formats/gamess.py index 038d9bdf..0428420d 100644 --- a/iodata/formats/gamess.py +++ b/iodata/formats/gamess.py @@ -48,7 +48,7 @@ def _read_data(lit: LineIterator) -> tuple: def _read_coordinates(lit: LineIterator, result: dict) -> tuple: """Extract ``numbers`` and ``coordinates`` from the punch file.""" - for i in range(2): + for _ in range(2): next(lit) natom = len(result["symbols"]) # if the data are already read before, just overwrite them diff --git a/iodata/formats/gaussianlog.py b/iodata/formats/gaussianlog.py index f147ccf7..b9341550 100644 --- a/iodata/formats/gaussianlog.py +++ b/iodata/formats/gaussianlog.py @@ -124,7 +124,7 @@ def _load_fourindex_g09(lit: LineIterator, nbasis: int) -> np.ndarray: """ result = np.zeros((nbasis, nbasis, nbasis, nbasis)) # Skip first six lines - for i in range(6): + for _i in range(6): next(lit) # Start reading elements until a line is encountered that does not start # with ' I=' diff --git a/iodata/formats/json.py b/iodata/formats/json.py index 7540b175..39837c8c 100644 --- a/iodata/formats/json.py +++ b/iodata/formats/json.py @@ -648,7 +648,7 @@ def _parse_json(json_in: dict, lit: LineIterator) -> dict: f"{lit.filename}: QCSchema files should have a `schema_name` key." "Attempting to determine schema type...", FileFormatWarning, - 2, + stacklevel=2, ) # Geometry is required in any molecule schema if "geometry" in result: @@ -673,7 +673,7 @@ def _parse_json(json_in: dict, lit: LineIterator) -> dict: f"{lit.filename}: QCSchema files should have a `schema_version` key." "Attempting to load without version number.", FileFormatWarning, - 2, + stacklevel=2, ) if schema_name == "qcschema_molecule": @@ -763,7 +763,7 @@ def _parse_topology_keys(mol: dict, lit: LineIterator) -> dict: warn( f"{lit.filename}: QCSchema files should have a '{key}' key.", FileFormatWarning, - 2, + stacklevel=2, ) for key in topology_keys: if key not in mol: @@ -789,7 +789,7 @@ def _parse_topology_keys(mol: dict, lit: LineIterator) -> dict: "Some QCSchema writers omit this key for default value 0.0," "Ensure this value is correct.", FileFormatWarning, - 2, + stacklevel=2, ) formal_charge = 0.0 else: @@ -804,7 +804,7 @@ def _parse_topology_keys(mol: dict, lit: LineIterator) -> dict: "Some QCSchema writers omit this key for default value 1," "Ensure this value is correct.", FileFormatWarning, - 2, + stacklevel=2, ) topology_dict["spinpol"] = 0 else: @@ -827,7 +827,7 @@ def _parse_topology_keys(mol: dict, lit: LineIterator) -> dict: "{}: Both `masses` and `mass_numbers` given. " "Both values will be written to `extra` dict.", FileFormatWarning, - 2, + stacklevel=2, ) extra_dict["mass_numbers"] = np.array(mol["mass_numbers"]) extra_dict["masses"] = np.array(mol["masses"]) @@ -940,7 +940,7 @@ def _version_check(result: dict, max_version: float, schema_name: str, lit: Line f"{lit.filename}: Unknown {schema_name} version {version}, " "loading may produce invalid results", FileFormatWarning, - 2, + stacklevel=2, ) return version @@ -1083,7 +1083,7 @@ def _parse_input_keys(result: dict, lit: LineIterator) -> dict: warn( f"{lit.filename}: QCSchema files should have a '{key}' key.", FileFormatWarning, - 2, + stacklevel=2, ) for key in input_keys: if key not in result: @@ -1215,14 +1215,17 @@ def _parse_model(model: dict, lit: LineIterator) -> dict: model_dict["lot"] = model["method"] # QCEngineRecords doesn't give an empty string for basis-free methods, omits req'd key instead if "basis" not in model: - warn(f"{lit.filename}: Model `basis` key should be given. Assuming basis-free method.") + warn( + f"{lit.filename}: Model `basis` key should be given. Assuming basis-free method.", + stacklevel=2, + ) elif isinstance(model["basis"], str): if model["basis"] == "": warn( f"{lit.filename}: QCSchema `basis` could not be read and will be omitted." "Unless model is for a basis-free method, check input file.", FileFormatWarning, - 2, + stacklevel=2, ) else: model_dict["obasis_name"] = model["basis"] @@ -1256,13 +1259,17 @@ def _parse_protocols(protocols: dict, lit: LineIterator) -> dict: warn( "{}: Protocols `wavefunction` key not specified, no properties will be kept.", FileFormatWarning, - 2, + stacklevel=2, ) wavefunction = "none" else: wavefunction = protocols["wavefunction"] if "stdout" not in protocols: - warn("{}: Protocols `stdout` key not specified, stdout will be kept.", FileFormatWarning, 2) + warn( + "{}: Protocols `stdout` key not specified, stdout will be kept.", + FileFormatWarning, + stacklevel=2, + ) keep_stdout = True else: keep_stdout = protocols["stdout"] @@ -1338,7 +1345,7 @@ def _parse_output_keys(result: dict, lit: LineIterator) -> dict: warn( f"{lit.filename}: QCSchema files should have a '{key}' key.", FileFormatWarning, - 2, + stacklevel=2, ) for key in output_keys: if key not in result: @@ -1494,7 +1501,7 @@ def _dump_qcschema_molecule(data: IOData) -> dict: "`charge` and `spinpol` should be given to write qcschema_molecule file:" "QCSchema defaults to charge = 0 and multiplicity = 1 if no values given.", FileFormatWarning, - 2, + stacklevel=2, ) if data.charge is not None: molecule_dict["molecular_charge"] = data.charge @@ -1691,7 +1698,7 @@ def _dump_qcschema_output(data: IOData) -> dict: "No basis name given. QCSchema assumes this signifies a basis-free method; to" "avoid this warning, specify `obasis_name` as an empty string.", FileFormatWarning, - 2, + stacklevel=2, ) if "basis" in data.extra["input"]["model"]: raise NotImplementedError("qcschema_basis is not yet supported in IOData.") diff --git a/iodata/formats/wfx.py b/iodata/formats/wfx.py index 790b254b..eab00ab3 100644 --- a/iodata/formats/wfx.py +++ b/iodata/formats/wfx.py @@ -142,7 +142,7 @@ def load_data_wfx(lit: LineIterator) -> dict: elif key in lbs_other: result[lbs_other[key]] = value else: - warnings.warn(f"Not recognized section label, skip {key}") + warnings.warn(f"Not recognized section label, skip {key}", stacklevel=2) # reshape some arrays result["atcoords"] = result["atcoords"].reshape(-1, 3) @@ -372,7 +372,7 @@ def dump_one(f: TextIO, data: IOData): for angmom, kind in zip(shell.angmoms, shell.kinds): n = len(data.obasis.conventions[angmom, kind]) c = raw_coeffs[index_mo_old : index_mo_old + n] - for j in range(shell.nprim): + for _j in range(shell.nprim): mo_coeffs[index_mo_new : index_mo_new + n] = c index_mo_new += n index_mo_old += n diff --git a/iodata/test/test_orbitals.py b/iodata/test/test_orbitals.py index fb2dc781..3fe5ce03 100644 --- a/iodata/test/test_orbitals.py +++ b/iodata/test/test_orbitals.py @@ -264,23 +264,23 @@ def test_generalized_empty(): assert mo.nbasis is None assert mo.norb is None with pytest.raises(NotImplementedError): - mo.spinpol + _ = mo.spinpol with pytest.raises(NotImplementedError): - mo.occsa + _ = mo.occsa with pytest.raises(NotImplementedError): - mo.occsb + _ = mo.occsb with pytest.raises(NotImplementedError): - mo.coeffsa + _ = mo.coeffsa with pytest.raises(NotImplementedError): - mo.coeffsb + _ = mo.coeffsb with pytest.raises(NotImplementedError): - mo.energiesa + _ = mo.energiesa with pytest.raises(NotImplementedError): - mo.energiesb + _ = mo.energiesb with pytest.raises(NotImplementedError): - mo.irrepsa + _ = mo.irrepsa with pytest.raises(NotImplementedError): - mo.irrepsb + _ = mo.irrepsb def test_generalized_occs(): @@ -291,23 +291,23 @@ def test_generalized_occs(): assert mo.nbasis is None assert mo.norb == 7 with pytest.raises(NotImplementedError): - mo.spinpol + _ = mo.spinpol with pytest.raises(NotImplementedError): - mo.occsa + _ = mo.occsa with pytest.raises(NotImplementedError): - mo.occsb + _ = mo.occsb with pytest.raises(NotImplementedError): - mo.coeffsa + _ = mo.coeffsa with pytest.raises(NotImplementedError): - mo.coeffsb + _ = mo.coeffsb with pytest.raises(NotImplementedError): - mo.energiesa + _ = mo.energiesa with pytest.raises(NotImplementedError): - mo.energiesb + _ = mo.energiesb with pytest.raises(NotImplementedError): - mo.irrepsa + _ = mo.irrepsa with pytest.raises(NotImplementedError): - mo.irrepsb + _ = mo.irrepsb def test_generalized_coeffs(): @@ -319,23 +319,23 @@ def test_generalized_coeffs(): assert mo.nbasis == 5 # 5 *spatial* basis functions! assert mo.norb == 7 with pytest.raises(NotImplementedError): - mo.spinpol + _ = mo.spinpol with pytest.raises(NotImplementedError): - mo.occsa + _ = mo.occsa with pytest.raises(NotImplementedError): - mo.occsb + _ = mo.occsb with pytest.raises(NotImplementedError): - mo.coeffsa + _ = mo.coeffsa with pytest.raises(NotImplementedError): - mo.coeffsb + _ = mo.coeffsb with pytest.raises(NotImplementedError): - mo.energiesa + _ = mo.energiesa with pytest.raises(NotImplementedError): - mo.energiesb + _ = mo.energiesb with pytest.raises(NotImplementedError): - mo.irrepsa + _ = mo.irrepsa with pytest.raises(NotImplementedError): - mo.irrepsb + _ = mo.irrepsb def test_generalized_energies(): @@ -347,23 +347,23 @@ def test_generalized_energies(): assert mo.nbasis is None assert mo.norb == 7 with pytest.raises(NotImplementedError): - mo.spinpol + _ = mo.spinpol with pytest.raises(NotImplementedError): - mo.occsa + _ = mo.occsa with pytest.raises(NotImplementedError): - mo.occsb + _ = mo.occsb with pytest.raises(NotImplementedError): - mo.coeffsa + _ = mo.coeffsa with pytest.raises(NotImplementedError): - mo.coeffsb + _ = mo.coeffsb with pytest.raises(NotImplementedError): - mo.energiesa + _ = mo.energiesa with pytest.raises(NotImplementedError): - mo.energiesb + _ = mo.energiesb with pytest.raises(NotImplementedError): - mo.irrepsa + _ = mo.irrepsa with pytest.raises(NotImplementedError): - mo.irrepsb + _ = mo.irrepsb def test_generalized_irreps(): @@ -375,20 +375,20 @@ def test_generalized_irreps(): assert mo.nbasis is None assert mo.norb == 7 with pytest.raises(NotImplementedError): - mo.spinpol + _ = mo.spinpol with pytest.raises(NotImplementedError): - mo.occsa + _ = mo.occsa with pytest.raises(NotImplementedError): - mo.occsb + _ = mo.occsb with pytest.raises(NotImplementedError): - mo.coeffsa + _ = mo.coeffsa with pytest.raises(NotImplementedError): - mo.coeffsb + _ = mo.coeffsb with pytest.raises(NotImplementedError): - mo.energiesa + _ = mo.energiesa with pytest.raises(NotImplementedError): - mo.energiesb + _ = mo.energiesb with pytest.raises(NotImplementedError): - mo.irrepsa + _ = mo.irrepsa with pytest.raises(NotImplementedError): - mo.irrepsb + _ = mo.irrepsb diff --git a/iodata/utils.py b/iodata/utils.py index 5e8cfe92..3d84330e 100644 --- a/iodata/utils.py +++ b/iodata/utils.py @@ -115,7 +115,7 @@ def warn(self, msg: str): Message to raise alongside filename and line number. """ - warnings.warn(f"{self.filename}:{self.lineno} {msg}", FileFormatWarning, 2) + warnings.warn(f"{self.filename}:{self.lineno} {msg}", FileFormatWarning, stacklevel=2) def back(self, line): """Go one line back and decrease the lineno attribute by one.""" diff --git a/pyproject.toml b/pyproject.toml index 9af33956..5891e324 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,4 +54,4 @@ line-length = 100 target-version = "py39" [tool.ruff.lint] -select = ["E", "F", "I", "UP"] +select = ["E", "F", "I", "UP", "B"]