dsw-config 4.13.0__py2.py3-none-any.whl → 4.14.0__py2.py3-none-any.whl
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.
- dsw/config/build_info.py +4 -4
- dsw/config/keys.py +23 -15
- dsw/config/logging.py +4 -4
- dsw/config/model.py +32 -43
- dsw/config/parser.py +11 -10
- dsw/config/sentry.py +30 -7
- {dsw_config-4.13.0.dist-info → dsw_config-4.14.0.dist-info}/METADATA +3 -3
- dsw_config-4.14.0.dist-info/RECORD +12 -0
- {dsw_config-4.13.0.dist-info → dsw_config-4.14.0.dist-info}/WHEEL +1 -1
- dsw_config-4.13.0.dist-info/RECORD +0 -12
- {dsw_config-4.13.0.dist-info → dsw_config-4.14.0.dist-info}/LICENSE +0 -0
- {dsw_config-4.13.0.dist-info → dsw_config-4.14.0.dist-info}/top_level.txt +0 -0
dsw/config/build_info.py
CHANGED
|
@@ -9,9 +9,9 @@ BuildInfo = namedtuple(
|
|
|
9
9
|
)
|
|
10
10
|
|
|
11
11
|
BUILD_INFO = BuildInfo(
|
|
12
|
-
version='v4.
|
|
13
|
-
built_at='
|
|
14
|
-
sha='
|
|
12
|
+
version='v4.14.0~213910f',
|
|
13
|
+
built_at='2025-01-07 08:17:37Z',
|
|
14
|
+
sha='213910ffb32a7cea98942ccd0f6c52cb6cf79128',
|
|
15
15
|
branch='HEAD',
|
|
16
|
-
tag='v4.
|
|
16
|
+
tag='v4.14.0',
|
|
17
17
|
)
|
dsw/config/keys.py
CHANGED
|
@@ -1,60 +1,61 @@
|
|
|
1
|
+
# pylint: disable=too-few-public-methods
|
|
1
2
|
import collections
|
|
3
|
+
import typing
|
|
2
4
|
|
|
3
|
-
from typing import Any, Optional, Generic, TypeVar, Callable
|
|
4
5
|
|
|
6
|
+
T = typing.TypeVar('T')
|
|
5
7
|
|
|
6
|
-
T = TypeVar('T')
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
def cast_bool(value: Any) -> bool:
|
|
9
|
+
def cast_bool(value: typing.Any) -> bool:
|
|
10
10
|
return bool(value)
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
def cast_optional_bool(value: Any) ->
|
|
13
|
+
def cast_optional_bool(value: typing.Any) -> bool | None:
|
|
14
14
|
if value is None:
|
|
15
15
|
return None
|
|
16
16
|
return bool(value)
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
def cast_int(value: Any) -> int:
|
|
19
|
+
def cast_int(value: typing.Any) -> int:
|
|
20
20
|
return int(value)
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
def cast_optional_int(value: Any) ->
|
|
23
|
+
def cast_optional_int(value: typing.Any) -> int | None:
|
|
24
24
|
if value is None:
|
|
25
25
|
return None
|
|
26
26
|
return int(value)
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
def cast_float(value: Any) -> float:
|
|
29
|
+
def cast_float(value: typing.Any) -> float:
|
|
30
30
|
return float(value)
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
def cast_optional_float(value: Any) ->
|
|
33
|
+
def cast_optional_float(value: typing.Any) -> float | None:
|
|
34
34
|
if value is None:
|
|
35
35
|
return None
|
|
36
36
|
return float(value)
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
def cast_str(value: Any) -> str:
|
|
39
|
+
def cast_str(value: typing.Any) -> str:
|
|
40
40
|
return str(value)
|
|
41
41
|
|
|
42
42
|
|
|
43
|
-
def cast_optional_str(value: Any) ->
|
|
43
|
+
def cast_optional_str(value: typing.Any) -> str | None:
|
|
44
44
|
if value is None:
|
|
45
45
|
return None
|
|
46
46
|
return str(value)
|
|
47
47
|
|
|
48
48
|
|
|
49
|
-
def cast_optional_dict(value: Any) ->
|
|
49
|
+
def cast_optional_dict(value: typing.Any) -> dict | None:
|
|
50
50
|
if not isinstance(value, dict):
|
|
51
51
|
return None
|
|
52
52
|
return value
|
|
53
53
|
|
|
54
54
|
|
|
55
|
-
class ConfigKey(Generic[T]):
|
|
55
|
+
class ConfigKey(typing.Generic[T]):
|
|
56
56
|
|
|
57
|
-
def __init__(self, yaml_path: list[str],
|
|
57
|
+
def __init__(self, *, yaml_path: list[str],
|
|
58
|
+
cast: typing.Callable[[typing.Any], T],
|
|
58
59
|
var_names=None, default=None, required=False):
|
|
59
60
|
self.yaml_path = yaml_path
|
|
60
61
|
self.var_names = var_names or [] # type: list[str]
|
|
@@ -63,12 +64,13 @@ class ConfigKey(Generic[T]):
|
|
|
63
64
|
self.cast = cast
|
|
64
65
|
|
|
65
66
|
def __str__(self):
|
|
66
|
-
return 'ConfigKey:
|
|
67
|
+
return f'ConfigKey: {".".join(self.yaml_path)}'
|
|
67
68
|
|
|
68
69
|
|
|
69
70
|
class ConfigKeysMeta(type):
|
|
70
71
|
|
|
71
72
|
@classmethod
|
|
73
|
+
# pylint: disable-next=unused-argument
|
|
72
74
|
def __prepare__(mcs, name, bases, **kwargs):
|
|
73
75
|
return collections.OrderedDict()
|
|
74
76
|
|
|
@@ -176,6 +178,12 @@ class _SentryKeys(ConfigKeysContainer):
|
|
|
176
178
|
default='',
|
|
177
179
|
cast=cast_str,
|
|
178
180
|
)
|
|
181
|
+
environment = ConfigKey(
|
|
182
|
+
yaml_path=['sentry', 'environment'],
|
|
183
|
+
var_names=['SENTRY_ENVIRONMENT'],
|
|
184
|
+
default='production',
|
|
185
|
+
cast=cast_str,
|
|
186
|
+
)
|
|
179
187
|
|
|
180
188
|
|
|
181
189
|
class _DatabaseKeys(ConfigKeysContainer):
|
dsw/config/logging.py
CHANGED
|
@@ -28,6 +28,8 @@ class DSWLogger(logging.Logger):
|
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
def prepare_logging(logging_cfg):
|
|
31
|
+
# pylint: disable-next=no-member
|
|
32
|
+
logger_dict = logging.root.manager.loggerDict
|
|
31
33
|
if logging_cfg.dict_config is not None:
|
|
32
34
|
logging.config.dictConfig(logging_cfg.dict_config)
|
|
33
35
|
else:
|
|
@@ -36,15 +38,13 @@ def prepare_logging(logging_cfg):
|
|
|
36
38
|
level=logging_cfg.global_level,
|
|
37
39
|
format=logging_cfg.message_format
|
|
38
40
|
)
|
|
39
|
-
dsw_loggers = (logging.getLogger(name)
|
|
40
|
-
for name in logging.root.manager.loggerDict.keys()
|
|
41
|
+
dsw_loggers = (logging.getLogger(name) for name in logger_dict
|
|
41
42
|
if name.lower().startswith('dsw'))
|
|
42
43
|
for logger in dsw_loggers:
|
|
43
44
|
logger.setLevel(logging_cfg.level)
|
|
44
45
|
# Set for all existing loggers
|
|
45
46
|
logging.getLogger().addFilter(filter=LOG_FILTER)
|
|
46
|
-
loggers = (logging.getLogger(name)
|
|
47
|
-
for name in logging.root.manager.loggerDict.keys())
|
|
47
|
+
loggers = (logging.getLogger(name) for name in logger_dict)
|
|
48
48
|
for logger in loggers:
|
|
49
49
|
logger.addFilter(filter=LOG_FILTER)
|
|
50
50
|
# Set for any future loggers
|
dsw/config/model.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import dataclasses
|
|
2
2
|
|
|
3
3
|
from .logging import prepare_logging, LOG_FILTER
|
|
4
4
|
|
|
@@ -19,52 +19,44 @@ class ConfigModel:
|
|
|
19
19
|
return _config_to_string(self)
|
|
20
20
|
|
|
21
21
|
|
|
22
|
+
@dataclasses.dataclass
|
|
22
23
|
class GeneralConfig(ConfigModel):
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
self.client_url = client_url
|
|
27
|
-
self.secret = secret
|
|
24
|
+
environment: str
|
|
25
|
+
client_url: str
|
|
26
|
+
secret: str
|
|
28
27
|
|
|
29
28
|
|
|
29
|
+
@dataclasses.dataclass
|
|
30
30
|
class SentryConfig(ConfigModel):
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
self.traces_sample_rate = traces_sample_rate
|
|
37
|
-
self.max_breadcrumbs = max_breadcrumbs
|
|
31
|
+
enabled: bool
|
|
32
|
+
workers_dsn: str | None
|
|
33
|
+
traces_sample_rate: float | None
|
|
34
|
+
max_breadcrumbs: int | None
|
|
35
|
+
environment: str
|
|
38
36
|
|
|
39
37
|
|
|
38
|
+
@dataclasses.dataclass
|
|
40
39
|
class DatabaseConfig(ConfigModel):
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
self.connection_string = connection_string
|
|
45
|
-
self.connection_timeout = connection_timeout
|
|
46
|
-
self.queue_timeout = queue_timeout
|
|
40
|
+
connection_string: str
|
|
41
|
+
connection_timeout: int
|
|
42
|
+
queue_timeout: int
|
|
47
43
|
|
|
48
44
|
|
|
45
|
+
@dataclasses.dataclass
|
|
49
46
|
class S3Config(ConfigModel):
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
self.password = password
|
|
56
|
-
self.bucket = bucket
|
|
57
|
-
self.region = region
|
|
47
|
+
url: str
|
|
48
|
+
username: str
|
|
49
|
+
password: str
|
|
50
|
+
bucket: str
|
|
51
|
+
region: str
|
|
58
52
|
|
|
59
53
|
|
|
54
|
+
@dataclasses.dataclass
|
|
60
55
|
class LoggingConfig(ConfigModel):
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
self.global_level = global_level
|
|
66
|
-
self.message_format = message_format
|
|
67
|
-
self.dict_config = dict_config
|
|
56
|
+
level: str
|
|
57
|
+
global_level: str
|
|
58
|
+
message_format: str
|
|
59
|
+
dict_config: dict | None = None
|
|
68
60
|
|
|
69
61
|
def apply(self):
|
|
70
62
|
prepare_logging(self)
|
|
@@ -74,20 +66,17 @@ class LoggingConfig(ConfigModel):
|
|
|
74
66
|
LOG_FILTER.set_extra(key, value)
|
|
75
67
|
|
|
76
68
|
|
|
69
|
+
@dataclasses.dataclass
|
|
77
70
|
class AWSConfig(ConfigModel):
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
self.access_key_id = access_key_id
|
|
82
|
-
self.secret_access_key = secret_access_key
|
|
83
|
-
self.region = region
|
|
71
|
+
access_key_id: str | None
|
|
72
|
+
secret_access_key: str | None
|
|
73
|
+
region: str | None
|
|
84
74
|
|
|
85
75
|
@property
|
|
86
76
|
def has_credentials(self) -> bool:
|
|
87
77
|
return self.access_key_id is not None and self.secret_access_key is not None
|
|
88
78
|
|
|
89
79
|
|
|
80
|
+
@dataclasses.dataclass
|
|
90
81
|
class CloudConfig(ConfigModel):
|
|
91
|
-
|
|
92
|
-
def __init__(self, multi_tenant: bool):
|
|
93
|
-
self.multi_tenant = multi_tenant
|
|
82
|
+
multi_tenant: bool
|
dsw/config/parser.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
|
-
import
|
|
2
|
+
import typing
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
import yaml
|
|
5
5
|
|
|
6
6
|
from .keys import ConfigKey, ConfigKeys
|
|
7
7
|
from .model import GeneralConfig, SentryConfig, S3Config, \
|
|
@@ -10,14 +10,14 @@ from .model import GeneralConfig, SentryConfig, S3Config, \
|
|
|
10
10
|
|
|
11
11
|
class MissingConfigurationError(Exception):
|
|
12
12
|
|
|
13
|
-
def __init__(self, missing:
|
|
13
|
+
def __init__(self, missing: list[str]):
|
|
14
14
|
self.missing = missing
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class DSWConfigParser:
|
|
18
18
|
|
|
19
19
|
def __init__(self, keys=ConfigKeys):
|
|
20
|
-
self.cfg =
|
|
20
|
+
self.cfg = {}
|
|
21
21
|
self.keys = keys
|
|
22
22
|
|
|
23
23
|
@staticmethod
|
|
@@ -28,7 +28,7 @@ class DSWConfigParser:
|
|
|
28
28
|
except Exception:
|
|
29
29
|
return False
|
|
30
30
|
|
|
31
|
-
def read_file(self, fp: IO):
|
|
31
|
+
def read_file(self, fp: typing.IO):
|
|
32
32
|
self.cfg = yaml.load(fp, Loader=yaml.FullLoader) or self.cfg
|
|
33
33
|
|
|
34
34
|
def read_string(self, content: str):
|
|
@@ -50,12 +50,12 @@ class DSWConfigParser:
|
|
|
50
50
|
if self.has_value_for_path(key.yaml_path):
|
|
51
51
|
return True
|
|
52
52
|
for var_name in key.var_names:
|
|
53
|
-
if var_name in os.environ.
|
|
54
|
-
self._prefix_var(var_name) in os.environ.keys():
|
|
53
|
+
if var_name in os.environ or self._prefix_var(var_name) in os.environ:
|
|
55
54
|
return True
|
|
55
|
+
return False
|
|
56
56
|
|
|
57
57
|
def get_or_default(self, key: ConfigKey):
|
|
58
|
-
x = self.cfg
|
|
58
|
+
x: typing.Any = self.cfg
|
|
59
59
|
for p in key.yaml_path:
|
|
60
60
|
if not hasattr(x, 'keys') or p not in x.keys():
|
|
61
61
|
return key.default
|
|
@@ -64,9 +64,9 @@ class DSWConfigParser:
|
|
|
64
64
|
|
|
65
65
|
def get(self, key: ConfigKey):
|
|
66
66
|
for var_name in key.var_names:
|
|
67
|
-
if var_name in os.environ
|
|
67
|
+
if var_name in os.environ:
|
|
68
68
|
return key.cast(os.environ[var_name])
|
|
69
|
-
if self._prefix_var(var_name) in os.environ
|
|
69
|
+
if self._prefix_var(var_name) in os.environ:
|
|
70
70
|
return key.cast(os.environ[self._prefix_var(var_name)])
|
|
71
71
|
return key.cast(self.get_or_default(key))
|
|
72
72
|
|
|
@@ -118,6 +118,7 @@ class DSWConfigParser:
|
|
|
118
118
|
workers_dsn=self.get(self.keys.sentry.worker_dsn),
|
|
119
119
|
traces_sample_rate=self.get(self.keys.sentry.traces_sample_rate),
|
|
120
120
|
max_breadcrumbs=self.get(self.keys.sentry.max_breadcrumbs),
|
|
121
|
+
environment=self.get(self.keys.sentry.environment),
|
|
121
122
|
)
|
|
122
123
|
|
|
123
124
|
@property
|
dsw/config/sentry.py
CHANGED
|
@@ -1,23 +1,46 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import typing
|
|
3
|
+
|
|
1
4
|
import sentry_sdk
|
|
5
|
+
from sentry_sdk.types import Event, Hint
|
|
6
|
+
from sentry_sdk.integrations.logging import LoggingIntegration
|
|
2
7
|
|
|
3
8
|
from .model import SentryConfig
|
|
4
9
|
|
|
5
10
|
|
|
11
|
+
EventProcessor = typing.Callable[[Event, Hint], typing.Optional[Event]]
|
|
12
|
+
|
|
13
|
+
|
|
6
14
|
class SentryReporter:
|
|
7
15
|
report = False
|
|
16
|
+
filters = [] # type: list[EventProcessor]
|
|
8
17
|
|
|
9
18
|
@classmethod
|
|
10
|
-
def initialize(cls,
|
|
11
|
-
|
|
19
|
+
def initialize(cls, *, config: SentryConfig, prog_name: str, release: str,
|
|
20
|
+
breadcrumb_level: int | None = logging.INFO,
|
|
21
|
+
event_level: int | None = logging.ERROR):
|
|
12
22
|
cls.report = config.enabled and config.workers_dsn is not None
|
|
13
23
|
if cls.report:
|
|
24
|
+
def before_send(event, hint):
|
|
25
|
+
for f in cls.filters:
|
|
26
|
+
if not f(event, hint):
|
|
27
|
+
return None
|
|
28
|
+
return event
|
|
29
|
+
|
|
14
30
|
sentry_sdk.init(
|
|
15
|
-
dsn=
|
|
31
|
+
dsn=config.workers_dsn,
|
|
16
32
|
traces_sample_rate=config.traces_sample_rate or 1.0,
|
|
17
33
|
max_breadcrumbs=config.max_breadcrumbs or sentry_sdk.consts.DEFAULT_MAX_BREADCRUMBS,
|
|
18
34
|
release=release,
|
|
19
|
-
|
|
20
|
-
|
|
35
|
+
environment=config.environment,
|
|
36
|
+
before_send=before_send,
|
|
37
|
+
default_integrations=False,
|
|
38
|
+
integrations=[
|
|
39
|
+
LoggingIntegration(
|
|
40
|
+
level=breadcrumb_level,
|
|
41
|
+
event_level=event_level,
|
|
42
|
+
),
|
|
43
|
+
],
|
|
21
44
|
)
|
|
22
45
|
sentry_sdk.set_tag('component', prog_name)
|
|
23
46
|
|
|
@@ -32,6 +55,6 @@ class SentryReporter:
|
|
|
32
55
|
sentry_sdk.capture_message(*args, **kwargs)
|
|
33
56
|
|
|
34
57
|
@classmethod
|
|
35
|
-
def
|
|
58
|
+
def set_tags(cls, **tags):
|
|
36
59
|
if cls.report:
|
|
37
|
-
sentry_sdk.
|
|
60
|
+
sentry_sdk.set_tags(tags)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dsw-config
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.14.0
|
|
4
4
|
Summary: Library for DSW config manipulation
|
|
5
5
|
Author-email: Marek Suchánek <marek.suchanek@ds-wizard.org>
|
|
6
6
|
License: Apache License 2.0
|
|
@@ -11,11 +11,11 @@ Keywords: dsw,config,yaml,parser
|
|
|
11
11
|
Classifier: Development Status :: 5 - Production/Stable
|
|
12
12
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
13
13
|
Classifier: Programming Language :: Python
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
16
|
Classifier: Topic :: Text Processing
|
|
17
17
|
Classifier: Topic :: Utilities
|
|
18
|
-
Requires-Python: <4,>=3.
|
|
18
|
+
Requires-Python: <4,>=3.11
|
|
19
19
|
Description-Content-Type: text/markdown
|
|
20
20
|
License-File: LICENSE
|
|
21
21
|
Requires-Dist: PyYAML
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
dsw/config/__init__.py,sha256=2tf8kQHwcEpoGwUoXyczIFzkAUi112973KTccusrDmM,123
|
|
2
|
+
dsw/config/build_info.py,sha256=Z0iljAjUVSul40hTK_8w0vOzIBbNyBIglaD7dVc-8zI,381
|
|
3
|
+
dsw/config/keys.py,sha256=uKMBHJI8gCrSqyjdpFnwzj1zRRoJnyB0jlXR4p0zDD0,6998
|
|
4
|
+
dsw/config/logging.py,sha256=I4-WjLNRIlmRS3TRXIF66IzI4c0DLzYsbJ0A9jGiPW4,1479
|
|
5
|
+
dsw/config/model.py,sha256=4IIy25TkS0VfDOxWdOW4AxVHVdUiRfBCmEqin9JcYf0,1760
|
|
6
|
+
dsw/config/parser.py,sha256=SOznsTdEMZ31aTKenvYpICA4y4_z-8MWFeTn3xUrlRY,4469
|
|
7
|
+
dsw/config/sentry.py,sha256=anpGZATeJYTLq7n8BF9m_8fcoNrP2hAS53fAZ6JsyOA,1940
|
|
8
|
+
dsw_config-4.14.0.dist-info/LICENSE,sha256=rDtJ4LdsXvf_euOpGD0Q86P78K4JyM5m4yfYz9wZ750,11346
|
|
9
|
+
dsw_config-4.14.0.dist-info/METADATA,sha256=8HiRtfirCeNYgQIeGmBl6VynOd5FnXtOzdhxCEO5XJI,1796
|
|
10
|
+
dsw_config-4.14.0.dist-info/WHEEL,sha256=M1ikteR9eetPNvm1LyQ3rpXxNYuGd90oakQO1a-ohSk,109
|
|
11
|
+
dsw_config-4.14.0.dist-info/top_level.txt,sha256=7SfbsHFoJ_vlAgG6C-xzETETwYO71dBrGnod8uMFnjw,4
|
|
12
|
+
dsw_config-4.14.0.dist-info/RECORD,,
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
dsw/config/__init__.py,sha256=2tf8kQHwcEpoGwUoXyczIFzkAUi112973KTccusrDmM,123
|
|
2
|
-
dsw/config/build_info.py,sha256=ldrmlx-ppzLSG3lD4GXZxHk1Xe1y2LPjAaNR2GQccu4,381
|
|
3
|
-
dsw/config/keys.py,sha256=6X62tAr4ysFpI-ZCHsH9-0Eg0oh9szyjHqJihEQrQTQ,6691
|
|
4
|
-
dsw/config/logging.py,sha256=vCpt349vmvO08SNbp0K6aU9BPt_78op0QxKflDYmg7Q,1484
|
|
5
|
-
dsw/config/model.py,sha256=zJieb9FDDzCGwxX1ijaRVHpcyyx65Q-grqJBaRd6P2s,2684
|
|
6
|
-
dsw/config/parser.py,sha256=klrTnzpe7dL6mxsewb8QExqqKfC-CZcIfZSINoeqVHk,4451
|
|
7
|
-
dsw/config/sentry.py,sha256=Em1d72DGhLmrM5nUIuOwkG_98cjX4NeiYbQluTjRisg,1181
|
|
8
|
-
dsw_config-4.13.0.dist-info/LICENSE,sha256=rDtJ4LdsXvf_euOpGD0Q86P78K4JyM5m4yfYz9wZ750,11346
|
|
9
|
-
dsw_config-4.13.0.dist-info/METADATA,sha256=xSwbsKw0cNZoqXxANgMT1Nz58jAt6QXdfL_6xmHyXf0,1796
|
|
10
|
-
dsw_config-4.13.0.dist-info/WHEEL,sha256=pxeNX5JdtCe58PUSYP9upmc7jdRPgvT0Gm9kb1SHlVw,109
|
|
11
|
-
dsw_config-4.13.0.dist-info/top_level.txt,sha256=7SfbsHFoJ_vlAgG6C-xzETETwYO71dBrGnod8uMFnjw,4
|
|
12
|
-
dsw_config-4.13.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|