From ee407e4f23fcea3e6c8edc508d8cfb330ad032c6 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Wed, 7 Feb 2024 17:18:37 -0500 Subject: [PATCH 1/8] apply ruff rules --- .pre-commit-config.yaml | 2 ++ pyproject.toml | 30 ++++++++++++++++++++++++++++++ tests/__init__.py | 3 +++ tests/context.py | 3 --- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ac10f01..f921780 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,6 +16,8 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.2.0 hooks: + - id: ruff + args: [ --fix ] - id: ruff-format # numpydoc - repo: https://github.com/Carreau/velin diff --git a/pyproject.toml b/pyproject.toml index 8c55bd1..4f0b795 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,3 +32,33 @@ include = ["dargs*"] [tool.setuptools_scm] write_to = "dargs/_version.py" + +[tool.ruff.lint] +select = [ + "E", # errors + "F", # pyflakes + "D", # pydocstyle + "UP", # pyupgrade + "C4", # flake8-comprehensions + "RUF", # ruff + "I", # isort +] + +ignore = [ + "E501", # line too long + "F841", # local variable is assigned to but never used + "E741", # ambiguous variable name + "E402", # module level import not at top of file + "D100", # TODO: missing docstring in public module + "D101", # TODO: missing docstring in public class + "D102", # TODO: missing docstring in public method + "D103", # TODO: missing docstring in public function + "D104", # TODO: missing docstring in public package + "D105", # TODO: missing docstring in magic method + "D401", # TODO: first line should be in imperative mood + "D404", # TODO: first word of the docstring should not be This +] +ignore-init-module-imports = true + +[tool.ruff.lint.pydocstyle] +convention = "numpy" diff --git a/tests/__init__.py b/tests/__init__.py index e69de29..06e23c9 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -0,0 +1,3 @@ +import sys, os + +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) diff --git a/tests/context.py b/tests/context.py index 2f99e4c..be82834 100644 --- a/tests/context.py +++ b/tests/context.py @@ -1,4 +1 @@ -import sys, os - -sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) import dargs From b772e94b054292a918346cbe162cc78f3234da71 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 7 Feb 2024 22:19:01 +0000 Subject: [PATCH 2/8] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dargs/__init__.py | 2 +- dargs/dargs.py | 2 +- docs/conf.py | 1 - tests/__init__.py | 3 ++- tests/context.py | 1 - tests/dpmdargs.py | 9 ++++----- tests/test_checker.py | 4 ++-- tests/test_creation.py | 2 +- tests/test_docgen.py | 7 +++---- tests/test_normalizer.py | 5 +++-- 10 files changed, 17 insertions(+), 19 deletions(-) diff --git a/dargs/__init__.py b/dargs/__init__.py index bc51216..01e78f3 100644 --- a/dargs/__init__.py +++ b/dargs/__init__.py @@ -1,3 +1,3 @@ -from .dargs import Argument, Variant, ArgumentEncoder +from .dargs import Argument, ArgumentEncoder, Variant __all__ = ["Argument", "Variant", "ArgumentEncoder"] diff --git a/dargs/dargs.py b/dargs/dargs.py index e98c7a9..cc89df4 100644 --- a/dargs/dargs.py +++ b/dargs/dargs.py @@ -611,7 +611,7 @@ def gen_doc_head(self, path: Optional[List[str]] = None, **kwargs) -> str: if self.optional: typesig += ", optional" if self.default == "": - typesig += f", default: (empty string)" + typesig += ", default: (empty string)" elif self.default is not _Flags.NONE: typesig += f", default: ``{self.default}``" if self.alias: diff --git a/docs/conf.py b/docs/conf.py index 4bebdaa..4c106fc 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Configuration file for the Sphinx documentation builder. # diff --git a/tests/__init__.py b/tests/__init__.py index 06e23c9..aa17b14 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,3 +1,4 @@ -import sys, os +import os +import sys sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) diff --git a/tests/context.py b/tests/context.py index be82834..e69de29 100644 --- a/tests/context.py +++ b/tests/context.py @@ -1 +0,0 @@ -import dargs diff --git a/tests/dpmdargs.py b/tests/dpmdargs.py index 3d68d27..7d41537 100644 --- a/tests/dpmdargs.py +++ b/tests/dpmdargs.py @@ -1,5 +1,4 @@ -from .context import dargs -from dargs import dargs, Argument, Variant +from dargs import Argument, Variant, dargs ACTIVATION_FN_DICT = { "relu": None, @@ -202,7 +201,7 @@ def descrpt_se_ar_args(): def descrpt_hybrid_args(): - doc_list = f"A list of descriptor definitions" + doc_list = "A list of descriptor definitions" return [ Argument( @@ -243,7 +242,7 @@ def descrpt_variant_type_args(): link_se_a_3be = make_link("se_a_3be", "model/descriptor[se_a_3be]") link_se_a_tpe = make_link("se_a_tpe", "model/descriptor[se_a_tpe]") link_hybrid = make_link("hybrid", "model/descriptor[hybrid]") - doc_descrpt_type = f"The type of the descritpor. See explanation below. \n\n\ + doc_descrpt_type = "The type of the descritpor. See explanation below. \n\n\ - `loc_frame`: Defines a local frame at each atom, and the compute the descriptor as local coordinates under this frame.\n\n\ - `se_a`: Used by the smooth edition of Deep Potential. The full relative coordinates are used to construct the descriptor.\n\n\ - `se_r`: Used by the smooth edition of Deep Potential. Only the distance between atoms is used to construct the descriptor.\n\n\ @@ -391,7 +390,7 @@ def modifier_dipole_charge(): doc_model_name = "The name of the frozen dipole model file." doc_model_charge_map = f"The charge of the WFCC. The list length should be the same as the {make_link('sel_type', 'model/fitting_net[dipole]/sel_type')}. " doc_sys_charge_map = f"The charge of real atoms. The list length should be the same as the {make_link('type_map', 'model/type_map')}" - doc_ewald_h = f"The grid spacing of the FFT grid. Unit is A" + doc_ewald_h = "The grid spacing of the FFT grid. Unit is A" doc_ewald_beta = f"The splitting parameter of Ewald sum. Unit is A^{-1}" return [ diff --git a/tests/test_checker.py b/tests/test_checker.py index 62be7ec..f00fc16 100644 --- a/tests/test_checker.py +++ b/tests/test_checker.py @@ -1,6 +1,6 @@ -from typing import List -from .context import dargs import unittest +from typing import List + from dargs import Argument, Variant from dargs.dargs import ArgumentKeyError, ArgumentTypeError, ArgumentValueError diff --git a/tests/test_creation.py b/tests/test_creation.py index 0c32aad..a13569c 100644 --- a/tests/test_creation.py +++ b/tests/test_creation.py @@ -1,5 +1,5 @@ -from .context import dargs import unittest + from dargs import Argument, Variant diff --git a/tests/test_docgen.py b/tests/test_docgen.py index baf4132..9b543a6 100644 --- a/tests/test_docgen.py +++ b/tests/test_docgen.py @@ -1,8 +1,8 @@ -from .context import dargs -import unittest import json +import unittest from typing import List -from dargs import Argument, Variant, ArgumentEncoder + +from dargs import Argument, ArgumentEncoder, Variant class TestDocgen(unittest.TestCase): @@ -217,7 +217,6 @@ def test_multi_variants(self): # print("\n\n"+docstr) def test_dpmd(self): - from dargs import dargs from .dpmdargs import gen_doc dargs.RAW_ANCHOR = False diff --git a/tests/test_normalizer.py b/tests/test_normalizer.py index 3050db9..753f575 100644 --- a/tests/test_normalizer.py +++ b/tests/test_normalizer.py @@ -1,5 +1,5 @@ -from .context import dargs import unittest + from dargs import Argument, Variant @@ -186,7 +186,8 @@ def test_complicated(self): def test_dpmd(self): import json - from .dpmdargs import normalize, example_json_str + + from .dpmdargs import example_json_str, normalize data = json.loads(example_json_str) normalize(data) From 1ed70980eade8cf0bb319ee3cbfd2c9823f6e9de Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Wed, 7 Feb 2024 17:22:10 -0500 Subject: [PATCH 3/8] fix import --- tests/test_docgen.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_docgen.py b/tests/test_docgen.py index 9b543a6..98203ee 100644 --- a/tests/test_docgen.py +++ b/tests/test_docgen.py @@ -2,6 +2,7 @@ import unittest from typing import List +import dargs from dargs import Argument, ArgumentEncoder, Variant From b42db1c6a6343a6033a4d56f7ab2a9a8ee68891f Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Wed, 7 Feb 2024 17:30:42 -0500 Subject: [PATCH 4/8] fix several errors --- dargs/dargs.py | 26 +++++++++++++++----------- dargs/sphinx.py | 24 ++++++++++++------------ 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/dargs/dargs.py b/dargs/dargs.py index cc89df4..41ad255 100644 --- a/dargs/dargs.py +++ b/dargs/dargs.py @@ -40,7 +40,9 @@ HookArgKType = Callable[["Argument", dict, List[str]], None] HookArgVType = Callable[["Argument", Any, List[str]], None] HookVrntType = Callable[["Variant", dict, List[str]], None] -_DUMMYHOOK = lambda a, x, p: None # for doing nothing in traversing +def _DUMMYHOOK(a, x, p): + # for doing nothing in traversing + pass class _Flags(Enum): @@ -68,19 +70,19 @@ def __str__(self) -> str: class ArgumentKeyError(ArgumentError): - """Error class for missing or invalid argument keys""" + """Error class for missing or invalid argument keys.""" pass class ArgumentTypeError(ArgumentError): - """Error class for invalid argument data types""" + """Error class for invalid argument data types.""" pass class ArgumentValueError(ArgumentError): - """Error class for missing or invalid argument values""" + """Error class for missing or invalid argument values.""" pass @@ -169,8 +171,10 @@ def __init__( def __eq__(self, other: "Argument") -> bool: # do not compare doc and default # since they do not enter to the type checking - fkey = lambda f: f.name - vkey = lambda v: v.flag_name + def fkey(f): + return f.name + def vkey(v): + return v.flag_name return ( self.name == other.name and set(self.dtype) == set(other.dtype) @@ -204,7 +208,7 @@ def __getitem__(self, key: str) -> "Argument": return self[skey][rkey] @property - def I(self): + def I(self): # noqa:E743 # return a dummy argument that only has self as a sub field # can be used in indexing return Argument("_", dict, [self]) @@ -473,7 +477,7 @@ def normalize( do_alias: bool = True, trim_pattern: Optional[str] = None, ): - """Modify `argdict` so that it meets the Argument structure + """Modify `argdict` so that it meets the Argument structure. Normalization can add default values to optional args, substitute alias by its standard names, and discard unnecessary @@ -526,7 +530,7 @@ def normalize_value( do_alias: bool = True, trim_pattern: Optional[str] = None, ): - """Modify the value so that it meets the Argument structure + """Modify the value so that it meets the Argument structure. Same as `normalize({self.name: value})[self.name]`. @@ -760,7 +764,7 @@ def add_choice( *args, **kwargs, ) -> "Argument": - """Add a choice Argument to the current Variant""" + """Add a choice Argument to the current Variant.""" if isinstance(tag, Argument): newarg = tag else: @@ -835,7 +839,7 @@ def gen_doc( if kwargs.get("make_link"): if not kwargs.get("make_anchor"): raise ValueError("`make_link` only works with `make_anchor` set") - fnstr, target = make_ref_pair(path + [self.flag_name], fnstr, "flag") + fnstr, target = make_ref_pair([*path, self.flag_name], fnstr, "flag") body_list.append(target + "\n") for choice in self.choice_dict.values(): body_list.append("") diff --git a/dargs/sphinx.py b/dargs/sphinx.py index 5cc9e7f..e1f5bc3 100644 --- a/dargs/sphinx.py +++ b/dargs/sphinx.py @@ -20,7 +20,7 @@ where `_test_argument` returns an :class:`Argument `. A :class:`list` of :class:`Argument ` is also accepted. """ import sys -from typing import List +from typing import List, ClassVar from docutils.parsers.rst import Directive from docutils.parsers.rst.directives import unchanged @@ -34,10 +34,10 @@ class DargsDirective(Directive): - """dargs directive""" + """dargs directive.""" - has_content = True - option_spec = dict( + has_content: ClassVar[bool] = True + option_spec: ClassVar[dict] = dict( module=unchanged, func=unchanged, ) @@ -88,7 +88,7 @@ class DargsObject(ObjectDescription): This directive creates a signature node for an argument. """ - option_spec = dict( + option_spec: ClassVar[dict] = dict( path=unchanged, ) @@ -117,7 +117,7 @@ def add_target_and_index(self, name, sig, signode): self.indexnode["entries"].append( ( "pair", - "%s ; %s (%s) " % (name, path, self.objtype.title()), + f"{name}; {path} ({self.objtype.title()})", targetid, "main", None, @@ -133,19 +133,19 @@ class DargsDomain(Domain): - dargs::argument role """ - name = "dargs" - label = "dargs" - object_types = { + name: ClassVar[str] = "dargs" + label: ClassVar[str] = "dargs" + object_types: ClassVar[dict] = { "argument": ObjType("argument", "argument"), } - directives = { + directives: ClassVar[dict] = { "argument": DargsObject, } - roles = { + roles: ClassVar[dict] = { "argument": XRefRole(), } - initial_data = { + initial_data[dict] = { "arguments": {}, # fullname -> docname, objtype } From b69268ff0e059502cddd508e692e43acc220ede8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 7 Feb 2024 22:30:48 +0000 Subject: [PATCH 5/8] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dargs/dargs.py | 4 ++++ dargs/sphinx.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/dargs/dargs.py b/dargs/dargs.py index 41ad255..78267e1 100644 --- a/dargs/dargs.py +++ b/dargs/dargs.py @@ -40,6 +40,8 @@ HookArgKType = Callable[["Argument", dict, List[str]], None] HookArgVType = Callable[["Argument", Any, List[str]], None] HookVrntType = Callable[["Variant", dict, List[str]], None] + + def _DUMMYHOOK(a, x, p): # for doing nothing in traversing pass @@ -173,8 +175,10 @@ def __eq__(self, other: "Argument") -> bool: # since they do not enter to the type checking def fkey(f): return f.name + def vkey(v): return v.flag_name + return ( self.name == other.name and set(self.dtype) == set(other.dtype) diff --git a/dargs/sphinx.py b/dargs/sphinx.py index e1f5bc3..d901466 100644 --- a/dargs/sphinx.py +++ b/dargs/sphinx.py @@ -20,7 +20,7 @@ where `_test_argument` returns an :class:`Argument `. A :class:`list` of :class:`Argument ` is also accepted. """ import sys -from typing import List, ClassVar +from typing import ClassVar, List from docutils.parsers.rst import Directive from docutils.parsers.rst.directives import unchanged From ec394f8a5ee10d2ae2b7ae86aa3fa01154f1c028 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Wed, 7 Feb 2024 17:35:47 -0500 Subject: [PATCH 6/8] fix errors --- dargs/dargs.py | 9 ++++----- dargs/sphinx.py | 17 ++++++++--------- pyproject.toml | 1 + tests/dpmdargs.py | 3 ++- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/dargs/dargs.py b/dargs/dargs.py index 78267e1..d65f105 100644 --- a/dargs/dargs.py +++ b/dargs/dargs.py @@ -1,5 +1,4 @@ -r""" -Some (ocaml) pseudo-code here to show the intended type structure:: +r"""Some (ocaml) pseudo-code here to show the intended type structure. type args = {key: str; value: data; optional: bool; doc: str} list and data = @@ -235,7 +234,7 @@ def _reorg_dtype(self): if ( self.optional and self.default is not _Flags.NONE - and all([not isinstance_annotation(self.default, tt) for tt in self.dtype]) + and all(not isinstance_annotation(self.default, tt) for tt in self.dtype) ): self.dtype.add(type(self.default)) # and make it compatible with `isinstance` @@ -741,7 +740,7 @@ def set_default(self, default_tag: Union[bool, str]): self.default_tag = default_tag def extend_choices(self, choices: Optional[Iterable["Argument"]]): - """Add a list of choice Arguments to the current Variant""" + """Add a list of choice Arguments to the current Variant.""" # choices is a list of arguments # whose name is treated as the switch tag # we convert it into a dict for better reference @@ -994,7 +993,7 @@ def isinstance_annotation(value, dtype) -> bool: class ArgumentEncoder(json.JSONEncoder): - """Extended JSON Encoder to encode Argument object: + """Extended JSON Encoder to encode Argument object. Examples -------- diff --git a/dargs/sphinx.py b/dargs/sphinx.py index d901466..8678170 100644 --- a/dargs/sphinx.py +++ b/dargs/sphinx.py @@ -37,10 +37,10 @@ class DargsDirective(Directive): """dargs directive.""" has_content: ClassVar[bool] = True - option_spec: ClassVar[dict] = dict( - module=unchanged, - func=unchanged, - ) + option_spec: ClassVar[dict] = { + "module": unchanged, + "func": unchanged, + } def run(self): if "module" in self.options and "func" in self.options: @@ -59,10 +59,9 @@ def run(self): if not hasattr(mod, attr_name): raise self.error( ( - 'Module "%s" has no attribute "%s"\n' + f'Module "{module_name}" has no attribute "{attr_name}"\n' "Incorrect argparse :module: or :func: values?" ) - % (module_name, attr_name) ) func = getattr(mod, attr_name) arguments = func() @@ -78,7 +77,7 @@ def run(self): make_anchor=True, make_link=True, use_sphinx_domain=True ) rsts.extend(rst.split("\n")) - self.state_machine.insert_input(rsts, "%s:%s" % (module_name, attr_name)) + self.state_machine.insert_input(rsts, f"{module_name}:{attr_name}") return [] @@ -145,13 +144,13 @@ class DargsDomain(Domain): "argument": XRefRole(), } - initial_data[dict] = { + initial_data: ClassVar[dict] = { "arguments": {}, # fullname -> docname, objtype } def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode): """Resolve cross-references.""" - targetid = "%s:%s" % (typ, target) + targetid = f"{typ}:{target}" obj = self.data["arguments"].get(targetid) if obj is None: return None diff --git a/pyproject.toml b/pyproject.toml index 4f0b795..ab89bf1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,6 +55,7 @@ ignore = [ "D103", # TODO: missing docstring in public function "D104", # TODO: missing docstring in public package "D105", # TODO: missing docstring in magic method + "D205", # 1 blank line required between summary line and description "D401", # TODO: first line should be in imperative mood "D404", # TODO: first word of the docstring should not be This ] diff --git a/tests/dpmdargs.py b/tests/dpmdargs.py index 7d41537..9a5b1db 100644 --- a/tests/dpmdargs.py +++ b/tests/dpmdargs.py @@ -139,7 +139,8 @@ def descrpt_se_a_tpe_args(): doc_type_nlayer = "number of hidden layers of type embedding net" doc_numb_aparam = "dimension of atomic parameter. if set to a value > 0, the atomic parameters are embedded." - return descrpt_se_a_args() + [ + return [ + *descrpt_se_a_args(), Argument("type_nchanl", int, optional=True, default=4, doc=doc_type_nchanl), Argument("type_nlayer", int, optional=True, default=2, doc=doc_type_nlayer), Argument("numb_aparam", int, optional=True, default=0, doc=doc_numb_aparam), From a1491c4ff7bc848f86584e35d37751f658fd5fab Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 7 Feb 2024 22:36:11 +0000 Subject: [PATCH 7/8] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dargs/sphinx.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/dargs/sphinx.py b/dargs/sphinx.py index 8678170..735f0f5 100644 --- a/dargs/sphinx.py +++ b/dargs/sphinx.py @@ -58,10 +58,8 @@ def run(self): if not hasattr(mod, attr_name): raise self.error( - ( - f'Module "{module_name}" has no attribute "{attr_name}"\n' - "Incorrect argparse :module: or :func: values?" - ) + f'Module "{module_name}" has no attribute "{attr_name}"\n' + "Incorrect argparse :module: or :func: values?" ) func = getattr(mod, attr_name) arguments = func() From e22dfddecc949c6e1edeb0708542f5f2233608e2 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Wed, 7 Feb 2024 17:37:43 -0500 Subject: [PATCH 8/8] fix errors --- dargs/sphinx.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/dargs/sphinx.py b/dargs/sphinx.py index 735f0f5..2c7aa82 100644 --- a/dargs/sphinx.py +++ b/dargs/sphinx.py @@ -85,9 +85,9 @@ class DargsObject(ObjectDescription): This directive creates a signature node for an argument. """ - option_spec: ClassVar[dict] = dict( - path=unchanged, - ) + option_spec: ClassVar[dict] = { + "path": unchanged, + } def handle_signature(self, sig, signode): signode += addnodes.desc_name(sig, sig) @@ -95,7 +95,7 @@ def handle_signature(self, sig, signode): def add_target_and_index(self, name, sig, signode): path = self.options["path"] - targetid = "%s:%s" % (self.objtype, path) + targetid = f"{self.objtype}:{path}" if targetid not in self.state.document.ids: signode["names"].append(targetid) signode["ids"].append(targetid) @@ -105,8 +105,7 @@ def add_target_and_index(self, name, sig, signode): inv = self.env.domaindata["dargs"]["arguments"] if targetid in inv: self.state.document.reporter.warning( - 'Duplicated argument "%s" described in "%s".' - % (targetid, self.env.doc2path(inv[targetid][0])), + f'Duplicated argument "{targetid}" described in "{self.env.doc2path(inv[targetid][0])}".', line=self.lineno, ) inv[targetid] = (self.env.docname, self.objtype)