Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion dargs/_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@


def test_arguments() -> list[Argument]:
"""Returns a list of arguments."""
"""Returns a list of arguments.

Returns
-------
list[Argument]
A list of test arguments
"""
return [
Argument(name="test1", dtype=int, doc="Argument 1"),
Argument(name="test2", dtype=[float, None], doc="Argument 2"),
Expand Down
13 changes: 9 additions & 4 deletions dargs/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,10 @@ def check_cli(
strict : bool
If True, raise an error if the key is not pre-defined

Returns
-------
dict
normalized data
Raises
------
RuntimeError
If the function cannot be imported or does not exist
"""
module_name, attr_name = func.strip().rsplit(".", 1)
try:
Expand Down Expand Up @@ -141,6 +141,11 @@ def doc_cli(
Function that returns an Argument or list of Arguments. E.g., `dargs._test.test_arguments`
arg : str, optional
Optional argument path (e.g., 'base/sub1'). If not provided, prints all top-level arguments.

Raises
------
RuntimeError
If the function cannot be imported or does not exist
"""
try:
module_name, attr_name = func.strip().rsplit(".", 1)
Expand Down
61 changes: 54 additions & 7 deletions dargs/dargs.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,13 @@ def extend_subfields(self, sub_fields: Iterable[Argument] | None) -> None:
self.dtype = self._reorg_dtype(self.dtype)

def add_subfield(self, name: str | Argument, *args: Any, **kwargs: Any) -> Argument:
"""Add a sub field to the current Argument."""
"""Add a sub field to the current Argument.

Returns
-------
Argument
The newly added sub field
"""
if isinstance(name, Argument):
newarg = name
else:
Expand All @@ -303,7 +309,13 @@ def extend_subvariants(self, sub_variants: Iterable[Variant] | None) -> None:
def add_subvariant(
self, flag_name: str | Variant, *args: Any, **kwargs: Any
) -> Variant:
"""Add a sub variant to the current Argument."""
"""Add a sub variant to the current Argument.

Returns
-------
Variant
The newly added sub variant
"""
if isinstance(flag_name, Variant):
newvrnt = flag_name
else:
Expand Down Expand Up @@ -426,6 +438,11 @@ def check(self, argdict: dict, strict: bool = False) -> None:
The arg dict to be checked
strict : bool, optional
If true, only keys defined in `Argument` are allowed.

Raises
------
ArgumentKeyError
If the check fails due to key errors
"""
if strict and len(argdict) != 1:
raise ArgumentKeyError(
Expand Down Expand Up @@ -638,7 +655,13 @@ def _convert_alias(self, argdict: dict, path: list[str] | None = None) -> None:
# below are doc generation part

def gen_doc(self, path: list[str] | None = None, **kwargs: Any) -> str:
"""Generate doc string for the current Argument."""
"""Generate doc string for the current Argument.

Returns
-------
str
The generated documentation string
"""
# the actual indentation is done here, and ONLY here
if path is None:
path = []
Expand Down Expand Up @@ -715,7 +738,13 @@ def gen_doc_body(self, path: list[str] | None = None, **kwargs: Any) -> str:
return body

def _get_type_name(self, dd: type | Any | None) -> str:
"""Get type name for doc/message generation."""
"""Get type name for doc/message generation.

Returns
-------
str
The type name as a string
"""
if dd is None:
return "None"
return str(dd) if isinstance(get_origin(dd), type) else dd.__name__
Expand Down Expand Up @@ -787,7 +816,13 @@ def __getitem__(self, key: str) -> Argument:
return self.choice_dict[key]

def set_default(self, default_tag: bool | str) -> None:
"""Change the default tag of the current Variant."""
"""Change the default tag of the current Variant.

Raises
------
ValueError
If trying to set an invalid default_tag
"""
if not default_tag:
self.optional = False
self.default_tag = ""
Expand Down Expand Up @@ -825,7 +860,13 @@ def add_choice(
*args: Any,
**kwargs: Any,
) -> Argument:
"""Add a choice Argument to the current Variant."""
"""Add a choice Argument to the current Variant.

Returns
-------
Argument
The newly added choice argument
"""
if isinstance(tag, Argument):
newarg = tag
else:
Expand Down Expand Up @@ -1064,7 +1105,13 @@ def trim_by_pattern(


def isinstance_annotation(value: Any, dtype: type | Any) -> bool:
"""Same as isinstance(), but supports arbitrary type annotations."""
"""Same as isinstance(), but supports arbitrary type annotations.

Returns
-------
bool
True if value matches the type annotation, False otherwise
"""
try:
typeguard.check_type(
value,
Expand Down
5 changes: 5 additions & 0 deletions dargs/json_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,11 @@ def _convert_types(T: type | Any | None) -> str:
-------
str
The JSON schema type.

Raises
------
ValueError
If the type cannot be converted to a JSON schema type
"""
# string, number, integer, object, array, boolean, null
if T is None or T is type(None):
Expand Down
15 changes: 15 additions & 0 deletions dargs/notebook.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ def print_html(data: Any, arg: Argument | list[Argument]) -> str:
-------
str
The HTML string.

Raises
------
ValueError
If the data or arg type is unknown
"""
if isinstance(data, str):
data = json.loads(data)
Expand Down Expand Up @@ -209,6 +214,16 @@ def print_html(self, _level: int = 0, _last_one: bool = True) -> str:
The level of indentation, by default 0
_last_one : bool, optional
Whether it is the last one, by default True

Returns
-------
str
The HTML string

Raises
------
ValueError
If the data or arg type is incompatible
"""
linebreak = "<br/>"
indent = (
Expand Down
24 changes: 21 additions & 3 deletions dargs/sphinx.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,13 @@ def resolve_xref(
node: Any,
contnode: Any,
) -> Any:
"""Resolve cross-references."""
"""Resolve cross-references.

Returns
-------
Any
The resolved reference node, or None if not found
"""
targetid = f"{typ}:{target}"
obj = self.data["arguments"].get(targetid)
if obj is None:
Expand All @@ -170,14 +176,26 @@ def resolve_xref(


def setup(app: Any) -> dict[str, bool]:
"""Setup sphinx app."""
"""Setup sphinx app.

Returns
-------
dict[str, bool]
Configuration dictionary for Sphinx
"""
app.add_directive("dargs", DargsDirective)
app.add_domain(DargsDomain)
return {"parallel_read_safe": True}


def _test_argument() -> Argument:
"""This internal function is used to generate docs of dargs."""
"""This internal function is used to generate docs of dargs.

Returns
-------
Argument
A test Argument object
"""
doc_test = "This argument/variant is only used to test."
return Argument(
name="test",
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,10 @@ select = [
"I", # isort
"TCH", # flake8-type-checking
"ANN", # flake8-annotations
"DOC", # pydoclint
"B904", # raise-without-from-inside-except
]
preview = true

ignore = [
"E501", # line too long
Expand All @@ -77,7 +79,6 @@ ignore = [
"D404", # TODO: first word of the docstring should not be This
"ANN401", # Allow typing.Any - necessary for a library handling arbitrary types
]
ignore-init-module-imports = true

[tool.ruff.lint.flake8-annotations]
allow-star-arg-any = true
Expand Down