From 6e7c704af5d3118091da85e48a3519752c1a21b6 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Thu, 16 May 2024 18:34:09 -0400 Subject: [PATCH 1/3] chore: improve type checking Signed-off-by: Jinzhe Zeng --- .github/workflows/type-check.yml | 17 +++ dargs/__init__.py | 2 + dargs/dargs.py | 196 ++++++++++++++++--------------- dargs/notebook.py | 12 +- dargs/py.typed | 0 dargs/sphinx.py | 19 +-- docs/conf.py | 2 + pyproject.toml | 12 ++ tests/__init__.py | 2 + tests/dpmdargs.py | 2 + tests/test_checker.py | 2 + tests/test_creation.py | 2 + tests/test_docgen.py | 2 + tests/test_normalizer.py | 2 + tests/test_notebook.py | 2 + 15 files changed, 167 insertions(+), 107 deletions(-) create mode 100644 .github/workflows/type-check.yml create mode 100644 dargs/py.typed diff --git a/.github/workflows/type-check.yml b/.github/workflows/type-check.yml new file mode 100644 index 0000000..61cb44d --- /dev/null +++ b/.github/workflows/type-check.yml @@ -0,0 +1,17 @@ +name: Python package + +on: + - push + - pull_request + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3.12 + - run: pip install uv + - run: uv run basedpyright --with .[typecheck] diff --git a/dargs/__init__.py b/dargs/__init__.py index 01e78f3..af2f59b 100644 --- a/dargs/__init__.py +++ b/dargs/__init__.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from .dargs import Argument, ArgumentEncoder, Variant __all__ = ["Argument", "Variant", "ArgumentEncoder"] diff --git a/dargs/dargs.py b/dargs/dargs.py index ad4875e..3c45363 100644 --- a/dargs/dargs.py +++ b/dargs/dargs.py @@ -16,6 +16,8 @@ We also need to pay special attention to flat the keys of its choices. """ +from __future__ import annotations + import difflib import fnmatch import json @@ -23,7 +25,7 @@ from copy import deepcopy from enum import Enum from textwrap import indent -from typing import Any, Callable, Dict, Iterable, List, Optional, Union +from typing import Any, Callable, Iterable, List try: from typing import get_origin @@ -54,9 +56,7 @@ class _Flags(Enum): class ArgumentError(Exception): """Base error class for invalid argument values in argchecking.""" - def __init__( - self, path: Union[None, str, List[str]] = None, message: Optional[str] = None - ): + def __init__(self, path: None | str | list[str] = None, message: str | None = None): super().__init__(message) if path is None: path = "" @@ -139,26 +139,25 @@ class Argument: def __init__( self, name: str, - dtype: Union[None, type, Iterable[type]], - sub_fields: Optional[Iterable["Argument"]] = None, - sub_variants: Optional[Iterable["Variant"]] = None, + dtype: None | type | Iterable[type | Any | None], + sub_fields: Iterable[Argument] | None = None, + sub_variants: Iterable[Variant] | None = None, repeat: bool = False, optional: bool = False, default: Any = _Flags.NONE, - alias: Optional[Iterable[str]] = None, - extra_check: Optional[Callable[[Any], bool]] = None, + alias: Iterable[str] | None = None, + extra_check: Callable[[Any], bool] | None = None, doc: str = "", fold_subdoc: bool = False, extra_check_errmsg: str = "", ): self.name = name - self.dtype = dtype - self.sub_fields: Dict[str, "Argument"] = {} - self.sub_variants: Dict[str, "Variant"] = {} + self.sub_fields: dict[str, Argument] = {} + self.sub_variants: dict[str, Variant] = {} self.repeat = repeat self.optional = optional self.default = default - self.alias = alias if alias is not None else [] + self.alias = tuple(alias) if alias is not None else [] self.extra_check = extra_check self.doc = doc self.fold_subdoc = fold_subdoc @@ -167,9 +166,12 @@ def __init__( self.extend_subfields(sub_fields) self.extend_subvariants(sub_variants) # handle the format of dtype, makeit a tuple - self._reorg_dtype() + self.dtype = self._reorg_dtype(dtype) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, Argument): + return NotImplemented - def __eq__(self, other: "Argument") -> bool: # do not compare doc and default # since they do not enter to the type checking def fkey(f): @@ -190,7 +192,7 @@ def vkey(v): def __repr__(self) -> str: return f"" - def __getitem__(self, key: str) -> "Argument": + def __getitem__(self, key: str) -> Argument: key = key.lstrip("/") if key in ("", "."): return self @@ -216,41 +218,43 @@ def I(self): # noqa:E743 # can be used in indexing return Argument("_", dict, [self]) - def _reorg_dtype(self): + def _reorg_dtype( + self, dtype: None | type | Any | Iterable[type | Any | None] + ) -> tuple[type | Any | None, ...]: if ( - isinstance(self.dtype, type) - or isinstance(get_origin(self.dtype), type) - or self.dtype is None + isinstance(dtype, type) + or isinstance(get_origin(dtype), type) + or dtype is None ): - self.dtype = [self.dtype] + dtype = [dtype] + assert dtype is not None # remove duplicate - self.dtype = { + dtype = { dt if type(dt) is type or type(get_origin(dt)) is type else type(dt) - for dt in self.dtype + for dt in dtype } # check conner cases if self.sub_fields or self.sub_variants: - self.dtype.add(list if self.repeat else dict) + dtype.add(list if self.repeat else dict) 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 dtype) ): - self.dtype.add(type(self.default)) + dtype.add(type(self.default)) # and make it compatible with `isinstance` - self.dtype = tuple(self.dtype) + return tuple(dtype) - def set_dtype(self, dtype: Union[None, type, Iterable[type]]): + def set_dtype(self, dtype: None | type | Iterable[type]): """Change the dtype of the current Argument.""" - self.dtype = dtype - self._reorg_dtype() + self.dtype = self._reorg_dtype(dtype) def set_repeat(self, repeat: bool = True): """Change the repeat attribute of the current Argument.""" self.repeat = repeat - self._reorg_dtype() + self.dtype = self._reorg_dtype(self.dtype) - def extend_subfields(self, sub_fields: Optional[Iterable["Argument"]]): + def extend_subfields(self, sub_fields: Iterable[Argument] | None): """Add a list of sub fields to the current Argument.""" if sub_fields is None: return @@ -260,9 +264,9 @@ def extend_subfields(self, sub_fields: Optional[Iterable["Argument"]]): ((s.name, s) for s in sub_fields), err_msg=f"building Argument `{self.name}`", ) - self._reorg_dtype() + self.dtype = self._reorg_dtype(self.dtype) - def add_subfield(self, name: Union[str, "Argument"], *args, **kwargs) -> "Argument": + def add_subfield(self, name: str | Argument, *args, **kwargs) -> Argument: """Add a sub field to the current Argument.""" if isinstance(name, Argument): newarg = name @@ -271,7 +275,7 @@ def add_subfield(self, name: Union[str, "Argument"], *args, **kwargs) -> "Argume self.extend_subfields([newarg]) return newarg - def extend_subvariants(self, sub_variants: Optional[Iterable["Variant"]]): + def extend_subvariants(self, sub_variants: Iterable[Variant] | None): """Add a list of sub variants to the current Argument.""" if sub_variants is None: return @@ -282,11 +286,9 @@ def extend_subvariants(self, sub_variants: Optional[Iterable["Variant"]]): exclude=self.sub_fields.keys(), err_msg=f"building Argument `{self.name}`", ) - self._reorg_dtype() + self.dtype = self._reorg_dtype(self.dtype) - def add_subvariant( - self, flag_name: Union[str, "Variant"], *args, **kwargs - ) -> "Variant": + def add_subvariant(self, flag_name: str | Variant, *args, **kwargs) -> Variant: """Add a sub variant to the current Argument.""" if isinstance(flag_name, Variant): newvrnt = flag_name @@ -298,7 +300,7 @@ def add_subvariant( # above are creation part # below are general traverse part - def flatten_sub(self, value: dict, path=None) -> Dict[str, "Argument"]: + def flatten_sub(self, value: dict, path=None) -> dict[str, Argument]: sub_dicts = [self.sub_fields] sub_dicts.extend( vrnt.flatten_sub(value, path) for vrnt in self.sub_variants.values() @@ -316,7 +318,7 @@ def traverse( value_hook: HookArgVType = _DUMMYHOOK, sub_hook: HookArgKType = _DUMMYHOOK, variant_hook: HookVrntType = _DUMMYHOOK, - path: Optional[List[str]] = None, + path: list[str] | None = None, ): # first, do something with the key # then, take out the vaule and do something with it @@ -339,7 +341,7 @@ def traverse_value( value_hook: HookArgVType = _DUMMYHOOK, sub_hook: HookArgKType = _DUMMYHOOK, variant_hook: HookVrntType = _DUMMYHOOK, - path: Optional[List[str]] = None, + path: list[str] | None = None, ): # this is not private, and can be called directly # in the condition where there is no leading key @@ -367,7 +369,7 @@ def _traverse_sub( value_hook: HookArgVType = _DUMMYHOOK, sub_hook: HookArgKType = _DUMMYHOOK, variant_hook: HookVrntType = _DUMMYHOOK, - path: Optional[List[str]] = None, + path: list[str] | None = None, ): assert isinstance(value, dict) if path is None: @@ -480,7 +482,7 @@ def normalize( inplace: bool = False, do_default: bool = True, do_alias: bool = True, - trim_pattern: Optional[str] = None, + trim_pattern: str | None = None, ): """Modify `argdict` so that it meets the Argument structure. @@ -533,7 +535,7 @@ def normalize_value( inplace: bool = False, do_default: bool = True, do_alias: bool = True, - trim_pattern: Optional[str] = None, + trim_pattern: str | None = None, ): """Modify the value so that it meets the Argument structure. @@ -600,7 +602,7 @@ def _convert_alias(self, argdict: dict, path=None): # above are normalizing part # below are doc generation part - def gen_doc(self, path: Optional[List[str]] = None, **kwargs) -> str: + def gen_doc(self, path: list[str] | None = None, **kwargs) -> str: """Generate doc string for the current Argument.""" # the actual indentation is done here, and ONLY here if path is None: @@ -613,7 +615,7 @@ def gen_doc(self, path: Optional[List[str]] = None, **kwargs) -> str: ] return "\n".join(filter(None, doc_list)) - def gen_doc_head(self, path: Optional[List[str]] = None, **kwargs) -> str: + def gen_doc_head(self, path: list[str] | None = None, **kwargs) -> str: typesig = "| type: " + " | ".join( [f"``{self._get_type_name(dt)}``" for dt in self.dtype] ) @@ -628,19 +630,20 @@ def gen_doc_head(self, path: Optional[List[str]] = None, **kwargs) -> str: typesig += ", ".join(f"*{al}*" for al in self.alias) head = f"{self.name}: " if kwargs.get("use_sphinx_domain", False): + assert path is not None head = f".. dargs:argument:: {self.name}:\n :path: {'/'.join(path)}\n" head += f"\n{indent(typesig, INDENT)}" if kwargs.get("make_anchor"): head = f"{make_rst_refid(path)}\n" + head return head - def gen_doc_path(self, path: Optional[List[str]] = None, **kwargs) -> str: + def gen_doc_path(self, path: list[str] | None = None, **kwargs) -> str: if path is None: path = [self.name] pathdoc = f"| argument path: ``{'/'.join(path)}``\n" return pathdoc - def gen_doc_body(self, path: Optional[List[str]] = None, **kwargs) -> str: + def gen_doc_body(self, path: list[str] | None = None, **kwargs) -> str: body_list = [] if self.doc: body_list.append(self.doc + "\n") @@ -698,14 +701,14 @@ class Variant: def __init__( self, flag_name: str, - choices: Optional[Iterable["Argument"]] = None, + choices: Iterable[Argument] | None = None, optional: bool = False, default_tag: str = "", # this is indeed necessary in case of optional doc: str = "", ): self.flag_name = flag_name - self.choice_dict: Dict[str, Argument] = {} - self.choice_alias: Dict[str, str] = {} + self.choice_dict: dict[str, Argument] = {} + self.choice_alias: dict[str, str] = {} self.extend_choices(choices) self.optional = optional if optional and not default_tag: @@ -713,7 +716,9 @@ def __init__( self.set_default(default_tag) self.doc = doc - def __eq__(self, other: "Variant") -> bool: + def __eq__(self, other: object) -> bool: + if not isinstance(other, Variant): + return NotImplemented # do not compare doc return ( self.flag_name == other.flag_name @@ -727,10 +732,10 @@ def __repr__(self) -> str: f"" ) - def __getitem__(self, key: str) -> "Argument": + def __getitem__(self, key: str) -> Argument: return self.choice_dict[key] - def set_default(self, default_tag: Union[bool, str]): + def set_default(self, default_tag: bool | str): """Change the default tag of the current Variant.""" if not default_tag: self.optional = False @@ -741,7 +746,7 @@ def set_default(self, default_tag: Union[bool, str]): self.optional = True self.default_tag = default_tag - def extend_choices(self, choices: Optional[Iterable["Argument"]]): + def extend_choices(self, choices: Iterable[Argument] | None): """Add a list of choice Arguments to the current Variant.""" # choices is a list of arguments # whose name is treated as the switch tag @@ -764,11 +769,11 @@ def extend_choices(self, choices: Optional[Iterable["Argument"]]): def add_choice( self, - tag: Union[str, "Argument"], - _dtype: Union[None, type, Iterable[type]] = dict, + tag: str | Argument, + _dtype: None | type | Iterable[type] = dict, *args, **kwargs, - ) -> "Argument": + ) -> Argument: """Add a choice Argument to the current Variant.""" if isinstance(tag, Argument): newarg = tag @@ -794,7 +799,7 @@ def dummy_argument(self): # above are creation part # below are helpers for traversing - def get_choice(self, argdict: dict, path=None) -> "Argument": + def get_choice(self, argdict: dict, path=None) -> Argument: if self.flag_name in argdict: tag = argdict[self.flag_name] if tag in self.choice_dict: @@ -819,7 +824,7 @@ def get_choice(self, argdict: dict, path=None) -> "Argument": "to choose variant but not found.", ) - def flatten_sub(self, argdict: dict, path=None) -> Dict[str, "Argument"]: + def flatten_sub(self, argdict: dict, path=None) -> dict[str, Argument]: choice = self.get_choice(argdict, path) fields = { self.flag_name: self.dummy_argument(), # as a placeholder @@ -837,7 +842,7 @@ def _convert_choice_alias(self, argdict: dict, path=None): # below are doc generation part def gen_doc( - self, path: Optional[List[str]] = None, showflag: bool = False, **kwargs + self, path: list[str] | None = None, showflag: bool = False, **kwargs ) -> str: body_list = [""] body_list.append( @@ -847,6 +852,7 @@ def gen_doc( body_list.append(self.gen_doc_flag(path, showflag=showflag, **kwargs)) fnstr = f"*{self.flag_name}*" if kwargs.get("make_link"): + assert path is not None 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") @@ -872,7 +878,7 @@ def gen_doc( body = "\n".join(body_list) return body - def gen_doc_flag(self, path: Optional[List[str]] = None, **kwargs) -> str: + def gen_doc_flag(self, path: list[str] | None = None, **kwargs) -> str: headdoc = f"{self.flag_name}:" typedoc = "| type: ``str`` (flag key)" if self.optional: @@ -917,7 +923,7 @@ def gen_doc_flag(self, path: Optional[List[str]] = None, **kwargs) -> str: return "\n".join([x for x in allparts if x is not None]) def _make_cpath( - self, cname: str, path: Optional[List[str]] = None, showflag: bool = False + self, cname: str, path: list[str] | None = None, showflag: bool = False ): f_str = f"{self.flag_name}=" if showflag else "" c_str = f"[{f_str}{cname}]" @@ -949,9 +955,9 @@ def make_ref_pair(path, text=None, prefix=None): def update_nodup( this: dict, - *others: Union[dict, Iterable[tuple]], - exclude: Optional[Iterable] = None, - err_msg: Optional[str] = None, + *others: dict | Iterable[tuple], + exclude: Iterable | None = None, + err_msg: str | None = None, ): for pair in others: if isinstance(pair, dict): @@ -969,7 +975,7 @@ def update_nodup( def trim_by_pattern( argdict: dict, pattern: str, - reserved: Optional[List[str]] = None, + reserved: Iterable[str] | None = None, use_regex: bool = False, ): rep = fnmatch.translate(pattern) if not use_regex else pattern @@ -1007,7 +1013,7 @@ class ArgumentEncoder(json.JSONEncoder): >>> json.dumps(some_arg, cls=ArgumentEncoder) """ - def default(self, obj) -> Dict[str, Union[str, bool, List]]: + def default(self, o) -> Any: """Generate a dict containing argument information, making it ready to be encoded to JSON string. @@ -1017,42 +1023,42 @@ def default(self, obj) -> Dict[str, Union[str, bool, List]]: Returns ------- - dict: Dict - a dict containing argument information + Any + any; for Argument and Variant, returns a dict containing argument information """ - if isinstance(obj, Argument): + if isinstance(o, Argument): output = { "object": "Argument", - "name": obj.name, - "type": obj.dtype, - "optional": obj.optional, - "alias": obj.alias, - "doc": obj.doc, - "repeat": obj.repeat, - "sub_fields": obj.sub_fields, - "sub_variants": obj.sub_variants, + "name": o.name, + "type": o.dtype, + "optional": o.optional, + "alias": o.alias, + "doc": o.doc, + "repeat": o.repeat, + "sub_fields": o.sub_fields, + "sub_variants": o.sub_variants, } - if obj.optional and obj.default is not _Flags.NONE: - output["default"] = obj.default + if o.optional and o.default is not _Flags.NONE: + output["default"] = o.default return output - elif isinstance(obj, Variant): + elif isinstance(o, Variant): return { "object": "Variant", - "flag_name": obj.flag_name, - "optional": obj.optional, - "default_tag": obj.default_tag, - "choice_dict": obj.choice_dict, - "choice_alias": obj.choice_alias, - "doc": obj.doc, + "flag_name": o.flag_name, + "optional": o.optional, + "default_tag": o.default_tag, + "choice_dict": o.choice_dict, + "choice_alias": o.choice_alias, + "doc": o.doc, } - elif isinstance(get_origin(obj), type): - return get_origin(obj).__name__ - elif isinstance(obj, type): - return obj.__name__ - return json.JSONEncoder.default(self, obj) + elif isinstance(get_origin(o), type): + return get_origin(o).__name__ + elif isinstance(o, type): + return o.__name__ + return json.JSONEncoder.default(self, o) -def did_you_mean(choice: str, choices: List[str]) -> str: +def did_you_mean(choice: str, choices: Iterable[str]) -> str: """Get did you mean message. Parameters diff --git a/dargs/notebook.py b/dargs/notebook.py index b69b31b..dce5f77 100644 --- a/dargs/notebook.py +++ b/dargs/notebook.py @@ -17,9 +17,11 @@ >>> JSON(jstr, _test_argument()) ''' +from __future__ import annotations + import json import re -from typing import List, Union +from typing import Any from IPython.display import HTML, display @@ -87,7 +89,7 @@ """ -def JSON(data: Union[dict, str], arg: Union[Argument, List[Argument]]): +def JSON(data: dict | str, arg: Argument | list[Argument]): """Display JSON data with Argument in the Jupyter Notebook. Parameters @@ -100,7 +102,7 @@ def JSON(data: Union[dict, str], arg: Union[Argument, List[Argument]]): display(HTML(print_html(data, arg))) -def print_html(data: Union[dict, str], arg: Union[Argument, List[Argument]]) -> str: +def print_html(data: Any, arg: Argument | list[Argument]) -> str: """Print HTML string with Argument in the Jupyter Notebook. Parameters @@ -142,11 +144,11 @@ class ArgumentData: ---------- data : dict The data to be displayed. - arg : dargs.Argument + arg : Union[dargs.Argument, dargs.Variant] The Argument that describes the data. """ - def __init__(self, data: dict, arg: Argument): + def __init__(self, data: dict, arg: Argument | Variant): self.data = data self.arg = arg self.subdata = [] diff --git a/dargs/py.typed b/dargs/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/dargs/sphinx.py b/dargs/sphinx.py index 4e61770..affb1fa 100644 --- a/dargs/sphinx.py +++ b/dargs/sphinx.py @@ -20,8 +20,10 @@ where `_test_argument` returns an :class:`Argument `. A :class:`list` of :class:`Argument ` is also accepted. """ +from __future__ import annotations + import sys -from typing import ClassVar, List +from typing import TYPE_CHECKING, Any, Callable, ClassVar, List from docutils.parsers.rst import Directive from docutils.parsers.rst.directives import unchanged @@ -33,12 +35,15 @@ from .dargs import Argument, Variant +if TYPE_CHECKING: + from sphinx.util.typing import RoleFunction + class DargsDirective(Directive): """dargs directive.""" has_content: ClassVar[bool] = True - option_spec: ClassVar[dict] = { + option_spec: ClassVar[dict[str, Callable[[str], Any]] | None] = { "module": unchanged, "func": unchanged, } @@ -132,17 +137,17 @@ class DargsDomain(Domain): name: ClassVar[str] = "dargs" label: ClassVar[str] = "dargs" - object_types: ClassVar[dict] = { + object_types: ClassVar[dict[str, ObjType]] = { # type: ignore "argument": ObjType("argument", "argument"), } - directives: ClassVar[dict] = { + directives: ClassVar[dict[str, type[Directive]]] = { # type: ignore "argument": DargsObject, } - roles: ClassVar[dict] = { + roles: ClassVar[dict[str, RoleFunction | XRefRole]] = { # type: ignore "argument": XRefRole(), } - initial_data: ClassVar[dict] = { + initial_data: ClassVar[dict] = { # type: ignore "arguments": {}, # fullname -> docname, objtype } @@ -203,7 +208,7 @@ def _test_argument() -> Argument: ) -def _test_arguments() -> List[Argument]: +def _test_arguments() -> list[Argument]: """Returns a list of arguments.""" return [ Argument(name="test1", dtype=int, doc="Argument 1"), diff --git a/docs/conf.py b/docs/conf.py index 88c1a40..34270de 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -11,6 +11,8 @@ # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # +from __future__ import annotations + import os import sys from datetime import date diff --git a/pyproject.toml b/pyproject.toml index 29d7fbe..8e5b0e2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,6 +31,11 @@ repository = "https://github.com/deepmodeling/dargs" test = [ "ipython", ] +typecheck = [ + "basedpyright==1.12.2", + "sphinx", + "ipython", +] [tool.setuptools.packages.find] include = ["dargs*"] @@ -47,6 +52,7 @@ select = [ "C4", # flake8-comprehensions "RUF", # ruff "I", # isort + "TCH", # flake8-type-checking ] ignore = [ @@ -68,3 +74,9 @@ ignore-init-module-imports = true [tool.ruff.lint.pydocstyle] convention = "numpy" + +[tool.ruff.lint.isort] +required-imports = ["from __future__ import annotations"] + +[tool.pyright] +include = ["dargs"] diff --git a/tests/__init__.py b/tests/__init__.py index aa17b14..1a60d59 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import os import sys diff --git a/tests/dpmdargs.py b/tests/dpmdargs.py index 9a5b1db..8241083 100644 --- a/tests/dpmdargs.py +++ b/tests/dpmdargs.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from dargs import Argument, Variant, dargs ACTIVATION_FN_DICT = { diff --git a/tests/test_checker.py b/tests/test_checker.py index 2370591..62fea21 100644 --- a/tests/test_checker.py +++ b/tests/test_checker.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import unittest from typing import List diff --git a/tests/test_creation.py b/tests/test_creation.py index a13569c..c75a8ec 100644 --- a/tests/test_creation.py +++ b/tests/test_creation.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import unittest from dargs import Argument, Variant diff --git a/tests/test_docgen.py b/tests/test_docgen.py index 98203ee..edcfabe 100644 --- a/tests/test_docgen.py +++ b/tests/test_docgen.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import json import unittest from typing import List diff --git a/tests/test_normalizer.py b/tests/test_normalizer.py index 753f575..2282d9f 100644 --- a/tests/test_normalizer.py +++ b/tests/test_normalizer.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import unittest from dargs import Argument, Variant diff --git a/tests/test_notebook.py b/tests/test_notebook.py index 01e46a7..bd26f50 100644 --- a/tests/test_notebook.py +++ b/tests/test_notebook.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import unittest from xml.etree import ElementTree as ET From d9ef16467522d49c4c019aea255298f7c010a287 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Thu, 16 May 2024 18:35:56 -0400 Subject: [PATCH 2/3] move _reorg_dtype before extend_subfields and extend_subvariants Signed-off-by: Jinzhe Zeng --- dargs/dargs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dargs/dargs.py b/dargs/dargs.py index 3c45363..290f9fd 100644 --- a/dargs/dargs.py +++ b/dargs/dargs.py @@ -162,11 +162,11 @@ def __init__( self.doc = doc self.fold_subdoc = fold_subdoc self.extra_check_errmsg = extra_check_errmsg + # handle the format of dtype, makeit a tuple + self.dtype = self._reorg_dtype(dtype) # adding subfields and subvariants self.extend_subfields(sub_fields) self.extend_subvariants(sub_variants) - # handle the format of dtype, makeit a tuple - self.dtype = self._reorg_dtype(dtype) def __eq__(self, other: object) -> bool: if not isinstance(other, Argument): From 548bc7003f0eb1de397ddb24ad4b7775bffb72f6 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Thu, 16 May 2024 18:36:53 -0400 Subject: [PATCH 3/3] rename github actions name Signed-off-by: Jinzhe Zeng --- .github/workflows/type-check.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/type-check.yml b/.github/workflows/type-check.yml index 61cb44d..e65f47e 100644 --- a/.github/workflows/type-check.yml +++ b/.github/workflows/type-check.yml @@ -1,11 +1,10 @@ -name: Python package - +name: Type check on: - push - pull_request jobs: - build: + type_check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4