cxppython 0.0.2__tar.gz → 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cxppython-0.0.2 → cxppython-0.1.0}/PKG-INFO +1 -1
- cxppython-0.1.0/cxppython/core/config.py +248 -0
- cxppython-0.1.0/cxppython/utils/__init__.py +0 -0
- {cxppython-0.0.2 → cxppython-0.1.0}/cxppython/utils/database/mysql.py +8 -4
- {cxppython-0.0.2 → cxppython-0.1.0}/cxppython.egg-info/PKG-INFO +1 -1
- {cxppython-0.0.2 → cxppython-0.1.0}/cxppython.egg-info/SOURCES.txt +2 -0
- {cxppython-0.0.2 → cxppython-0.1.0}/setup.py +1 -1
- {cxppython-0.0.2 → cxppython-0.1.0}/LICENSE +0 -0
- {cxppython-0.0.2 → cxppython-0.1.0}/README.md +0 -0
- {cxppython-0.0.2 → cxppython-0.1.0}/cxppython/__init__.py +0 -0
- {cxppython-0.0.2/cxppython/utils → cxppython-0.1.0/cxppython/core}/__init__.py +0 -0
- {cxppython-0.0.2 → cxppython-0.1.0}/cxppython/main.py +0 -0
- {cxppython-0.0.2 → cxppython-0.1.0}/cxppython/utils/btlogging/__init__.py +0 -0
- {cxppython-0.0.2 → cxppython-0.1.0}/cxppython/utils/btlogging/console.py +0 -0
- {cxppython-0.0.2 → cxppython-0.1.0}/cxppython/utils/btlogging/defines.py +0 -0
- {cxppython-0.0.2 → cxppython-0.1.0}/cxppython/utils/btlogging/format.py +0 -0
- {cxppython-0.0.2 → cxppython-0.1.0}/cxppython/utils/btlogging/helpers.py +0 -0
- {cxppython-0.0.2 → cxppython-0.1.0}/cxppython/utils/btlogging/loggingmachine.py +0 -0
- {cxppython-0.0.2 → cxppython-0.1.0}/cxppython/utils/database/__init__.py +0 -0
- {cxppython-0.0.2 → cxppython-0.1.0}/cxppython/utils/easy_imports.py +0 -0
- {cxppython-0.0.2 → cxppython-0.1.0}/cxppython.egg-info/dependency_links.txt +0 -0
- {cxppython-0.0.2 → cxppython-0.1.0}/cxppython.egg-info/requires.txt +0 -0
- {cxppython-0.0.2 → cxppython-0.1.0}/cxppython.egg-info/top_level.txt +0 -0
- {cxppython-0.0.2 → cxppython-0.1.0}/setup.cfg +0 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
"""Implementation of the config class, which manages the configuration of different Bittensor modules.
|
|
2
|
+
|
|
3
|
+
Example:
|
|
4
|
+
import argparse
|
|
5
|
+
import bittensor as bt
|
|
6
|
+
|
|
7
|
+
parser = argparse.ArgumentParser('Miner')
|
|
8
|
+
bt.Axon.add_args(parser)
|
|
9
|
+
bt.Subtensor.add_args(parser)
|
|
10
|
+
bt.Async_subtensor.add_args(parser)
|
|
11
|
+
bt.Wallet.add_args(parser)
|
|
12
|
+
bt.logging.add_args(parser)
|
|
13
|
+
bt.PriorityThreadPoolExecutor.add_args(parser)
|
|
14
|
+
config = bt.config(parser)
|
|
15
|
+
|
|
16
|
+
print(config)
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import argparse
|
|
20
|
+
import os
|
|
21
|
+
import sys
|
|
22
|
+
from copy import deepcopy
|
|
23
|
+
from typing import Any, TypeVar, Type, Optional
|
|
24
|
+
|
|
25
|
+
import yaml
|
|
26
|
+
from munch import DefaultMunch
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _filter_keys(obj):
|
|
30
|
+
"""Filters keys from an object, excluding private and certain internal properties."""
|
|
31
|
+
if isinstance(obj, dict):
|
|
32
|
+
return {
|
|
33
|
+
k: _filter_keys(v)
|
|
34
|
+
for k, v in obj.items()
|
|
35
|
+
if not k.startswith("__") and not k.startswith("_Config__is_set")
|
|
36
|
+
}
|
|
37
|
+
elif isinstance(obj, (Config, DefaultMunch)):
|
|
38
|
+
return _filter_keys(obj.toDict())
|
|
39
|
+
return obj
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class InvalidConfigFile(Exception):
|
|
43
|
+
"""Raised when there's an error loading the config file."""
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class Config(DefaultMunch):
|
|
47
|
+
"""Manages configuration for Bittensor modules with nested namespace support."""
|
|
48
|
+
|
|
49
|
+
def __init__(
|
|
50
|
+
self,
|
|
51
|
+
parser: argparse.ArgumentParser = None,
|
|
52
|
+
args: Optional[list[str]] = None,
|
|
53
|
+
strict: bool = False,
|
|
54
|
+
default: Any = None,
|
|
55
|
+
) -> None:
|
|
56
|
+
super().__init__(default)
|
|
57
|
+
self.__is_set = {}
|
|
58
|
+
|
|
59
|
+
if parser is None:
|
|
60
|
+
return
|
|
61
|
+
|
|
62
|
+
self._add_default_arguments(parser)
|
|
63
|
+
args = args or sys.argv[1:]
|
|
64
|
+
self._validate_required_args(parser, args)
|
|
65
|
+
|
|
66
|
+
config_params = self._parse_args(args, parser, strict=False)
|
|
67
|
+
config_path = self._get_config_path(config_params)
|
|
68
|
+
strict = strict or getattr(config_params, "strict", False)
|
|
69
|
+
|
|
70
|
+
if config_path:
|
|
71
|
+
self._load_config_file(parser, config_path)
|
|
72
|
+
|
|
73
|
+
params = self._parse_args(args, parser, strict)
|
|
74
|
+
self._build_config_tree(params)
|
|
75
|
+
self._detect_set_parameters(parser, args)
|
|
76
|
+
|
|
77
|
+
def __str__(self) -> str:
|
|
78
|
+
"""String representation without private keys, optimized to avoid deepcopy."""
|
|
79
|
+
cleaned = _filter_keys(self.toDict())
|
|
80
|
+
return "\n" + yaml.dump(cleaned, sort_keys=False, default_flow_style=False)
|
|
81
|
+
|
|
82
|
+
def __repr__(self) -> str:
|
|
83
|
+
"""String representation of the Config."""
|
|
84
|
+
return self.__str__()
|
|
85
|
+
|
|
86
|
+
def _validate_required_args(
|
|
87
|
+
self, parser: argparse.ArgumentParser, args: list[str]
|
|
88
|
+
) -> None:
|
|
89
|
+
"""Validates required arguments are present."""
|
|
90
|
+
missing = self._find_missing_required_args(parser, args)
|
|
91
|
+
if missing:
|
|
92
|
+
raise ValueError(f"Missing required arguments: {', '.join(missing)}")
|
|
93
|
+
|
|
94
|
+
def _find_missing_required_args(
|
|
95
|
+
self, parser: argparse.ArgumentParser, args: list[str]
|
|
96
|
+
) -> list[str]:
|
|
97
|
+
"""Identifies missing required arguments."""
|
|
98
|
+
required = {a.dest for a in parser._actions if a.required}
|
|
99
|
+
provided = {a.split("=")[0].lstrip("-") for a in args if a.startswith("-")}
|
|
100
|
+
return list(required - provided)
|
|
101
|
+
|
|
102
|
+
def _get_config_path(self, params: DefaultMunch) -> Optional[str]:
|
|
103
|
+
"""Gets Config path from parameters."""
|
|
104
|
+
return getattr(params, "config", None)
|
|
105
|
+
|
|
106
|
+
def _load_config_file(self, parser: argparse.ArgumentParser, path: str) -> None:
|
|
107
|
+
"""Loads Config from YAML file."""
|
|
108
|
+
try:
|
|
109
|
+
with open(os.path.expanduser(path)) as f:
|
|
110
|
+
config = yaml.safe_load(f)
|
|
111
|
+
print(f"Loading config from: {path}")
|
|
112
|
+
parser.set_defaults(**config)
|
|
113
|
+
except Exception as e:
|
|
114
|
+
raise InvalidConfigFile(f"Error loading config: {e}") from e
|
|
115
|
+
|
|
116
|
+
def _build_config_tree(self, params: DefaultMunch) -> None:
|
|
117
|
+
"""Builds nested Config structure."""
|
|
118
|
+
for key, value in params.items():
|
|
119
|
+
if key in ["__is_set"]:
|
|
120
|
+
continue
|
|
121
|
+
current = self
|
|
122
|
+
parts = key.split(".")
|
|
123
|
+
for part in parts[:-1]:
|
|
124
|
+
current = current.setdefault(part, Config())
|
|
125
|
+
current[parts[-1]] = value
|
|
126
|
+
|
|
127
|
+
def _detect_set_parameters(
|
|
128
|
+
self, parser: argparse.ArgumentParser, args: list[str]
|
|
129
|
+
) -> None:
|
|
130
|
+
"""Detects which parameters were explicitly set."""
|
|
131
|
+
temp_parser = self._create_non_default_parser(parser)
|
|
132
|
+
detected = self._parse_args(args, temp_parser, strict=False)
|
|
133
|
+
self.__is_set = DefaultMunch(**{k: True for k in detected.keys()})
|
|
134
|
+
|
|
135
|
+
def _create_non_default_parser(
|
|
136
|
+
self, original: argparse.ArgumentParser
|
|
137
|
+
) -> argparse.ArgumentParser:
|
|
138
|
+
"""Creates a parser that ignores default values."""
|
|
139
|
+
parser = deepcopy(original)
|
|
140
|
+
for action in parser._actions:
|
|
141
|
+
action.default = argparse.SUPPRESS
|
|
142
|
+
return parser
|
|
143
|
+
|
|
144
|
+
@staticmethod
|
|
145
|
+
def _parse_args(
|
|
146
|
+
args: list[str], parser: argparse.ArgumentParser, strict: bool
|
|
147
|
+
) -> DefaultMunch:
|
|
148
|
+
"""Parses args with error handling."""
|
|
149
|
+
try:
|
|
150
|
+
if strict:
|
|
151
|
+
result = parser.parse_args(args)
|
|
152
|
+
return DefaultMunch.fromDict(vars(result))
|
|
153
|
+
|
|
154
|
+
result, unknown = parser.parse_known_args(args)
|
|
155
|
+
for arg in unknown:
|
|
156
|
+
if arg.startswith("--") and (name := arg[2:]) in vars(result):
|
|
157
|
+
setattr(result, name, True)
|
|
158
|
+
return DefaultMunch.fromDict(vars(result))
|
|
159
|
+
except Exception:
|
|
160
|
+
raise ValueError("Invalid arguments provided.")
|
|
161
|
+
|
|
162
|
+
def __deepcopy__(self, memo) -> "Config":
|
|
163
|
+
"""Creates a deep copy that maintains Config type."""
|
|
164
|
+
new_config = Config()
|
|
165
|
+
memo[id(self)] = new_config
|
|
166
|
+
|
|
167
|
+
for key, value in self.items():
|
|
168
|
+
new_config[key] = deepcopy(value, memo)
|
|
169
|
+
|
|
170
|
+
new_config.__is_set = deepcopy(self.__is_set, memo)
|
|
171
|
+
return new_config
|
|
172
|
+
|
|
173
|
+
def merge(self, other: "Config") -> None:
|
|
174
|
+
"""Merges another Config into this one."""
|
|
175
|
+
self.update(self._merge_dicts(self, other))
|
|
176
|
+
self.__is_set.update(other.__is_set)
|
|
177
|
+
|
|
178
|
+
@staticmethod
|
|
179
|
+
def _merge_dicts(a: DefaultMunch, b: DefaultMunch) -> DefaultMunch:
|
|
180
|
+
"""Recursively merges two Config objects."""
|
|
181
|
+
result = deepcopy(a)
|
|
182
|
+
for key, value in b.items():
|
|
183
|
+
if key in result:
|
|
184
|
+
if isinstance(result[key], DefaultMunch) and isinstance(
|
|
185
|
+
value, DefaultMunch
|
|
186
|
+
):
|
|
187
|
+
result[key] = Config._merge_dicts(result[key], value)
|
|
188
|
+
else:
|
|
189
|
+
result[key] = deepcopy(value)
|
|
190
|
+
else:
|
|
191
|
+
result[key] = deepcopy(value)
|
|
192
|
+
return result
|
|
193
|
+
|
|
194
|
+
def is_set(self, param_name: str) -> bool:
|
|
195
|
+
"""Checks if a parameter was explicitly set."""
|
|
196
|
+
return self.__is_set.get(param_name, False)
|
|
197
|
+
|
|
198
|
+
def to_dict(self) -> dict:
|
|
199
|
+
"""Returns the configuration as a dictionary."""
|
|
200
|
+
return self.toDict()
|
|
201
|
+
|
|
202
|
+
def _add_default_arguments(self, parser: argparse.ArgumentParser) -> None:
|
|
203
|
+
"""Adds default arguments to the Config parser."""
|
|
204
|
+
arguments = [
|
|
205
|
+
(
|
|
206
|
+
"--config",
|
|
207
|
+
{
|
|
208
|
+
"type": str,
|
|
209
|
+
"help": "If set, defaults are overridden by passed file.",
|
|
210
|
+
"default": False,
|
|
211
|
+
},
|
|
212
|
+
),
|
|
213
|
+
(
|
|
214
|
+
"--strict",
|
|
215
|
+
{
|
|
216
|
+
"action": "store_true",
|
|
217
|
+
"help": "If flagged, config will check that only exact arguments have been set.",
|
|
218
|
+
"default": False,
|
|
219
|
+
},
|
|
220
|
+
),
|
|
221
|
+
(
|
|
222
|
+
"--no_version_checking",
|
|
223
|
+
{
|
|
224
|
+
"action": "store_true",
|
|
225
|
+
"help": "Set `true to stop cli version checking.",
|
|
226
|
+
"default": False,
|
|
227
|
+
},
|
|
228
|
+
),
|
|
229
|
+
]
|
|
230
|
+
|
|
231
|
+
for arg_name, kwargs in arguments:
|
|
232
|
+
try:
|
|
233
|
+
parser.add_argument(arg_name, **kwargs)
|
|
234
|
+
except argparse.ArgumentError:
|
|
235
|
+
# this can fail if argument has already been added.
|
|
236
|
+
pass
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
T = TypeVar("T", bound="DefaultConfig")
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
class DefaultConfig(Config):
|
|
243
|
+
"""A Config with a set of default values."""
|
|
244
|
+
|
|
245
|
+
@classmethod
|
|
246
|
+
def default(cls: Type[T]) -> T:
|
|
247
|
+
"""Get default config."""
|
|
248
|
+
raise NotImplementedError("Function default is not implemented.")
|
|
File without changes
|
|
@@ -27,9 +27,6 @@ class MysqlDB:
|
|
|
27
27
|
|
|
28
28
|
@staticmethod
|
|
29
29
|
def session() -> Session:
|
|
30
|
-
# engine = DB.__instance.engine
|
|
31
|
-
# session = sessionmaker(bind=engine)
|
|
32
|
-
# return session()
|
|
33
30
|
session = MysqlDB.__instance.session
|
|
34
31
|
return session()
|
|
35
32
|
|
|
@@ -66,6 +63,7 @@ class MysqlDB:
|
|
|
66
63
|
# 尝试建立连接
|
|
67
64
|
with MysqlDB.instance().engine.connect() as connection:
|
|
68
65
|
cc.logging.success("Database connection successful!")
|
|
66
|
+
connection.commit()
|
|
69
67
|
return True
|
|
70
68
|
except OperationalError as e:
|
|
71
69
|
cc.logging.error(f"Failed to connect to the database: {e}")
|
|
@@ -96,7 +94,13 @@ class MysqlDB:
|
|
|
96
94
|
stmt = insert(model).values(batch)
|
|
97
95
|
if ignore_existing:
|
|
98
96
|
stmt = stmt.prefix_with("IGNORE")
|
|
99
|
-
|
|
97
|
+
|
|
98
|
+
try:
|
|
99
|
+
session.execute(stmt)
|
|
100
|
+
except Exception as e:
|
|
101
|
+
cc.logging.error(f"Batch insert failed at index {i}: {e}")
|
|
102
|
+
session.rollback()
|
|
103
|
+
raise
|
|
100
104
|
|
|
101
105
|
if commit_per_batch:
|
|
102
106
|
session.commit()
|
|
@@ -8,6 +8,8 @@ cxppython.egg-info/SOURCES.txt
|
|
|
8
8
|
cxppython.egg-info/dependency_links.txt
|
|
9
9
|
cxppython.egg-info/requires.txt
|
|
10
10
|
cxppython.egg-info/top_level.txt
|
|
11
|
+
cxppython/core/__init__.py
|
|
12
|
+
cxppython/core/config.py
|
|
11
13
|
cxppython/utils/__init__.py
|
|
12
14
|
cxppython/utils/easy_imports.py
|
|
13
15
|
cxppython/utils/btlogging/__init__.py
|
|
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|
|
2
2
|
|
|
3
3
|
setup(
|
|
4
4
|
name="cxppython", # 包名
|
|
5
|
-
version="0.0
|
|
5
|
+
version="0.1.0", # 版本号
|
|
6
6
|
packages=find_packages(exclude=["tests", "tests.*"]), # 自动找到所有包
|
|
7
7
|
description="A python utils package",
|
|
8
8
|
long_description=open("README.md").read(),
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|