diff --git a/Changelog.md b/Changelog.md index 79841cc..95def24 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,10 @@ -# 0.08 +# 0.0.9 + +## 新特性 + ++ 可以使用`@regist_config_file_parser(config_file_name)`来注册如何解析特定命名的配置文件 + +# 0.0.8 ## 新特性 diff --git a/README.md b/README.md index f4a8c60..a3bd254 100644 --- a/README.md +++ b/README.md @@ -362,10 +362,19 @@ class Test_A(EntryPoint): default_config_file_paths = [ "/test_config.json", str(Path.home().joinpath(".test_config.json")), - "./test_config.json" + "./test_config.json", + "./test_config_other.json" ] ``` +##### 指定特定命名的配置文件的解析方式 + +可以使用`@regist_config_file_parser(config_file_name)`来注册如何解析特定命名的配置文件. + +```python + +``` + #### 从环境变量中读取配置参数 要从环境变量中读取配置必须设置`schema`字段,`EntryPoint`会按照其中`properties`字段定义的字段范围和字段类型解析环境变量. @@ -435,6 +444,29 @@ def main(a,b): ``` +另一种指定入口函数的方法是重写子类的`do_main(self)->None`方法 + +```python +class Test_A(EntryPoint): + argparse_noflag = "a" + argparse_check_required=True + schema = { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "a": { + "type": "number" + }, + "b": { + "type": "number" + } + }, + "required": ["a","b"] + } + def do_main(self)->None: + print(self.config) +``` + #### 直接从节点对象中获取配置 节点对象的`config`属性会在每次调用时copy一份当前的配置值,config是不可写的. diff --git a/schema_entry/entrypoint.py b/schema_entry/entrypoint.py index 4ddcfb1..b3c9544 100644 --- a/schema_entry/entrypoint.py +++ b/schema_entry/entrypoint.py @@ -44,6 +44,7 @@ class EntryPoint(EntryPointABC): argparse_check_required = False argparse_noflag = None + _config_file_parser_map: Dict[str, Callable[[Path], Dict[str, Any]]] = {} def _check_schema(self) -> None: if self.schema is not None: @@ -248,6 +249,15 @@ def parse_yaml_configfile_args(self, p: Path) -> Dict[str, Any]: return res return result + def regist_config_file_parser(self, file_name: str) -> Callable[[Callable[[Path], Dict[str, Any]]], Callable[[Path], Dict[str, Any]]]: + def decorate(func: Callable[[Path], Dict[str, Any]]) -> Callable[[Path], Dict[str, Any]]: + @functools.wraps(func) + def wrap(p: Path) -> Dict[str, Any]: + return func(p) + self._config_file_parser_map[file_name] = func + return wrap + return decorate + def parse_configfile_args(self) -> Dict[str, Any]: if not self.default_config_file_paths: return {} @@ -255,6 +265,9 @@ def parse_configfile_args(self) -> Dict[str, Any]: for p_str in self.default_config_file_paths: p = Path(p_str) if p.is_file(): + parfunc = self._config_file_parser_map.get(p.name) + if parfunc: + return parfunc(p) if p.suffix == ".json": return self.parse_json_configfile_args(p) elif p.suffix == ".yml": diff --git a/schema_entry/entrypoint_base.py b/schema_entry/entrypoint_base.py index aeb3c64..4806b54 100644 --- a/schema_entry/entrypoint_base.py +++ b/schema_entry/entrypoint_base.py @@ -1,6 +1,7 @@ """入口类的抽象基类.""" import abc import argparse +from pathlib import Path from typing import Callable, Sequence, Dict, Any, Optional, List, Union, Tuple @@ -40,6 +41,7 @@ class EntryPointABC(abc.ABC): _subcmds: Dict[str, "EntryPointABC"] _main: Optional[Callable[..., None]] + _config_file_parser_map: Dict[str, Callable[[Path], Dict[str, Any]]] _config: Dict[str, Any] @abc.abstractproperty @@ -79,6 +81,19 @@ def regist_sub(self, subcmdclz: type) -> "EntryPointABC": [EntryPointABC]: 注册类的实例 ''' + + @abc.abstractmethod + def regist_config_file_parser(self, file_name: str) -> Callable[[Callable[[Path], Dict[str, Any]]], Callable[[Path], Dict[str, Any]]]: + '''注册特定配置文件名的解析方式. + + Args: + file_name (str): 指定文件名 + + Returns: + Callable[[Callable[[Path], None]], Callable[[Path], None]]: 注册的解析函数 + + ''' + @abc.abstractmethod def as_main(self, func: Callable[..., None]) -> Callable[..., None]: """注册函数在解析参数成功后执行. diff --git a/setup.cfg b/setup.cfg index 5b8c1e2..c4ed7c6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = schema_entry -version = 0.0.8 +version = 0.0.9 url = https://github.com/Python-Tools/schema_entry author = hsz author_email = hsz1273327@gmail.com diff --git a/tests/test_entrypoint.py b/tests/test_entrypoint.py index 379ad5b..39c33d0 100644 --- a/tests/test_entrypoint.py +++ b/tests/test_entrypoint.py @@ -59,6 +59,25 @@ def _(a_a: float) -> None: assert root.usage == "test_a [options]" + def test_override_do_main(self) -> None: + class Test_A(EntryPoint): + schema = { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "a_a": { + "type": "number", + "default": 33.3 + } + }, + "required": ["a_a"] + } + def do_main(self): + assert self.config["a_a"]==33.3 + root = Test_A() + root([]) + + def test_default_subcmd_usage(self) -> None: class A(EntryPoint): pass