From a9aff9205f040e4ee9715c375ad97de1eeac357d Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Mon, 26 Jul 2021 04:49:29 -0400 Subject: [PATCH 1/3] add a JSON encoder to encode `Argument` --- dargs/__init__.py | 4 ++-- dargs/dargs.py | 48 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/dargs/__init__.py b/dargs/__init__.py index 41a3f4d..858e9a4 100644 --- a/dargs/__init__.py +++ b/dargs/__init__.py @@ -1,3 +1,3 @@ -from .dargs import Argument, Variant +from .dargs import Argument, Variant, ArgumentEncoder -__all__ = ["Argument", "Variant"] \ No newline at end of file +__all__ = ["Argument", "Variant", "ArgumentEncoder"] \ No newline at end of file diff --git a/dargs/dargs.py b/dargs/dargs.py index c67885f..4c5db3c 100644 --- a/dargs/dargs.py +++ b/dargs/dargs.py @@ -23,6 +23,7 @@ from copy import deepcopy from enum import Enum import fnmatch, re +import json INDENT = " " # doc is indented by four spaces @@ -632,4 +633,49 @@ def trim_by_pattern(argdict: dict, pattern: str, f"following reserved names: {', '.join(conflict)}") unrequired = list(filter(rem.match, argdict.keys())) for key in unrequired: - argdict.pop(key) \ No newline at end of file + argdict.pop(key) + + +class ArgumentEncoder(json.JSONEncoder): + """Extended JSON Encoder to encode Argument object: + + Usage + ----- + >>> json.dumps(some_arg, cls=ArgumentEncoder) + """ + def default(self, obj) -> Dict[str, Union[str, bool, List]]: + """Generate a dict containing argument information, making it ready to be encoded + to JSON string. + + Note + ---- + All object in the dict should be JSON serializable. + + Returns + ------- + dict: Dict + a dict containing argument information + """ + if isinstance(obj, Argument): + return { + "name": obj.name, + "type": obj.dtype, + "alias": obj.alias, + "doc": obj.doc, + "sub_filed": obj.sub_fields, + "fold_subdoc": obj.fold_subdoc, + "repeat": obj.repeat, + "sub_fields": obj.sub_fields, + "sub_variants": obj.sub_variants, + } + elif isinstance(obj, Variant): + return { + "flag_name": obj.flag_name, + "optional": obj.optional, + "default_tag": obj.default_tag, + "choice_dict": obj.choice_dict, + "doc": obj.doc, + } + elif isinstance(obj, type): + return obj.__name__ + return json.JSONEncoder.default(self, obj) From 894624cfe9a7584f63fbcfc0b5948a3831694822 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Mon, 26 Jul 2021 15:46:27 -0400 Subject: [PATCH 2/3] fix typos; add unittests --- dargs/dargs.py | 8 ++++---- tests/test_docgen.py | 7 ++++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/dargs/dargs.py b/dargs/dargs.py index 4c5db3c..42fcf41 100644 --- a/dargs/dargs.py +++ b/dargs/dargs.py @@ -639,8 +639,8 @@ def trim_by_pattern(argdict: dict, pattern: str, class ArgumentEncoder(json.JSONEncoder): """Extended JSON Encoder to encode Argument object: - Usage - ----- + Examples + -------- >>> json.dumps(some_arg, cls=ArgumentEncoder) """ def default(self, obj) -> Dict[str, Union[str, bool, List]]: @@ -658,18 +658,18 @@ def default(self, obj) -> Dict[str, Union[str, bool, List]]: """ if isinstance(obj, Argument): return { + "object": "Argument", "name": obj.name, "type": obj.dtype, "alias": obj.alias, "doc": obj.doc, - "sub_filed": obj.sub_fields, - "fold_subdoc": obj.fold_subdoc, "repeat": obj.repeat, "sub_fields": obj.sub_fields, "sub_variants": obj.sub_variants, } elif isinstance(obj, Variant): return { + "object": "Variant", "flag_name": obj.flag_name, "optional": obj.optional, "default_tag": obj.default_tag, diff --git a/tests/test_docgen.py b/tests/test_docgen.py index 89ba141..e5653d3 100644 --- a/tests/test_docgen.py +++ b/tests/test_docgen.py @@ -1,6 +1,7 @@ from context import dargs import unittest -from dargs import Argument, Variant +import json +from dargs import Argument, Variant, ArgumentEncoder class TestDocgen(unittest.TestCase): @@ -16,6 +17,7 @@ def test_sub_fields(self): ], doc="sub doc." * 5) ], doc="Base doc. " * 10) docstr = ca.gen_doc() + jsonstr = json.dumps(ca, cls=ArgumentEncoder) # print("\n\n"+docstr) def test_sub_repeat(self): @@ -29,6 +31,7 @@ def test_sub_repeat(self): ], doc="sub doc." * 5) ], doc="Base doc. " * 10, repeat=True) docstr = ca.gen_doc() + jsonstr = json.dumps(ca, cls=ArgumentEncoder) # print("\n\n"+docstr) def test_sub_variants(self): @@ -66,6 +69,7 @@ def test_sub_variants(self): ], optional=True, default_tag="type1", doc="another vnt") ]) docstr = ca.gen_doc(make_anchor=True) + jsonstr = json.dumps(ca, cls=ArgumentEncoder) # print("\n\n"+docstr) def test_multi_variants(self): @@ -110,6 +114,7 @@ def test_multi_variants(self): ]) ]) docstr = ca.gen_doc() + jsonstr = json.dumps(ca, cls=ArgumentEncoder) # print("\n\n"+docstr) def test_dpmd(self): From d0b6eab8df154ba228af7a507c2650cb5c1277e0 Mon Sep 17 00:00:00 2001 From: Jinzhe Zeng Date: Mon, 26 Jul 2021 15:54:57 -0400 Subject: [PATCH 3/3] add optional for Argument, choice_alias for Variant --- dargs/dargs.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dargs/dargs.py b/dargs/dargs.py index 42fcf41..5ea6ad2 100644 --- a/dargs/dargs.py +++ b/dargs/dargs.py @@ -661,6 +661,7 @@ def default(self, obj) -> Dict[str, Union[str, bool, List]]: "object": "Argument", "name": obj.name, "type": obj.dtype, + "optional": obj.optional, "alias": obj.alias, "doc": obj.doc, "repeat": obj.repeat, @@ -674,6 +675,7 @@ def default(self, obj) -> Dict[str, Union[str, bool, List]]: "optional": obj.optional, "default_tag": obj.default_tag, "choice_dict": obj.choice_dict, + "choice_alias": obj.choice_alias, "doc": obj.doc, } elif isinstance(obj, type):