xenoslib 0.1.29.23__tar.gz → 0.1.30__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.
- {xenoslib-0.1.29.23/xenoslib.egg-info → xenoslib-0.1.30}/PKG-INFO +1 -1
- {xenoslib-0.1.29.23 → xenoslib-0.1.30}/xenoslib/about.py +1 -1
- xenoslib-0.1.30/xenoslib/extend.py +198 -0
- xenoslib-0.1.30/xenoslib/tools/__init__.py +1 -0
- xenoslib-0.1.29.23/xenoslib/extend.py → xenoslib-0.1.30/xenoslib/tools/config_loader.py +8 -183
- {xenoslib-0.1.29.23 → xenoslib-0.1.30/xenoslib.egg-info}/PKG-INFO +1 -1
- {xenoslib-0.1.29.23 → xenoslib-0.1.30}/xenoslib.egg-info/SOURCES.txt +3 -1
- {xenoslib-0.1.29.23 → xenoslib-0.1.30}/LICENSE +0 -0
- {xenoslib-0.1.29.23 → xenoslib-0.1.30}/README.md +0 -0
- {xenoslib-0.1.29.23 → xenoslib-0.1.30}/setup.cfg +0 -0
- {xenoslib-0.1.29.23 → xenoslib-0.1.30}/setup.py +0 -0
- {xenoslib-0.1.29.23 → xenoslib-0.1.30}/xenoslib/__init__.py +0 -0
- {xenoslib-0.1.29.23 → xenoslib-0.1.30}/xenoslib/__main__.py +0 -0
- {xenoslib-0.1.29.23 → xenoslib-0.1.30}/xenoslib/base.py +0 -0
- {xenoslib-0.1.29.23 → xenoslib-0.1.30}/xenoslib/dev.py +0 -0
- {xenoslib-0.1.29.23 → xenoslib-0.1.30}/xenoslib/linux.py +0 -0
- {xenoslib-0.1.29.23 → xenoslib-0.1.30}/xenoslib/mail.py +0 -0
- {xenoslib-0.1.29.23 → xenoslib-0.1.30}/xenoslib/mock.py +0 -0
- {xenoslib-0.1.29.23 → xenoslib-0.1.30}/xenoslib/onedrive.py +0 -0
- {xenoslib-0.1.29.23 → xenoslib-0.1.30}/xenoslib/win_trayicon.py +0 -0
- {xenoslib-0.1.29.23 → xenoslib-0.1.30}/xenoslib/windows.py +0 -0
- {xenoslib-0.1.29.23 → xenoslib-0.1.30}/xenoslib.egg-info/dependency_links.txt +0 -0
- {xenoslib-0.1.29.23 → xenoslib-0.1.30}/xenoslib.egg-info/requires.txt +0 -0
- {xenoslib-0.1.29.23 → xenoslib-0.1.30}/xenoslib.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
import logging
|
|
6
|
+
|
|
7
|
+
import yaml
|
|
8
|
+
import requests
|
|
9
|
+
|
|
10
|
+
from xenoslib.tools import ConfigLoader # noqa compactive
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class YamlConfig(dict):
|
|
17
|
+
"""A thread unsafe yaml file config utility , can work as a dict except __init__"""
|
|
18
|
+
|
|
19
|
+
def __getattr__(self, key):
|
|
20
|
+
return self.get(key)
|
|
21
|
+
|
|
22
|
+
def __setattr__(self, name, value):
|
|
23
|
+
try:
|
|
24
|
+
getattr(super(), name)
|
|
25
|
+
except AttributeError as exc:
|
|
26
|
+
if str(exc).startswith("'super' object has no attribute "):
|
|
27
|
+
self[name] = value
|
|
28
|
+
return
|
|
29
|
+
raise exc
|
|
30
|
+
raise AttributeError(f"'{__class__.__name__}' object attribute '{name}' is read-only")
|
|
31
|
+
|
|
32
|
+
def __str__(self):
|
|
33
|
+
return yaml.safe_dump(self.copy(), allow_unicode=True)
|
|
34
|
+
|
|
35
|
+
def __repr__(self):
|
|
36
|
+
return repr(str(self))
|
|
37
|
+
|
|
38
|
+
def __init__(self, conf_path=None):
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
def __new__(cls, conf_path="config.yml", *args, **kwargs):
|
|
42
|
+
if not hasattr(cls, "_instances"):
|
|
43
|
+
cls._instances = {}
|
|
44
|
+
if cls._instances.get(conf_path) is None:
|
|
45
|
+
cls._instances[conf_path] = super().__new__(cls)
|
|
46
|
+
super().__setattr__(cls._instances[conf_path], "_conf_path", conf_path)
|
|
47
|
+
cls._instances[conf_path]._load_conf()
|
|
48
|
+
return cls._instances[conf_path]
|
|
49
|
+
|
|
50
|
+
def _load_conf(self):
|
|
51
|
+
if os.path.exists(self._conf_path):
|
|
52
|
+
with open(self._conf_path, encoding="utf-8") as r:
|
|
53
|
+
self.update(yaml.safe_load(r))
|
|
54
|
+
|
|
55
|
+
def save(self):
|
|
56
|
+
data = str(self)
|
|
57
|
+
with open(self._conf_path, "w", encoding="utf-8") as w:
|
|
58
|
+
w.write(data)
|
|
59
|
+
# yaml.safe_dump(self.copy(), w, allow_unicode=True)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class RequestAdapter:
|
|
63
|
+
def request(self, method, path, *args, **kwargs):
|
|
64
|
+
"""to-do: support stream=True"""
|
|
65
|
+
url = f"{self.base_url}/{path}"
|
|
66
|
+
logger.debug(url)
|
|
67
|
+
response = self.session.request(method, url, *args, **kwargs)
|
|
68
|
+
logger.debug(response.text)
|
|
69
|
+
response.raise_for_status()
|
|
70
|
+
try:
|
|
71
|
+
return response.json()
|
|
72
|
+
except Exception as exc:
|
|
73
|
+
logger.debug(exc)
|
|
74
|
+
return response
|
|
75
|
+
|
|
76
|
+
def get(self, path, *args, **kwargs):
|
|
77
|
+
return self.request("get", path, *args, **kwargs)
|
|
78
|
+
|
|
79
|
+
def post(self, path, *args, **kwargs):
|
|
80
|
+
return self.request("post", path, *args, **kwargs)
|
|
81
|
+
|
|
82
|
+
def put(self, path, *args, **kwargs):
|
|
83
|
+
return self.request("put", path, *args, **kwargs)
|
|
84
|
+
|
|
85
|
+
def delete(self, path, *args, **kwargs):
|
|
86
|
+
return self.request("delete", path, *args, **kwargs)
|
|
87
|
+
|
|
88
|
+
def patch(self, path, *args, **kwargs):
|
|
89
|
+
return self.request("patch", path, *args, **kwargs)
|
|
90
|
+
|
|
91
|
+
def head(self, path, *args, **kwargs):
|
|
92
|
+
return self.request("head", path, *args, **kwargs)
|
|
93
|
+
|
|
94
|
+
def __init__(self):
|
|
95
|
+
self.session = requests.Session()
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def del_to_recyclebin(filepath, on_fail_delete=False):
|
|
99
|
+
"""delete file to recyclebin if possible"""
|
|
100
|
+
if not sys.platform == "win32":
|
|
101
|
+
if on_fail_delete:
|
|
102
|
+
os.remove(filepath)
|
|
103
|
+
return True
|
|
104
|
+
return False
|
|
105
|
+
from win32com.shell import shell, shellcon
|
|
106
|
+
|
|
107
|
+
res, _ = shell.SHFileOperation(
|
|
108
|
+
(
|
|
109
|
+
0,
|
|
110
|
+
shellcon.FO_DELETE,
|
|
111
|
+
filepath,
|
|
112
|
+
None,
|
|
113
|
+
shellcon.FOF_SILENT | shellcon.FOF_ALLOWUNDO | shellcon.FOF_NOCONFIRMATION,
|
|
114
|
+
None,
|
|
115
|
+
None,
|
|
116
|
+
)
|
|
117
|
+
)
|
|
118
|
+
return res == 0
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def send_notify(msg, key):
|
|
122
|
+
"""send a message for ifttt"""
|
|
123
|
+
url = f"https://maker.ifttt.com/trigger/message/with/key/{key}"
|
|
124
|
+
data = {"value1": msg}
|
|
125
|
+
return requests.post(url, data=data, timeout=(30, 30))
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class IFTTTLogHandler(logging.Handler):
|
|
129
|
+
"""
|
|
130
|
+
log handler for IFTTT
|
|
131
|
+
usage:
|
|
132
|
+
key = 'xxxxx.xxxzx.xxxzx.xxxzx'
|
|
133
|
+
iftttloghandler = IFTTTLogHandler(key, level=logging.INFO)
|
|
134
|
+
logging.getLogger(__name__).addHandler(iftttloghandler)
|
|
135
|
+
"""
|
|
136
|
+
|
|
137
|
+
def __init__(self, key, level=logging.CRITICAL, *args, **kwargs):
|
|
138
|
+
self.key = key
|
|
139
|
+
super().__init__(level=level, *args, **kwargs)
|
|
140
|
+
|
|
141
|
+
def emit(self, record):
|
|
142
|
+
try:
|
|
143
|
+
send_notify(self.format(record), self.key)
|
|
144
|
+
except Exception as exc:
|
|
145
|
+
print(exc)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class SlackLogHandler(logging.Handler):
|
|
149
|
+
"""
|
|
150
|
+
log handler for Slack
|
|
151
|
+
usage:
|
|
152
|
+
slackloghandler = SlackLogHandler(webhook_url, level=logging.INFO)
|
|
153
|
+
logging.getLogger(__name__).addHandler(slackloghandler)
|
|
154
|
+
"""
|
|
155
|
+
|
|
156
|
+
def __init__(self, webhook_url, level=logging.CRITICAL, *args, **kwargs):
|
|
157
|
+
self.url = webhook_url
|
|
158
|
+
self.headers = {"Content-type": "application/json"}
|
|
159
|
+
super().__init__(level=level, *args, **kwargs)
|
|
160
|
+
|
|
161
|
+
def emit(self, record):
|
|
162
|
+
try:
|
|
163
|
+
data = {"text": self.format(record)}
|
|
164
|
+
requests.post(self.url, headers=self.headers, json=data, timeout=(30, 30))
|
|
165
|
+
except Exception as exc:
|
|
166
|
+
print(exc)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
class DingTalkLogHandler(logging.Handler):
|
|
170
|
+
"""
|
|
171
|
+
log handler for DingTalk
|
|
172
|
+
usage:
|
|
173
|
+
token = 'xxxxx.xxxzx.xxxzx.xxxzx'
|
|
174
|
+
dingtalkloghandler = DingTalkLogHandler(token, level=logging.INFO)
|
|
175
|
+
logging.getLogger(__name__).addHandler(dingtalkloghandler)
|
|
176
|
+
"""
|
|
177
|
+
|
|
178
|
+
def __init__(self, token, level=logging.CRITICAL, *args, **kwargs):
|
|
179
|
+
self.token = token
|
|
180
|
+
super().__init__(level=level, *args, **kwargs)
|
|
181
|
+
|
|
182
|
+
def emit(self, record):
|
|
183
|
+
headers = {"Content-Type": "application/json"}
|
|
184
|
+
url = "https://oapi.dingtalk.com/robot/send"
|
|
185
|
+
params = {"access_token": self.token}
|
|
186
|
+
msg = self.format(record)
|
|
187
|
+
data = {"msgtype": "text", "text": {"content": msg}}
|
|
188
|
+
try:
|
|
189
|
+
response = requests.post(
|
|
190
|
+
url, headers=headers, params=params, json=data, timeout=(10, 10)
|
|
191
|
+
)
|
|
192
|
+
print(response.json())
|
|
193
|
+
except Exception as exc:
|
|
194
|
+
print(exc)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
if __name__ == "__main__":
|
|
198
|
+
pass
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .config_loader import ConfigLoader # noqa
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
import os
|
|
4
|
-
import sys
|
|
5
4
|
import logging
|
|
6
5
|
|
|
7
6
|
import yaml
|
|
8
|
-
import requests
|
|
9
7
|
|
|
10
8
|
from xenoslib.base import SingletonWithArgs
|
|
11
9
|
|
|
@@ -13,187 +11,6 @@ from xenoslib.base import SingletonWithArgs
|
|
|
13
11
|
logger = logging.getLogger(__name__)
|
|
14
12
|
|
|
15
13
|
|
|
16
|
-
class YamlConfig(dict):
|
|
17
|
-
"""A thread unsafe yaml file config utility , can work as a dict except __init__"""
|
|
18
|
-
|
|
19
|
-
def __getattr__(self, key):
|
|
20
|
-
return self.get(key)
|
|
21
|
-
|
|
22
|
-
def __setattr__(self, name, value):
|
|
23
|
-
try:
|
|
24
|
-
getattr(super(), name)
|
|
25
|
-
except AttributeError as exc:
|
|
26
|
-
if str(exc).startswith("'super' object has no attribute "):
|
|
27
|
-
self[name] = value
|
|
28
|
-
return
|
|
29
|
-
raise exc
|
|
30
|
-
raise AttributeError(f"'{__class__.__name__}' object attribute '{name}' is read-only")
|
|
31
|
-
|
|
32
|
-
def __str__(self):
|
|
33
|
-
return yaml.safe_dump(self.copy(), allow_unicode=True)
|
|
34
|
-
|
|
35
|
-
def __repr__(self):
|
|
36
|
-
return repr(str(self))
|
|
37
|
-
|
|
38
|
-
def __init__(self, conf_path=None):
|
|
39
|
-
pass
|
|
40
|
-
|
|
41
|
-
def __new__(cls, conf_path="config.yml", *args, **kwargs):
|
|
42
|
-
if not hasattr(cls, "_instances"):
|
|
43
|
-
cls._instances = {}
|
|
44
|
-
if cls._instances.get(conf_path) is None:
|
|
45
|
-
cls._instances[conf_path] = super().__new__(cls)
|
|
46
|
-
super().__setattr__(cls._instances[conf_path], "_conf_path", conf_path)
|
|
47
|
-
cls._instances[conf_path]._load_conf()
|
|
48
|
-
return cls._instances[conf_path]
|
|
49
|
-
|
|
50
|
-
def _load_conf(self):
|
|
51
|
-
if os.path.exists(self._conf_path):
|
|
52
|
-
with open(self._conf_path, encoding="utf-8") as r:
|
|
53
|
-
self.update(yaml.safe_load(r))
|
|
54
|
-
|
|
55
|
-
def save(self):
|
|
56
|
-
data = str(self)
|
|
57
|
-
with open(self._conf_path, "w", encoding="utf-8") as w:
|
|
58
|
-
w.write(data)
|
|
59
|
-
# yaml.safe_dump(self.copy(), w, allow_unicode=True)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
class RequestAdapter:
|
|
63
|
-
def request(self, method, path, *args, **kwargs):
|
|
64
|
-
"""to-do: support stream=True"""
|
|
65
|
-
url = f"{self.base_url}/{path}"
|
|
66
|
-
logger.debug(url)
|
|
67
|
-
response = self.session.request(method, url, *args, **kwargs)
|
|
68
|
-
logger.debug(response.text)
|
|
69
|
-
response.raise_for_status()
|
|
70
|
-
try:
|
|
71
|
-
return response.json()
|
|
72
|
-
except Exception as exc:
|
|
73
|
-
logger.debug(exc)
|
|
74
|
-
return response
|
|
75
|
-
|
|
76
|
-
def get(self, path, *args, **kwargs):
|
|
77
|
-
return self.request("get", path, *args, **kwargs)
|
|
78
|
-
|
|
79
|
-
def post(self, path, *args, **kwargs):
|
|
80
|
-
return self.request("post", path, *args, **kwargs)
|
|
81
|
-
|
|
82
|
-
def put(self, path, *args, **kwargs):
|
|
83
|
-
return self.request("put", path, *args, **kwargs)
|
|
84
|
-
|
|
85
|
-
def delete(self, path, *args, **kwargs):
|
|
86
|
-
return self.request("delete", path, *args, **kwargs)
|
|
87
|
-
|
|
88
|
-
def patch(self, path, *args, **kwargs):
|
|
89
|
-
return self.request("patch", path, *args, **kwargs)
|
|
90
|
-
|
|
91
|
-
def head(self, path, *args, **kwargs):
|
|
92
|
-
return self.request("head", path, *args, **kwargs)
|
|
93
|
-
|
|
94
|
-
def __init__(self):
|
|
95
|
-
self.session = requests.Session()
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
def del_to_recyclebin(filepath, on_fail_delete=False):
|
|
99
|
-
"""delete file to recyclebin if possible"""
|
|
100
|
-
if not sys.platform == "win32":
|
|
101
|
-
if on_fail_delete:
|
|
102
|
-
os.remove(filepath)
|
|
103
|
-
return True
|
|
104
|
-
return False
|
|
105
|
-
from win32com.shell import shell, shellcon
|
|
106
|
-
|
|
107
|
-
res, _ = shell.SHFileOperation(
|
|
108
|
-
(
|
|
109
|
-
0,
|
|
110
|
-
shellcon.FO_DELETE,
|
|
111
|
-
filepath,
|
|
112
|
-
None,
|
|
113
|
-
shellcon.FOF_SILENT | shellcon.FOF_ALLOWUNDO | shellcon.FOF_NOCONFIRMATION,
|
|
114
|
-
None,
|
|
115
|
-
None,
|
|
116
|
-
)
|
|
117
|
-
)
|
|
118
|
-
return res == 0
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
def send_notify(msg, key):
|
|
122
|
-
"""send a message for ifttt"""
|
|
123
|
-
url = f"https://maker.ifttt.com/trigger/message/with/key/{key}"
|
|
124
|
-
data = {"value1": msg}
|
|
125
|
-
return requests.post(url, data=data, timeout=(30, 30))
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
class IFTTTLogHandler(logging.Handler):
|
|
129
|
-
"""
|
|
130
|
-
log handler for IFTTT
|
|
131
|
-
usage:
|
|
132
|
-
key = 'xxxxx.xxxzx.xxxzx.xxxzx'
|
|
133
|
-
iftttloghandler = IFTTTLogHandler(key, level=logging.INFO)
|
|
134
|
-
logging.getLogger(__name__).addHandler(iftttloghandler)
|
|
135
|
-
"""
|
|
136
|
-
|
|
137
|
-
def __init__(self, key, level=logging.CRITICAL, *args, **kwargs):
|
|
138
|
-
self.key = key
|
|
139
|
-
super().__init__(level=level, *args, **kwargs)
|
|
140
|
-
|
|
141
|
-
def emit(self, record):
|
|
142
|
-
try:
|
|
143
|
-
send_notify(self.format(record), self.key)
|
|
144
|
-
except Exception as exc:
|
|
145
|
-
print(exc)
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
class SlackLogHandler(logging.Handler):
|
|
149
|
-
"""
|
|
150
|
-
log handler for Slack
|
|
151
|
-
usage:
|
|
152
|
-
slackloghandler = SlackLogHandler(webhook_url, level=logging.INFO)
|
|
153
|
-
logging.getLogger(__name__).addHandler(slackloghandler)
|
|
154
|
-
"""
|
|
155
|
-
|
|
156
|
-
def __init__(self, webhook_url, level=logging.CRITICAL, *args, **kwargs):
|
|
157
|
-
self.url = webhook_url
|
|
158
|
-
self.headers = {"Content-type": "application/json"}
|
|
159
|
-
super().__init__(level=level, *args, **kwargs)
|
|
160
|
-
|
|
161
|
-
def emit(self, record):
|
|
162
|
-
try:
|
|
163
|
-
data = {"text": self.format(record)}
|
|
164
|
-
requests.post(self.url, headers=self.headers, json=data, timeout=(30, 30))
|
|
165
|
-
except Exception as exc:
|
|
166
|
-
print(exc)
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
class DingTalkLogHandler(logging.Handler):
|
|
170
|
-
"""
|
|
171
|
-
log handler for DingTalk
|
|
172
|
-
usage:
|
|
173
|
-
token = 'xxxxx.xxxzx.xxxzx.xxxzx'
|
|
174
|
-
dingtalkloghandler = DingTalkLogHandler(token, level=logging.INFO)
|
|
175
|
-
logging.getLogger(__name__).addHandler(dingtalkloghandler)
|
|
176
|
-
"""
|
|
177
|
-
|
|
178
|
-
def __init__(self, token, level=logging.CRITICAL, *args, **kwargs):
|
|
179
|
-
self.token = token
|
|
180
|
-
super().__init__(level=level, *args, **kwargs)
|
|
181
|
-
|
|
182
|
-
def emit(self, record):
|
|
183
|
-
headers = {"Content-Type": "application/json"}
|
|
184
|
-
url = "https://oapi.dingtalk.com/robot/send"
|
|
185
|
-
params = {"access_token": self.token}
|
|
186
|
-
msg = self.format(record)
|
|
187
|
-
data = {"msgtype": "text", "text": {"content": msg}}
|
|
188
|
-
try:
|
|
189
|
-
response = requests.post(
|
|
190
|
-
url, headers=headers, params=params, json=data, timeout=(10, 10)
|
|
191
|
-
)
|
|
192
|
-
print(response.json())
|
|
193
|
-
except Exception as exc:
|
|
194
|
-
print(exc)
|
|
195
|
-
|
|
196
|
-
|
|
197
14
|
class ConfigLoader(SingletonWithArgs):
|
|
198
15
|
"""Centralized configuration management with optional Vault integration.
|
|
199
16
|
|
|
@@ -362,6 +179,13 @@ class SectionProxy:
|
|
|
362
179
|
"""Dictionary-style access to configuration values."""
|
|
363
180
|
return self._loader.get(self._section, key)
|
|
364
181
|
|
|
182
|
+
def get(self, key, default=None):
|
|
183
|
+
"""Dictionary-style access to configuration values."""
|
|
184
|
+
try:
|
|
185
|
+
return self._loader.get(self._section, key)
|
|
186
|
+
except KeyError:
|
|
187
|
+
return default
|
|
188
|
+
|
|
365
189
|
def __getattr__(self, key):
|
|
366
190
|
"""Attribute-style access to configuration values."""
|
|
367
191
|
try:
|
|
@@ -384,3 +208,4 @@ if __name__ == "__main__":
|
|
|
384
208
|
|
|
385
209
|
print("With Vault:", config_with_vault.test.test)
|
|
386
210
|
print("With Vault:", config_with_vault["cis"]["cis_client_id"])
|
|
211
|
+
print("Try val not exists: ", config_with_vault.test.get("not_exists"))
|
|
@@ -17,4 +17,6 @@ xenoslib.egg-info/PKG-INFO
|
|
|
17
17
|
xenoslib.egg-info/SOURCES.txt
|
|
18
18
|
xenoslib.egg-info/dependency_links.txt
|
|
19
19
|
xenoslib.egg-info/requires.txt
|
|
20
|
-
xenoslib.egg-info/top_level.txt
|
|
20
|
+
xenoslib.egg-info/top_level.txt
|
|
21
|
+
xenoslib/tools/__init__.py
|
|
22
|
+
xenoslib/tools/config_loader.py
|
|
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
|