appier 1.33.3__py2.py3-none-any.whl → 1.33.5__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.
- appier/__init__.py +9 -1
- appier/base.py +31 -6
- appier/http.py +1 -1
- appier/scheduler.py +8 -0
- appier/structures.py +26 -0
- appier/test/scheduler.py +27 -0
- appier/test/structures.py +38 -0
- appier/util.py +1 -1
- {appier-1.33.3.dist-info → appier-1.33.5.dist-info}/METADATA +1 -1
- {appier-1.33.3.dist-info → appier-1.33.5.dist-info}/RECORD +13 -13
- {appier-1.33.3.dist-info → appier-1.33.5.dist-info}/LICENSE +0 -0
- {appier-1.33.3.dist-info → appier-1.33.5.dist-info}/WHEEL +0 -0
- {appier-1.33.3.dist-info → appier-1.33.5.dist-info}/top_level.txt +0 -0
appier/__init__.py
CHANGED
|
@@ -291,7 +291,15 @@ from .smtp import (
|
|
|
291
291
|
header,
|
|
292
292
|
)
|
|
293
293
|
from .storage import StorageEngine, BaseEngine, FsEngine
|
|
294
|
-
from .structures import
|
|
294
|
+
from .structures import (
|
|
295
|
+
OrderedDict,
|
|
296
|
+
LazyDict,
|
|
297
|
+
LazyValue,
|
|
298
|
+
GeneratorFile,
|
|
299
|
+
LimitedSizeDict,
|
|
300
|
+
lazy_dict,
|
|
301
|
+
lazy,
|
|
302
|
+
)
|
|
295
303
|
from .typesf import (
|
|
296
304
|
AbstractType,
|
|
297
305
|
Type,
|
appier/base.py
CHANGED
|
@@ -94,7 +94,7 @@ NAME = "appier"
|
|
|
94
94
|
""" The name to be used to describe the framework while working
|
|
95
95
|
on its own environment, this is just a descriptive value """
|
|
96
96
|
|
|
97
|
-
VERSION = "1.33.
|
|
97
|
+
VERSION = "1.33.5"
|
|
98
98
|
""" The version of the framework that is currently installed
|
|
99
99
|
this value may be used for debugging/diagnostic purposes """
|
|
100
100
|
|
|
@@ -4207,6 +4207,35 @@ class App(
|
|
|
4207
4207
|
)
|
|
4208
4208
|
line = line.decode(encoding, "ignore") if legacy.is_bytes(line) else line
|
|
4209
4209
|
|
|
4210
|
+
# runs the template for the path, so that it's possible to better
|
|
4211
|
+
# understand the origin of the path execution
|
|
4212
|
+
path_f = template % (path, lineno, context)
|
|
4213
|
+
|
|
4214
|
+
# in case the path to the file does not exists, then there's nothing
|
|
4215
|
+
# remaining to be done in terms of specific stack format
|
|
4216
|
+
if not path or not os.path.exists(path):
|
|
4217
|
+
# creates the "file-less" item dictionary to be used to a certain
|
|
4218
|
+
# degree of debuggability
|
|
4219
|
+
item_d = dict(
|
|
4220
|
+
id=id,
|
|
4221
|
+
path=path,
|
|
4222
|
+
path_f=path_f,
|
|
4223
|
+
line=line,
|
|
4224
|
+
lineno=lineno,
|
|
4225
|
+
context=context,
|
|
4226
|
+
lines=[],
|
|
4227
|
+
lines_b=[],
|
|
4228
|
+
)
|
|
4229
|
+
cls._extended_handle(item_d)
|
|
4230
|
+
|
|
4231
|
+
# adds the newly created formatted item to the list of formatted
|
|
4232
|
+
# items to be returned at the end of the method execution
|
|
4233
|
+
formatted.append(item_d)
|
|
4234
|
+
|
|
4235
|
+
# continues the loop as this is not a valid file and no
|
|
4236
|
+
# further information can be retrieved
|
|
4237
|
+
continue
|
|
4238
|
+
|
|
4210
4239
|
# opens the current file in stack trace and reads the complete
|
|
4211
4240
|
# contents from it so that the target lines may be read
|
|
4212
4241
|
file = open(path, "rb")
|
|
@@ -4220,7 +4249,7 @@ class App(
|
|
|
4220
4249
|
contents_d = contents.decode(encoding, "ignore")
|
|
4221
4250
|
|
|
4222
4251
|
# generates a new random identifier for the current stack item
|
|
4223
|
-
# this is going to be used to identify it
|
|
4252
|
+
# this is going to be used to identify it uniquely
|
|
4224
4253
|
id = str(uuid.uuid4())
|
|
4225
4254
|
|
|
4226
4255
|
# normalizes the currently extracted path by ensuring that it's
|
|
@@ -4259,10 +4288,6 @@ class App(
|
|
|
4259
4288
|
# directly print the complete set of lines in the structure
|
|
4260
4289
|
lines_b = legacy.u("\n").join((line["line"] for line in lines))
|
|
4261
4290
|
|
|
4262
|
-
# runs the template for the path, so that it's possible to better
|
|
4263
|
-
# understand the origin of the path execution
|
|
4264
|
-
path_f = template % (path, lineno, context)
|
|
4265
|
-
|
|
4266
4291
|
# creates the dictionary that contains the complete set of information
|
|
4267
4292
|
# about the current line in the stack and then runs the pipeline of
|
|
4268
4293
|
# operation in it to properly process it
|
appier/http.py
CHANGED
appier/scheduler.py
CHANGED
|
@@ -187,6 +187,14 @@ class SchedulerTask(object):
|
|
|
187
187
|
self.date = SchedulerDate.from_cron(cron)
|
|
188
188
|
self._enabled = True
|
|
189
189
|
|
|
190
|
+
def __eq__(self, other):
|
|
191
|
+
if isinstance(other, self.__class__):
|
|
192
|
+
return True
|
|
193
|
+
return False
|
|
194
|
+
|
|
195
|
+
def __lt__(self, other):
|
|
196
|
+
return False
|
|
197
|
+
|
|
190
198
|
def enable(self):
|
|
191
199
|
self._enabled = True
|
|
192
200
|
|
appier/structures.py
CHANGED
|
@@ -29,6 +29,7 @@ __license__ = "Apache License, Version 2.0"
|
|
|
29
29
|
""" The license for the module """
|
|
30
30
|
|
|
31
31
|
import os
|
|
32
|
+
import collections
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
class OrderedDict(dict):
|
|
@@ -280,5 +281,30 @@ class GeneratorFile(object):
|
|
|
280
281
|
self._generator.close()
|
|
281
282
|
|
|
282
283
|
|
|
284
|
+
class LimitedSizeDict(dict):
|
|
285
|
+
"""
|
|
286
|
+
Size limited dictionary that removes the oldest item
|
|
287
|
+
once the maximum size is reached.
|
|
288
|
+
|
|
289
|
+
Useful for caching purposes where the cache should have
|
|
290
|
+
a limited size and the oldest items should be removed
|
|
291
|
+
once the maximum size is reached, constrains memory usage.
|
|
292
|
+
"""
|
|
293
|
+
|
|
294
|
+
def __init__(self, max_size=128):
|
|
295
|
+
dict.__init__(self)
|
|
296
|
+
self.max_size = max_size
|
|
297
|
+
self._order = collections.deque()
|
|
298
|
+
|
|
299
|
+
def __setitem__(self, key, value):
|
|
300
|
+
if key in self:
|
|
301
|
+
self._order.remove(key)
|
|
302
|
+
elif len(self) >= self.max_size:
|
|
303
|
+
oldest_key = self._order.popleft()
|
|
304
|
+
del self[oldest_key]
|
|
305
|
+
dict.__setitem__(self, key, value)
|
|
306
|
+
self._order.append(key)
|
|
307
|
+
|
|
308
|
+
|
|
283
309
|
lazy_dict = LazyDict
|
|
284
310
|
lazy = LazyValue
|
appier/test/scheduler.py
CHANGED
|
@@ -134,6 +134,33 @@ class CronSchedulerTest(unittest.TestCase):
|
|
|
134
134
|
scheduler.next_run(), datetime.datetime(2013, 4, 10, hour=0, minute=11)
|
|
135
135
|
)
|
|
136
136
|
|
|
137
|
+
def test_duplicate(self):
|
|
138
|
+
state = dict(value=0)
|
|
139
|
+
|
|
140
|
+
def increment():
|
|
141
|
+
state["value"] += 1
|
|
142
|
+
|
|
143
|
+
scheduler = appier.CronScheduler(None)
|
|
144
|
+
task1 = scheduler.schedule(
|
|
145
|
+
lambda: increment(),
|
|
146
|
+
appier.SchedulerDate(minutes=11, days_of_month=10, days_of_week=2),
|
|
147
|
+
now=datetime.datetime(2013, 1, 1, hour=1, minute=1),
|
|
148
|
+
)
|
|
149
|
+
task2 = scheduler.schedule(
|
|
150
|
+
lambda: increment(),
|
|
151
|
+
appier.SchedulerDate(minutes=11, days_of_month=10, days_of_week=2),
|
|
152
|
+
now=datetime.datetime(2013, 1, 1, hour=1, minute=1),
|
|
153
|
+
)
|
|
154
|
+
self.assertNotEqual(task1, None)
|
|
155
|
+
self.assertNotEqual(task2, None)
|
|
156
|
+
self.assertEqual(isinstance(task1, appier.SchedulerTask), True)
|
|
157
|
+
self.assertEqual(isinstance(task2, appier.SchedulerTask), True)
|
|
158
|
+
self.assertEqual(task1.enabled, True)
|
|
159
|
+
self.assertEqual(task2.enabled, True)
|
|
160
|
+
self.assertEqual(
|
|
161
|
+
scheduler.next_run(), datetime.datetime(2013, 4, 10, hour=0, minute=11)
|
|
162
|
+
)
|
|
163
|
+
|
|
137
164
|
|
|
138
165
|
class SchedulerDateTest(unittest.TestCase):
|
|
139
166
|
|
appier/test/structures.py
CHANGED
|
@@ -220,3 +220,41 @@ class LazyDictTest(unittest.TestCase):
|
|
|
220
220
|
self.assertEqual(struct["first"], 1)
|
|
221
221
|
self.assertEqual(isinstance(struct.__getitem__("second", True), int), True)
|
|
222
222
|
self.assertEqual(struct["second"], 2)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
class LimitedSizeDictTest(unittest.TestCase):
|
|
226
|
+
def setUp(self):
|
|
227
|
+
self.dict_size = 1024
|
|
228
|
+
self.limited_dict = appier.LimitedSizeDict(self.dict_size)
|
|
229
|
+
|
|
230
|
+
def test_add_single_item(self):
|
|
231
|
+
self.limited_dict["first"] = "first_value"
|
|
232
|
+
self.assertIn("first", self.limited_dict)
|
|
233
|
+
self.assertEqual(self.limited_dict["first"], "first_value")
|
|
234
|
+
|
|
235
|
+
def test_exceeding_size_limit(self):
|
|
236
|
+
for index in range(self.dict_size + 1):
|
|
237
|
+
self.limited_dict["key_%d" % index] = "value_%d" % index
|
|
238
|
+
self.assertNotIn("key_0", self.limited_dict)
|
|
239
|
+
self.assertIn("key_%d" % self.dict_size, self.limited_dict)
|
|
240
|
+
|
|
241
|
+
def test_maintaining_order(self):
|
|
242
|
+
for index in range(self.dict_size):
|
|
243
|
+
self.limited_dict["key_%d" % index] = "value_%d" % index
|
|
244
|
+
self.limited_dict["new_key"] = "new_value"
|
|
245
|
+
self.assertNotIn("key_0", self.limited_dict)
|
|
246
|
+
self.assertIn("new_key", self.limited_dict)
|
|
247
|
+
self.assertEqual(self.limited_dict["new_key"], "new_value")
|
|
248
|
+
|
|
249
|
+
def test_update_existing_key(self):
|
|
250
|
+
self.limited_dict["first"] = "first_value"
|
|
251
|
+
self.limited_dict["first"] = "second_value"
|
|
252
|
+
self.assertEqual(self.limited_dict["first"], "second_value")
|
|
253
|
+
self.assertEqual(len(self.limited_dict), 1)
|
|
254
|
+
|
|
255
|
+
def test_repr(self):
|
|
256
|
+
self.limited_dict["first"] = "first_value"
|
|
257
|
+
self.limited_dict["second"] = "second_value"
|
|
258
|
+
repr_str = repr(self.limited_dict)
|
|
259
|
+
self.assertIn("'first': 'first_value'", repr_str)
|
|
260
|
+
self.assertIn("'second': 'second_value'", repr_str)
|
appier/util.py
CHANGED
|
@@ -503,7 +503,7 @@ def install_pip(package, delayed=False, isolated=True, user=None):
|
|
|
503
503
|
result = pip_main(args)
|
|
504
504
|
if result == 0:
|
|
505
505
|
return
|
|
506
|
-
raise exceptions.OperationalError(message="pip error")
|
|
506
|
+
raise exceptions.OperationalError(message="pip error, exit code (%d)" % result)
|
|
507
507
|
|
|
508
508
|
|
|
509
509
|
def install_pip_s(package, delayed=False):
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
appier/__init__.py,sha256
|
|
1
|
+
appier/__init__.py,sha256=-Xd1j5egjwXV6yoKAkcPVWIZEnpPK_SJTTmQjDrW93E,9413
|
|
2
2
|
appier/amqp.py,sha256=etYxUlfaK27Og_9FJ6qCgNLSYhnz9XgVhIhSmD2ITW4,3852
|
|
3
3
|
appier/api.py,sha256=s5ZJs0tgR3wktAhLZ7Vuhbd_4lWPsGJSEx0ptkqLxvM,14369
|
|
4
4
|
appier/asgi.py,sha256=sKQH9K_QEDPbBSk3AWcvHo7Lfl5yawIo6NcM0z1qQCw,12100
|
|
@@ -6,7 +6,7 @@ appier/async_neo.py,sha256=gQpyT1-nZE6Uynh5FEmFl5kfXkxChdUsgiKgwlaNw5E,5446
|
|
|
6
6
|
appier/async_old.py,sha256=m3BFqHVPCRuIZ9L2sGYhCQPEwuCNKBO2y7SKM0dbtj8,9194
|
|
7
7
|
appier/asynchronous.py,sha256=a1LQa3wbGMaXELhF7W71dRr1klPOj6x-ST9EInvPhtU,1757
|
|
8
8
|
appier/asynchronous.pyi,sha256=5CpLkpKcUq09woMOVYwpl24Pli0A8Xu6nXoT20xDQ-o,104
|
|
9
|
-
appier/base.py,sha256=
|
|
9
|
+
appier/base.py,sha256=FHxWkZJuWrM4-oyq0vjuL-lFq_nEDfWSrbHbkWwIkzU,270121
|
|
10
10
|
appier/base.pyi,sha256=Vx8idYnMvP3nLwGdd2LJKGc0RFpT6iav77YMcBpcr4o,2515
|
|
11
11
|
appier/bus.py,sha256=AMC2UXlaf6rzhzlIyTHkzbfb6tdfPBiOii4lpl9AAwg,7670
|
|
12
12
|
appier/bus.pyi,sha256=W6_MIBpvDq468wfT5XM2WpPuR3O49QiZMOSCdMsJWos,182
|
|
@@ -31,7 +31,7 @@ appier/extra_old.py,sha256=5mwfHIrz6Um7-QpXiqnEm_lXXpWhNvnMgPWIFVegItU,1991
|
|
|
31
31
|
appier/geo.py,sha256=EEPh8oX7Uk7iert-XKt7HCw0swicc8lFAv7XFeQSbZ8,4877
|
|
32
32
|
appier/git.py,sha256=-neM2mxqlyiCNu17CpLyiz3RN7Ti6LtAx5L1tipxAGA,9785
|
|
33
33
|
appier/graph.py,sha256=jSgu-ookILujLm4ivW14SymVmuI1nbjbVZMgRS2ehOg,4054
|
|
34
|
-
appier/http.py,sha256=
|
|
34
|
+
appier/http.py,sha256=qmQ3FP54oWtunPvQHePtkOS2I9ymLjkqzqoICYhhPVQ,38627
|
|
35
35
|
appier/legacy.py,sha256=o_oJ_2lqZELZKwkvfGt0aDam6ZSZiZiL7FYygNjrDbY,15881
|
|
36
36
|
appier/log.py,sha256=jhV7ub5nZwrLzY7x-tZDJfb8tcsXu-ndWxxrCspBUdU,12825
|
|
37
37
|
appier/meta.py,sha256=rgBLOjD6QU9CGYsbCQS3Fy4iY14uk1-Kd8ljkfmxxzc,7168
|
|
@@ -48,7 +48,7 @@ appier/preferences.pyi,sha256=uYVgvDq2f4KWlLRY-C8bi6xry_utFKDeToGHH5aptxc,197
|
|
|
48
48
|
appier/queuing.py,sha256=6AJlRVdd5JunzChu8Q1U-9Biq4vQUHTuJFC8qs2wzCs,8097
|
|
49
49
|
appier/redisdb.py,sha256=5inJMQqHVkfsGoqoRGYzewlgooDZD2uwOtlPXHX17V0,3504
|
|
50
50
|
appier/request.py,sha256=vNiRdBZXgboMx_d3xkGHlJf3f7ifejgKyhYZ4Pr9GlE,31450
|
|
51
|
-
appier/scheduler.py,sha256=
|
|
51
|
+
appier/scheduler.py,sha256=GMy2izW5I9WdX7N_-WWyl7YLfJnuznxe0GZiTJROnA0,9408
|
|
52
52
|
appier/scheduler.pyi,sha256=JHqH-DSKFZL1uXJTpWFTVHykRT8QRGrVdYCi0nyhjrQ,2132
|
|
53
53
|
appier/serialize.py,sha256=LiR1ZbAiC_I3lhlQToPK_u2DC2r04Gl9OEQTayW4Rlg,6669
|
|
54
54
|
appier/session.py,sha256=6rcwFdsu--7gFLr6mJJh3EFSZ_A3Oe8u7olAvTw2sUk,20380
|
|
@@ -56,9 +56,9 @@ appier/session.pyi,sha256=JBYcT1wZ9mKBBk9iTw2GDJENB8PWFzxXjIr9oXKe85Q,239
|
|
|
56
56
|
appier/settings.py,sha256=28tTRJIZ47iwXqUs6YtUoW7ntEVsp_0-QfONVDGA1sg,1136
|
|
57
57
|
appier/smtp.py,sha256=5tW0dOEm03kejLoQyhRQFjgjYRd-jhb-VlhEKDb4Zn0,3434
|
|
58
58
|
appier/storage.py,sha256=Qp_CMCDg85q35n9lggNVBZRWwlGrQ-nLYNj0W7Mnbec,7470
|
|
59
|
-
appier/structures.py,sha256=
|
|
59
|
+
appier/structures.py,sha256=lwAEiz4k1O4bywGcfHvOvZJusN-lUwcviihR9aZLMtY,8883
|
|
60
60
|
appier/typesf.py,sha256=iby3f-3XayIOu9FgjHS6I9L3UoaJntHtG73eKXgIgFE,36882
|
|
61
|
-
appier/util.py,sha256=
|
|
61
|
+
appier/util.py,sha256=e2682yvqkx8ck6p1RsgoBcCwPHw-QgVfzzTZRYXEBU8,86801
|
|
62
62
|
appier/validation.py,sha256=vxb289skd7RfGEQVmpkQxYb71JdAfLu17QaKOuAAEEQ,22388
|
|
63
63
|
appier/res/static/css/base.css,sha256=J9zLozd57KoslAsrsj2a42glGTObxbkrrckR-W-_f2A,6127
|
|
64
64
|
appier/res/static/images/favicon.ico,sha256=fAL8DLx_0Yl6jwpRG_K6S7g3yXxr9Hyjn3JmqyU8t7U,1150
|
|
@@ -84,16 +84,16 @@ appier/test/part.py,sha256=yHQxg2hdfojJMO2Fs0NLvYTX3uCJ6xwgsD4VaKV04ak,3352
|
|
|
84
84
|
appier/test/preferences.py,sha256=QyqoBddOCAmhkcgUYAJ5RgypqrkGL6x6s6a0jsIwE9w,2890
|
|
85
85
|
appier/test/queuing.py,sha256=Lq7gI5QkZfXPf_MUzmRd6LHHknf9EryF-MauWjDLJn0,5710
|
|
86
86
|
appier/test/request.py,sha256=h3DdvhEMARpYTp7eRcJ3-qLQyG-a8PHqSnWY52BiOeU,8176
|
|
87
|
-
appier/test/scheduler.py,sha256=
|
|
87
|
+
appier/test/scheduler.py,sha256=VlbwpoYYI5hgqlpjcyVcMnSHnLGCCCeMi6kyPD7YxV4,7440
|
|
88
88
|
appier/test/serialize.py,sha256=roX01n86AQfnPxzPVdIjdIUQWC_x0C_HE3hNgF37ci8,2120
|
|
89
89
|
appier/test/session.py,sha256=KdiYLLB5autIEu1sHwOuYJXVd0y6RMPgg0ITBuRTMfA,4419
|
|
90
90
|
appier/test/smtp.py,sha256=XJNa0ZTmabdrX8MfVMgcqBxabvBfHgIimvozdziP4_E,1826
|
|
91
|
-
appier/test/structures.py,sha256=
|
|
91
|
+
appier/test/structures.py,sha256=MRjUFRlnJi-i7YGWW5y792JbJwicNvOIzVAS220tgeQ,8367
|
|
92
92
|
appier/test/typesf.py,sha256=KHumQFzx7wPZSCb8_mpIwobhIy2Fh_0XYviwPjXMbKI,9680
|
|
93
93
|
appier/test/util.py,sha256=SSHuBAZQ0TcXLDYI0xUvmwId5nndDZb88s_5Y-Hqibw,46884
|
|
94
94
|
appier/test/validation.py,sha256=riOCsGKob1P5jnbcB5qGZ45ApimNAVS0byg9v_uUdrk,4952
|
|
95
|
-
appier-1.33.
|
|
96
|
-
appier-1.33.
|
|
97
|
-
appier-1.33.
|
|
98
|
-
appier-1.33.
|
|
99
|
-
appier-1.33.
|
|
95
|
+
appier-1.33.5.dist-info/LICENSE,sha256=Pd-b5cKP4n2tFDpdx27qJSIq0d1ok0oEcGTlbtL6QMU,11560
|
|
96
|
+
appier-1.33.5.dist-info/METADATA,sha256=MXQBzsrHoKyK4i3zHARYd3Zli3mRY16E-FlIzlD8mZU,1920
|
|
97
|
+
appier-1.33.5.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110
|
|
98
|
+
appier-1.33.5.dist-info/top_level.txt,sha256=Z2e_Y1ya06a554WwQZkfNRiaaQxqsdaPtBzrck384Lo,7
|
|
99
|
+
appier-1.33.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|