cloudoll 2.2.16__tar.gz → 2.2.18__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.
- {cloudoll-2.2.16 → cloudoll-2.2.18}/PKG-INFO +1 -1
- cloudoll-2.2.18/cloudoll/__init__.py +1 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/cli.py +1 -1
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/orm/field.py +67 -1
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/orm/model.py +8 -5
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/web/__init__.py +36 -62
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/web/settings.py +1 -1
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll.egg-info/PKG-INFO +1 -1
- cloudoll-2.2.16/cloudoll/__init__.py +0 -1
- {cloudoll-2.2.16 → cloudoll-2.2.18}/LICENSE +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/README.md +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/__main__.py +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/error/__init__.py +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/error/errors.py +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/logging/__init__.py +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/mail/__init__.py +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/mail/smtp.py +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/orm/__init__.py +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/orm/base.py +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/orm/err.py +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/orm/mysql.py +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/orm/parse.py +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/orm/postgres.py +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/robot/__init__.py +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/robot/dingtalk.py +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/robot/feishu.py +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/robot/slack.py +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/utils/__init__.py +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/utils/common.py +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/utils/m2d.py +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/utils/patch_loop.py +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/utils/watch.py +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/web/exception.py +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/web/html.py +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/web/http.py +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll/web/jwt.py +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll.egg-info/SOURCES.txt +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll.egg-info/dependency_links.txt +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll.egg-info/entry_points.txt +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll.egg-info/requires.txt +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/cloudoll.egg-info/top_level.txt +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/setup.cfg +0 -0
- {cloudoll-2.2.16 → cloudoll-2.2.18}/setup.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.2.18"
|
|
@@ -31,6 +31,17 @@ OP = objdict(
|
|
|
31
31
|
AVG="AVG",
|
|
32
32
|
AS="AS",
|
|
33
33
|
SUM="SUM",
|
|
34
|
+
IS_TODAY="IS_TODAY",
|
|
35
|
+
IS_THIS_WEEK="THIS_WEEK",
|
|
36
|
+
IS_THIS_MONTH="THIS_MONTH",
|
|
37
|
+
IS_THIS_YEAR="THIS_YEAR",
|
|
38
|
+
BEFORE_DAYS="BEFORE_DAYS",
|
|
39
|
+
BEFORE_HOURS="BEFORE_HOURS",
|
|
40
|
+
BEFORE_MINUTES="BEFORE_MINUTES",
|
|
41
|
+
BEFORE_YEARS="BEFORE_YEARS",
|
|
42
|
+
AFTER_YEARS="AFTER_YEARS",
|
|
43
|
+
AFTER_MONTHS="AFTER_MONTHS",
|
|
44
|
+
BEFORE_MONTHS="BEFORE_MONTHS",
|
|
34
45
|
DATE_FORMAT="DATE_FORMAT",
|
|
35
46
|
JSON_CONTAINS_OBJECT="JSON_CONTAINS_OBJECT",
|
|
36
47
|
JSON_CONTAINS_ARRAY="JSON_CONTAINS_ARRAY",
|
|
@@ -115,6 +126,39 @@ class FieldBase(object):
|
|
|
115
126
|
def date_format(self, args):
|
|
116
127
|
return Function(self, OP.DATE_FORMAT, args)
|
|
117
128
|
|
|
129
|
+
def is_today(self):
|
|
130
|
+
return Function(self, OP.IS_TODAY)
|
|
131
|
+
|
|
132
|
+
def is_this_week(self):
|
|
133
|
+
return Function(self, OP.IS_THIS_WEEK)
|
|
134
|
+
|
|
135
|
+
def is_this_month(self):
|
|
136
|
+
return Function(self, OP.IS_THIS_MONTH)
|
|
137
|
+
|
|
138
|
+
def is_this_year(self):
|
|
139
|
+
return Function(self, OP.IS_THIS_YEAR)
|
|
140
|
+
|
|
141
|
+
def before_days(self, args):
|
|
142
|
+
return Function(self, OP.BEFORE_DAYS, args)
|
|
143
|
+
|
|
144
|
+
def before_hours(self, args):
|
|
145
|
+
return Function(self, OP.BEFORE_HOURS, args)
|
|
146
|
+
|
|
147
|
+
def before_minutes(self, args):
|
|
148
|
+
return Function(self, OP.BEFORE_MINUTES, args)
|
|
149
|
+
|
|
150
|
+
def before_years(self, args):
|
|
151
|
+
return Function(self, OP.BEFORE_YEARS, args)
|
|
152
|
+
|
|
153
|
+
def before_months(self, args):
|
|
154
|
+
return Function(self, OP.BEFORE_MONTHS, args)
|
|
155
|
+
|
|
156
|
+
def after_months(self, args):
|
|
157
|
+
return Function(self, OP.AFTER_MONTHS, args)
|
|
158
|
+
|
|
159
|
+
def after_years(self, args):
|
|
160
|
+
return Function(self, OP.AFTER_YEARS, args)
|
|
161
|
+
|
|
118
162
|
def json_contains_object(self, key, value):
|
|
119
163
|
return Function(self, OP.JSON_CONTAINS_OBJECT, (key, value))
|
|
120
164
|
|
|
@@ -186,6 +230,28 @@ class Function(FieldBase):
|
|
|
186
230
|
# todo:
|
|
187
231
|
if op == OP.DATE_FORMAT:
|
|
188
232
|
return f"{op}({col_name},?)", [self.rpt]
|
|
233
|
+
elif op == OP.IS_TODAY:
|
|
234
|
+
return f"DATE({col_name}) = CURDATE()", None
|
|
235
|
+
elif op == OP.IS_THIS_WEEK:
|
|
236
|
+
return f"WEEK({col_name}, 1) = WEEK(CURDATE(), 1)", None
|
|
237
|
+
elif op == OP.IS_THIS_MONTH:
|
|
238
|
+
return f"MONTH({col_name}) = MONTH(CURDATE())", None
|
|
239
|
+
elif op == OP.IS_THIS_YEAR:
|
|
240
|
+
return f"YEAR({col_name}) = YEAR(CURDATE())", None
|
|
241
|
+
elif op == OP.BEFORE_DAYS:
|
|
242
|
+
return f"DATE({col_name}) >= CURDATE() - INTERVAL {self.rpt} DAY", None
|
|
243
|
+
elif op == OP.BEFORE_HOURS:
|
|
244
|
+
return f"{col_name} >= NOW() - INTERVAL {self.rpt} HOUR", None
|
|
245
|
+
elif op == OP.BEFORE_MINUTES:
|
|
246
|
+
return f"{col_name} >= NOW() - INTERVAL {self.rpt} MINUTE", None
|
|
247
|
+
elif op == OP.BEFORE_YEARS:
|
|
248
|
+
return f"{col_name} >= DATE_SUB(NOW(), INTERVAL {self.rpt} YEAR)", None
|
|
249
|
+
elif op == OP.BEFORE_MONTHS:
|
|
250
|
+
return f"{col_name} >= DATE_SUB(NOW(), INTERVAL {self.rpt} MONTH)", None
|
|
251
|
+
elif op == OP.AFTER_YEARS:
|
|
252
|
+
return f"{col_name} < DATE_SUB(NOW(), INTERVAL {self.rpt} YEAR)", None
|
|
253
|
+
elif op == OP.AFTER_MONTHS:
|
|
254
|
+
return f"{col_name} < DATE_SUB(NOW(), INTERVAL {self.rpt} MONTH)", None
|
|
189
255
|
elif op == OP.JSON_CONTAINS_OBJECT:
|
|
190
256
|
_k, _v = self.rpt
|
|
191
257
|
key = _k.full_name if isinstance(_k, Field) else f"'{_k}'"
|
|
@@ -328,4 +394,4 @@ class Field(FieldBase):
|
|
|
328
394
|
|
|
329
395
|
@value.setter
|
|
330
396
|
def value(self, value):
|
|
331
|
-
self._value = value
|
|
397
|
+
self._value = value
|
|
@@ -233,10 +233,13 @@ class Model(metaclass=ModelMetaclass):
|
|
|
233
233
|
params = []
|
|
234
234
|
for k, v in data.items():
|
|
235
235
|
if isinstance(v, Field):
|
|
236
|
-
value = v.value
|
|
237
|
-
if value is
|
|
238
|
-
if
|
|
236
|
+
value = v.value
|
|
237
|
+
if value is None:
|
|
238
|
+
if v.created_generated == True or v.update_generated == True:
|
|
239
239
|
value = datetime.datetime.now()
|
|
240
|
+
else:
|
|
241
|
+
value = v.default
|
|
242
|
+
if value is not None:
|
|
240
243
|
keys.append("`%s`=?" % k)
|
|
241
244
|
params.append(value)
|
|
242
245
|
elif v is not None: # fix sql format %s
|
|
@@ -314,7 +317,7 @@ class Model(metaclass=ModelMetaclass):
|
|
|
314
317
|
|
|
315
318
|
sql = f"update `{table}` set {keys} {where}"
|
|
316
319
|
|
|
317
|
-
if where is not None and where !=
|
|
320
|
+
if where is not None and where != "":
|
|
318
321
|
params += self.__params__
|
|
319
322
|
else:
|
|
320
323
|
pk, pkv = self._get_primary()
|
|
@@ -342,7 +345,7 @@ class Model(metaclass=ModelMetaclass):
|
|
|
342
345
|
args = self.__params__
|
|
343
346
|
sql = f"delete from `{table}` {where}"
|
|
344
347
|
|
|
345
|
-
if where is None or where ==
|
|
348
|
+
if where is None or where == "":
|
|
346
349
|
pk, pkv = self._get_primary()
|
|
347
350
|
if pkv is not None:
|
|
348
351
|
sql += f" where `{pk}`=?"
|
|
@@ -12,8 +12,6 @@ import importlib
|
|
|
12
12
|
import inspect
|
|
13
13
|
import json
|
|
14
14
|
from errno import EADDRINUSE
|
|
15
|
-
import pkgutil
|
|
16
|
-
import sys
|
|
17
15
|
from urllib import parse
|
|
18
16
|
from aiohttp import web
|
|
19
17
|
from aiohttp.web import Response
|
|
@@ -37,6 +35,7 @@ from decimal import Decimal
|
|
|
37
35
|
from datetime import datetime, date
|
|
38
36
|
from ..utils.common import chainMap, Object
|
|
39
37
|
from ..orm import create_engine, parse_coon
|
|
38
|
+
import uuid
|
|
40
39
|
|
|
41
40
|
# from ..orm.mysql import Mysql
|
|
42
41
|
from typing import Optional, Iterable
|
|
@@ -59,7 +58,7 @@ __ALL__ = (
|
|
|
59
58
|
)
|
|
60
59
|
|
|
61
60
|
|
|
62
|
-
class
|
|
61
|
+
class RequestHandler(object):
|
|
63
62
|
def __init__(self, cls, fn):
|
|
64
63
|
self.cls = cls
|
|
65
64
|
self.fn = fn
|
|
@@ -69,12 +68,12 @@ class _Handler(object):
|
|
|
69
68
|
# 获取函数参数的名称和默认值
|
|
70
69
|
props = inspect.getfullargspec(self.fn)
|
|
71
70
|
if len(props.args) == 2 and content_type == "multipart/form-data":
|
|
72
|
-
await
|
|
71
|
+
await set_session_route(request)
|
|
73
72
|
multipart = await request.multipart()
|
|
74
73
|
field = await multipart.next()
|
|
75
74
|
result = await self.fn(request, field)
|
|
76
75
|
elif len(props.args) == 1:
|
|
77
|
-
await
|
|
76
|
+
await set_session_route(request)
|
|
78
77
|
if content_type == "multipart/form-data":
|
|
79
78
|
data = await request.post()
|
|
80
79
|
elif content_type == "application/json":
|
|
@@ -109,7 +108,7 @@ class _Handler(object):
|
|
|
109
108
|
return render_json(result)
|
|
110
109
|
|
|
111
110
|
|
|
112
|
-
async def
|
|
111
|
+
async def set_session_route(request):
|
|
113
112
|
params = dict()
|
|
114
113
|
# match
|
|
115
114
|
rt = request.match_info
|
|
@@ -121,29 +120,6 @@ async def _set_session_route(request):
|
|
|
121
120
|
request.session = session
|
|
122
121
|
|
|
123
122
|
|
|
124
|
-
def _get_modules(fd):
|
|
125
|
-
modules = set()
|
|
126
|
-
temp = os.path.join(os.path.abspath("."), fd)
|
|
127
|
-
if not os.path.exists(temp):
|
|
128
|
-
print_info("Routers not detected")
|
|
129
|
-
return modules
|
|
130
|
-
s = find_packages(temp)
|
|
131
|
-
for pkg in s:
|
|
132
|
-
# modules.add(pkg)
|
|
133
|
-
pkg_path = temp + "/" + pkg.replace(".", "/")
|
|
134
|
-
if sys.version_info.major == 2 or (
|
|
135
|
-
sys.version_info.major == 3 and sys.version_info.minor < 6
|
|
136
|
-
):
|
|
137
|
-
for _, name, ispkg in pkgutil.iter_modules([pkg_path]):
|
|
138
|
-
if not ispkg:
|
|
139
|
-
modules.add(f".{pkg}.{name}")
|
|
140
|
-
else:
|
|
141
|
-
for info in pkgutil.iter_modules([pkg_path]):
|
|
142
|
-
if not info.ispkg:
|
|
143
|
-
modules.add(f".{pkg}.{info.name}")
|
|
144
|
-
return modules
|
|
145
|
-
|
|
146
|
-
|
|
147
123
|
async def check_port_open(port: int, delay: float = 1) -> None:
|
|
148
124
|
loop = asyncio.get_running_loop()
|
|
149
125
|
# the "s = socket.socket; s.bind" approach sometimes says a port is in use when it's not
|
|
@@ -165,21 +141,27 @@ async def check_port_open(port: int, delay: float = 1) -> None:
|
|
|
165
141
|
raise Exception("The port {} is already is use".format(port))
|
|
166
142
|
|
|
167
143
|
|
|
168
|
-
def
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if not os.path.exists(mid_dir):
|
|
173
|
-
print_info("Middlewares not detected")
|
|
144
|
+
def auto_reg_module(module_dir: str):
|
|
145
|
+
module_path = os.path.join(os.path.abspath("."), module_dir)
|
|
146
|
+
if not os.path.exists(module_path):
|
|
147
|
+
print_info(f"{module_dir} not detected")
|
|
174
148
|
return
|
|
175
|
-
for
|
|
176
|
-
if
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
149
|
+
for filename in os.listdir(module_dir):
|
|
150
|
+
if filename.startswith("__") or filename.startswith("."):
|
|
151
|
+
continue
|
|
152
|
+
full_path = os.path.join(os.path.abspath("."), module_dir, filename)
|
|
153
|
+
if os.path.isdir(full_path):
|
|
154
|
+
auto_reg_module(module_dir + os.sep + filename)
|
|
155
|
+
elif filename.endswith(".py"):
|
|
156
|
+
module_name = (
|
|
157
|
+
module_dir.replace(os.sep, ".")
|
|
158
|
+
+ "."
|
|
159
|
+
+ filename[:-3].replace(os.sep, ".")
|
|
160
|
+
)
|
|
161
|
+
importlib.import_module(module_name)
|
|
180
162
|
|
|
181
163
|
|
|
182
|
-
def
|
|
164
|
+
def parse_int(num):
|
|
183
165
|
return eval(num) if isinstance(num, str) else num
|
|
184
166
|
|
|
185
167
|
|
|
@@ -234,7 +216,7 @@ class Application(object):
|
|
|
234
216
|
self.config = config
|
|
235
217
|
|
|
236
218
|
# middlewares
|
|
237
|
-
|
|
219
|
+
auto_reg_module("middlewares")
|
|
238
220
|
|
|
239
221
|
conf_server = config.get("server")
|
|
240
222
|
client_max_size = 1024**2 * 2
|
|
@@ -244,7 +226,7 @@ class Application(object):
|
|
|
244
226
|
logger=None,
|
|
245
227
|
loop=loop,
|
|
246
228
|
middlewares=self._middleware,
|
|
247
|
-
client_max_size=
|
|
229
|
+
client_max_size=parse_int(client_max_size),
|
|
248
230
|
)
|
|
249
231
|
# database
|
|
250
232
|
self.app.db = Object()
|
|
@@ -257,10 +239,11 @@ class Application(object):
|
|
|
257
239
|
self.app.on_startup.append(self._init_session)
|
|
258
240
|
# self._init_session()
|
|
259
241
|
# router:
|
|
260
|
-
|
|
242
|
+
auto_reg_module("controllers")
|
|
243
|
+
self.app.add_routes(self._route_table)
|
|
261
244
|
|
|
262
245
|
# load life
|
|
263
|
-
entry = conf_server.get(
|
|
246
|
+
entry = conf_server.get("entry", entry_model)
|
|
264
247
|
self._load_life_cycle(entry)
|
|
265
248
|
|
|
266
249
|
# static
|
|
@@ -333,7 +316,7 @@ class Application(object):
|
|
|
333
316
|
storage = redis_storage.RedisStorage(
|
|
334
317
|
redis,
|
|
335
318
|
cookie_name=cookie_name,
|
|
336
|
-
max_age=
|
|
319
|
+
max_age=parse_int(max_age),
|
|
337
320
|
httponly=httponly,
|
|
338
321
|
secure=secure,
|
|
339
322
|
)
|
|
@@ -348,7 +331,7 @@ class Application(object):
|
|
|
348
331
|
storage = memcached_storage.MemcachedStorage(
|
|
349
332
|
mc,
|
|
350
333
|
cookie_name=cookie_name,
|
|
351
|
-
max_age=
|
|
334
|
+
max_age=parse_int(max_age),
|
|
352
335
|
httponly=httponly,
|
|
353
336
|
secure=secure,
|
|
354
337
|
)
|
|
@@ -365,23 +348,12 @@ class Application(object):
|
|
|
365
348
|
storage = cookie_storage.EncryptedCookieStorage(
|
|
366
349
|
secret_key,
|
|
367
350
|
cookie_name=cookie_name,
|
|
368
|
-
max_age=
|
|
351
|
+
max_age=parse_int(max_age),
|
|
369
352
|
httponly=httponly,
|
|
370
353
|
)
|
|
371
354
|
setup(apps, storage)
|
|
372
355
|
print_info("start local cookie.")
|
|
373
356
|
|
|
374
|
-
def _reg_router(self):
|
|
375
|
-
fd = "controllers"
|
|
376
|
-
modules = _get_modules(fd)
|
|
377
|
-
for module in modules:
|
|
378
|
-
# print(module)
|
|
379
|
-
importlib.import_module(module, fd)
|
|
380
|
-
|
|
381
|
-
self.app.add_routes(self._route_table)
|
|
382
|
-
# for route in self._routes:
|
|
383
|
-
# self.app.router.add_route(**route)
|
|
384
|
-
|
|
385
357
|
def run(self, **kw):
|
|
386
358
|
"""
|
|
387
359
|
run app
|
|
@@ -417,7 +389,7 @@ class Application(object):
|
|
|
417
389
|
|
|
418
390
|
def add_router(self, path, method, name):
|
|
419
391
|
def inner(handler):
|
|
420
|
-
handler =
|
|
392
|
+
handler = RequestHandler(self, handler)
|
|
421
393
|
self.app.router.add_route(method, path, handler, name=name)
|
|
422
394
|
return handler
|
|
423
395
|
|
|
@@ -478,6 +450,8 @@ class JsonEncoder(json.JSONEncoder):
|
|
|
478
450
|
return list(obj)
|
|
479
451
|
elif isinstance(obj, Model):
|
|
480
452
|
return obj.__dict__
|
|
453
|
+
elif isinstance(obj, uuid.UUID):
|
|
454
|
+
return str(obj)
|
|
481
455
|
else:
|
|
482
456
|
return super(JsonEncoder, self).default(obj)
|
|
483
457
|
|
|
@@ -556,8 +530,8 @@ def render_json(data, **kw) -> Response:
|
|
|
556
530
|
res["data"] = data
|
|
557
531
|
status = kw.get("status", 200)
|
|
558
532
|
if status == 200:
|
|
559
|
-
res["message"] = "OK"
|
|
560
|
-
res["code"] = 200
|
|
533
|
+
res["message"] = kw.get("message", "OK")
|
|
534
|
+
res["code"] = kw.get("code", 200)
|
|
561
535
|
|
|
562
536
|
res["timestamp"] = int(datetime.now().timestamp() * 1000)
|
|
563
537
|
text = json.dumps(res, ensure_ascii=False, cls=JsonEncoder)
|
|
@@ -11,6 +11,6 @@ def get_config(env):
|
|
|
11
11
|
if not os.path.exists(conf_path):
|
|
12
12
|
print_error(f"Configuration file does not exist: {conf_path}")
|
|
13
13
|
return {}
|
|
14
|
-
with open(conf_path,
|
|
14
|
+
with open(conf_path, "r", encoding="utf-8") as f:
|
|
15
15
|
config = yaml.safe_load(f)
|
|
16
16
|
return config or {}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "2.2.16"
|
|
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
|
|
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
|