appier 1.31.4__py2.py3-none-any.whl → 1.32.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.
Files changed (81) hide show
  1. appier/__init__.py +333 -52
  2. appier/amqp.py +29 -30
  3. appier/api.py +214 -212
  4. appier/asgi.py +54 -55
  5. appier/async_neo.py +46 -35
  6. appier/async_old.py +55 -42
  7. appier/asynchronous.py +7 -13
  8. appier/base.py +1762 -1429
  9. appier/bus.py +51 -52
  10. appier/cache.py +99 -84
  11. appier/common.py +9 -11
  12. appier/component.py +17 -19
  13. appier/compress.py +25 -28
  14. appier/config.py +96 -73
  15. appier/controller.py +9 -15
  16. appier/crypt.py +25 -21
  17. appier/data.py +73 -57
  18. appier/defines.py +191 -226
  19. appier/exceptions.py +103 -63
  20. appier/execution.py +94 -88
  21. appier/export.py +90 -88
  22. appier/extra.py +6 -13
  23. appier/extra_neo.py +8 -11
  24. appier/extra_old.py +18 -16
  25. appier/geo.py +57 -47
  26. appier/git.py +101 -90
  27. appier/graph.py +23 -24
  28. appier/http.py +520 -398
  29. appier/legacy.py +373 -180
  30. appier/log.py +90 -97
  31. appier/meta.py +42 -42
  32. appier/mock.py +32 -34
  33. appier/model.py +793 -681
  34. appier/model_a.py +208 -183
  35. appier/mongo.py +183 -107
  36. appier/observer.py +39 -31
  37. appier/part.py +23 -24
  38. appier/preferences.py +44 -47
  39. appier/queuing.py +78 -96
  40. appier/redisdb.py +40 -35
  41. appier/request.py +227 -175
  42. appier/scheduler.py +13 -18
  43. appier/serialize.py +37 -31
  44. appier/session.py +161 -147
  45. appier/settings.py +2 -11
  46. appier/smtp.py +53 -49
  47. appier/storage.py +39 -33
  48. appier/structures.py +50 -45
  49. appier/test/__init__.py +2 -11
  50. appier/test/base.py +111 -108
  51. appier/test/cache.py +28 -35
  52. appier/test/config.py +10 -19
  53. appier/test/crypt.py +3 -12
  54. appier/test/data.py +3 -12
  55. appier/test/exceptions.py +8 -17
  56. appier/test/export.py +16 -33
  57. appier/test/graph.py +27 -60
  58. appier/test/http.py +42 -54
  59. appier/test/legacy.py +20 -30
  60. appier/test/log.py +14 -35
  61. appier/test/mock.py +27 -123
  62. appier/test/model.py +79 -91
  63. appier/test/part.py +5 -14
  64. appier/test/preferences.py +5 -13
  65. appier/test/queuing.py +29 -37
  66. appier/test/request.py +61 -73
  67. appier/test/serialize.py +12 -23
  68. appier/test/session.py +10 -19
  69. appier/test/smtp.py +8 -14
  70. appier/test/structures.py +20 -24
  71. appier/test/typesf.py +14 -28
  72. appier/test/util.py +480 -438
  73. appier/typesf.py +251 -171
  74. appier/util.py +578 -407
  75. appier/validation.py +280 -143
  76. {appier-1.31.4.dist-info → appier-1.32.0.dist-info}/METADATA +6 -1
  77. appier-1.32.0.dist-info/RECORD +86 -0
  78. appier-1.31.4.dist-info/RECORD +0 -86
  79. {appier-1.31.4.dist-info → appier-1.32.0.dist-info}/LICENSE +0 -0
  80. {appier-1.31.4.dist-info → appier-1.32.0.dist-info}/WHEEL +0 -0
  81. {appier-1.31.4.dist-info → appier-1.32.0.dist-info}/top_level.txt +0 -0
appier/log.py CHANGED
@@ -2,7 +2,7 @@
2
2
  # -*- coding: utf-8 -*-
3
3
 
4
4
  # Hive Appier Framework
5
- # Copyright (c) 2008-2022 Hive Solutions Lda.
5
+ # Copyright (c) 2008-2024 Hive Solutions Lda.
6
6
  #
7
7
  # This file is part of Hive Appier Framework.
8
8
  #
@@ -22,16 +22,7 @@
22
22
  __author__ = "João Magalhães <joamag@hive.pt>"
23
23
  """ The author(s) of the module """
24
24
 
25
- __version__ = "1.0.0"
26
- """ The version of the module """
27
-
28
- __revision__ = "$LastChangedRevision$"
29
- """ The revision number of the module """
30
-
31
- __date__ = "$LastChangedDate$"
32
- """ The last change date of the module """
33
-
34
- __copyright__ = "Copyright (c) 2008-2022 Hive Solutions Lda."
25
+ __copyright__ = "Copyright (c) 2008-2024 Hive Solutions Lda."
35
26
  """ The copyright for the module """
36
27
 
37
28
  __license__ = "Apache License, Version 2.0"
@@ -61,12 +52,12 @@ multiple stream handlers, this version of the string
61
52
  includes the thread identification number and should be
62
53
  used for messages called from outside the main thread """
63
54
 
64
- LOGGING_EXTRA = "[%(name)s] " if config.conf("LOGGING_EXTRA", cast = bool) else ""
55
+ LOGGING_EXTRA = "[%(name)s] " if config.conf("LOGGING_EXTRA", cast=bool) else ""
65
56
  """ The extra logging attributes that are going to be applied
66
57
  to the format strings to obtain the final on the logging """
67
58
 
68
- LOGGIGN_SYSLOG = "1 %%(asctime)s %%(hostname)s %s %%(process)d %%(thread)d \
69
- [appierSDID@0 tid=\"%%(thread)d\"] %%(json)s"
59
+ LOGGIGN_SYSLOG = '1 %%(asctime)s %%(hostname)s %s %%(process)d %%(thread)d \
60
+ [appierSDID@0 tid="%%(thread)d"] %%(json)s'
70
61
  """ The format to be used for the message sent using the syslog
71
62
  logger, should contain extra structured data """
72
63
 
@@ -81,34 +72,29 @@ SILENT = logging.CRITICAL + 1
81
72
  or an handler, this is used as an utility for debugging
82
73
  purposes more that a real feature for production systems """
83
74
 
84
- LEVELS = (
85
- "DEBUG",
86
- "INFO",
87
- "WARNING",
88
- "ERROR",
89
- "CRITICAL"
90
- )
75
+ LEVELS = ("DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL")
91
76
  """ The sequence of levels from the least sever to the
92
77
  most sever this sequence may be used to find all the
93
78
  levels that are considered more sever that a level """
94
79
 
95
80
  LEVEL_ALIAS = {
96
- "DEBU" : "DEBUG",
97
- "WARN" : "WARNING",
98
- "INF" : "INFO",
99
- "ERR" : "ERROR",
100
- "CRIT" : "CRITICAL"
81
+ "DEBU": "DEBUG",
82
+ "WARN": "WARNING",
83
+ "INF": "INFO",
84
+ "ERR": "ERROR",
85
+ "CRIT": "CRITICAL",
101
86
  }
102
87
  """ Map defining a series of alias that may be used latter
103
88
  for proper debug level resolution """
104
89
 
105
- SYSLOG_PORTS = dict(tcp = 601, udp = 514)
90
+ SYSLOG_PORTS = dict(tcp=601, udp=514)
106
91
  """ Dictionary that maps the multiple transport protocol
107
92
  used by syslog with the appropriate default ports """
108
93
 
109
94
  LOGGING_FORMAT = LOGGING_FORMAT_T % LOGGING_EXTRA
110
95
  LOGGING_FORMAT_TID = LOGGING_FORMAT_TID_T % LOGGING_EXTRA
111
96
 
97
+
112
98
  class MemoryHandler(logging.Handler):
113
99
  """
114
100
  Logging handler that is used to store information in
@@ -116,8 +102,8 @@ class MemoryHandler(logging.Handler):
116
102
  long as the execution session is the same.
117
103
  """
118
104
 
119
- def __init__(self, level = logging.NOTSET, max_length = MAX_LENGTH):
120
- logging.Handler.__init__(self, level = level)
105
+ def __init__(self, level=logging.NOTSET, max_length=MAX_LENGTH):
106
+ logging.Handler.__init__(self, level=level)
121
107
  self.max_length = max_length
122
108
  self.messages = collections.deque()
123
109
  self.messages_l = dict()
@@ -133,12 +119,14 @@ class MemoryHandler(logging.Handler):
133
119
  def get_messages_l(self, level):
134
120
  # in case the level is not found in the list of levels
135
121
  # it's not considered valid and so an empty list is returned
136
- try: index = LEVELS.index(level)
137
- except Exception: return collections.deque()
122
+ try:
123
+ index = LEVELS.index(level)
124
+ except Exception:
125
+ return collections.deque()
138
126
 
139
127
  # retrieves the complete set of levels that are considered
140
128
  # equal or more severe than the requested one
141
- levels = LEVELS[:index + 1]
129
+ levels = LEVELS[: index + 1]
142
130
 
143
131
  # creates the list that will hold the various message
144
132
  # lists associated with the current severity level
@@ -149,7 +137,8 @@ class MemoryHandler(logging.Handler):
149
137
  # list to the list of message lists
150
138
  for level in levels:
151
139
  _messages_l = self.messages_l.get(level, None)
152
- if _messages_l == None: _messages_l = collections.deque()
140
+ if _messages_l == None:
141
+ _messages_l = collections.deque()
153
142
  self.messages_l[level] = _messages_l
154
143
  messages_l.append(_messages_l)
155
144
 
@@ -175,7 +164,8 @@ class MemoryHandler(logging.Handler):
175
164
  # the one defined as maximum must pop message from queue
176
165
  self.messages.appendleft(message)
177
166
  messages_s = len(self.messages)
178
- if messages_s > self.max_length: self.messages.pop()
167
+ if messages_s > self.max_length:
168
+ self.messages.pop()
179
169
 
180
170
  # iterates over all the messages list included in the retrieve
181
171
  # messages list to add the logging message to each of them
@@ -185,42 +175,42 @@ class MemoryHandler(logging.Handler):
185
175
  # specified also for the more general queue
186
176
  _messages_l.appendleft(message)
187
177
  messages_s = len(_messages_l)
188
- if messages_s > self.max_length: _messages_l.pop()
178
+ if messages_s > self.max_length:
179
+ _messages_l.pop()
189
180
 
190
181
  def clear(self):
191
182
  self.messages = collections.deque()
192
183
  self.messages_l = dict()
193
184
 
194
- def get_latest(self, count = None, level = None):
185
+ def get_latest(self, count=None, level=None):
195
186
  count = count or 100
196
187
  is_level = level and not legacy.is_string(level)
197
- if is_level: level = logging.getLevelName(level)
188
+ if is_level:
189
+ level = logging.getLevelName(level)
198
190
  level = level.upper() if level else level
199
191
  level = LEVEL_ALIAS.get(level, level)
200
192
  messages = self.messages_l.get(level, []) if level else self.messages
201
193
  slice = itertools.islice(messages, 0, count)
202
194
  return list(slice)
203
195
 
204
- def flush_to_file(
205
- self,
206
- path,
207
- count = None,
208
- level = None,
209
- reverse = True,
210
- clear = True
211
- ):
212
- messages = self.get_latest(level = level, count = count or 65536)
213
- if not messages: return
214
- if reverse: messages.reverse()
196
+ def flush_to_file(self, path, count=None, level=None, reverse=True, clear=True):
197
+ messages = self.get_latest(level=level, count=count or 65536)
198
+ if not messages:
199
+ return
200
+ if reverse:
201
+ messages.reverse()
215
202
  is_path = isinstance(path, legacy.STRINGS)
216
203
  file = open(path, "wb") if is_path else path
217
204
  try:
218
205
  for message in messages:
219
- message = legacy.bytes(message, "utf-8", force = True)
206
+ message = legacy.bytes(message, "utf-8", force=True)
220
207
  file.write(message + b"\n")
221
208
  finally:
222
- if is_path: file.close()
223
- if clear: self.clear()
209
+ if is_path:
210
+ file.close()
211
+ if clear:
212
+ self.clear()
213
+
224
214
 
225
215
  class BaseFormatter(logging.Formatter):
226
216
  """
@@ -237,19 +227,20 @@ class BaseFormatter(logging.Formatter):
237
227
 
238
228
  @classmethod
239
229
  def _wrap_record(cls, record):
240
- if hasattr(record, "_wrapped"): return
230
+ if hasattr(record, "_wrapped"):
231
+ return
241
232
  record.hostname = socket.gethostname()
242
233
  record.json = json.dumps(
243
234
  dict(
244
- message = str(record.msg),
245
- hostname = record.hostname,
246
- lineno = record.lineno,
247
- module = record.module,
248
- callable = record.funcName,
249
- level = record.levelname,
250
- thread = record.thread,
251
- process = record.process,
252
- logger = record.name
235
+ message=str(record.msg),
236
+ hostname=record.hostname,
237
+ lineno=record.lineno,
238
+ module=record.module,
239
+ callable=record.funcName,
240
+ level=record.levelname,
241
+ thread=record.thread,
242
+ process=record.process,
243
+ logger=record.name,
253
244
  )
254
245
  )
255
246
  record._wrapped = True
@@ -257,12 +248,14 @@ class BaseFormatter(logging.Formatter):
257
248
  def format(self, record):
258
249
  # runs the wrapping operation on the record so that more
259
250
  # information becomes available in it (as expected)
260
- if self._wrap: self.__class__._wrap_record(record)
251
+ if self._wrap:
252
+ self.__class__._wrap_record(record)
261
253
 
262
254
  # runs the basic format operation on the record so that
263
255
  # it gets properly formatted into a plain string
264
256
  return logging.Formatter.format(self, record)
265
257
 
258
+
266
259
  class ThreadFormatter(BaseFormatter):
267
260
  """
268
261
  Custom formatter class that changing the default format
@@ -278,14 +271,16 @@ class ThreadFormatter(BaseFormatter):
278
271
  def format(self, record):
279
272
  # runs the wrapping operation on the record so that more
280
273
  # information becomes available in it (as expected)
281
- if self._wrap: self.__class__._wrap_record(record)
274
+ if self._wrap:
275
+ self.__class__._wrap_record(record)
282
276
 
283
277
  # retrieves the reference to the current thread and verifies
284
278
  # if it represent the current process main thread, then selects
285
279
  # the appropriate formating string taking that into account
286
280
  current = threading.current_thread()
287
281
  is_main = current.name == "MainThread"
288
- if not is_main: return self._tidfmt.format(record)
282
+ if not is_main:
283
+ return self._tidfmt.format(record)
289
284
  return self._basefmt.format(record)
290
285
 
291
286
  def set_base(self, value, *args, **kwargs):
@@ -294,8 +289,8 @@ class ThreadFormatter(BaseFormatter):
294
289
  def set_tid(self, value, *args, **kwargs):
295
290
  self._tidfmt = BaseFormatter(value, *args, **kwargs)
296
291
 
297
- class DummyLogger(object):
298
292
 
293
+ class DummyLogger(object):
299
294
  def debug(self, object):
300
295
  pass
301
296
 
@@ -311,61 +306,59 @@ class DummyLogger(object):
311
306
  def critical(self, object):
312
307
  pass
313
308
 
314
- def reload_format(app = None):
309
+
310
+ def reload_format(app=None):
315
311
  global LOGGING_FORMAT
316
312
  global LOGGING_FORMAT_TID
317
313
 
318
314
  app = app or common.base().get_app()
319
315
 
320
316
  extra = LOGGING_EXTRA
321
- if app and not app.is_parent(): extra = "[%(process)d] " + extra
317
+ if app and not app.is_parent():
318
+ extra = "[%(process)d] " + extra
322
319
 
323
320
  LOGGING_FORMAT = LOGGING_FORMAT_T % extra
324
321
  LOGGING_FORMAT_TID = LOGGING_FORMAT_TID_T % extra
325
322
 
323
+
326
324
  def rotating_handler(
327
- path = "appier.log",
328
- max_bytes = 1048576,
329
- max_log = 5,
330
- encoding = None,
331
- delay = False
325
+ path="appier.log", max_bytes=1048576, max_log=5, encoding=None, delay=False
332
326
  ):
333
327
  return logging.handlers.RotatingFileHandler(
334
- path,
335
- maxBytes = max_bytes,
336
- backupCount = max_log,
337
- encoding = encoding,
338
- delay = delay
328
+ path, maxBytes=max_bytes, backupCount=max_log, encoding=encoding, delay=delay
339
329
  )
340
330
 
331
+
341
332
  def smtp_handler(
342
- host = "localhost",
343
- port = 25,
344
- sender = "no-reply@appier.com",
345
- receivers = [],
346
- subject = "Appier logging",
347
- username = None,
348
- password = None,
349
- stls = False
333
+ host="localhost",
334
+ port=25,
335
+ sender="no-reply@appier.com",
336
+ receivers=[],
337
+ subject="Appier logging",
338
+ username=None,
339
+ password=None,
340
+ stls=False,
350
341
  ):
351
342
  address = (host, port)
352
- if username and password: credentials = (username, password)
353
- else: credentials = None
343
+ if username and password:
344
+ credentials = (username, password)
345
+ else:
346
+ credentials = None
354
347
  has_secure = in_signature(logging.handlers.SMTPHandler.__init__, "secure")
355
- if has_secure: kwargs = dict(secure = () if stls else None)
356
- else: kwargs = dict()
348
+ if has_secure:
349
+ kwargs = dict(secure=() if stls else None)
350
+ else:
351
+ kwargs = dict()
357
352
  return logging.handlers.SMTPHandler(
358
- address,
359
- sender,
360
- receivers,
361
- subject,
362
- credentials = credentials,
363
- **kwargs
353
+ address, sender, receivers, subject, credentials=credentials, **kwargs
364
354
  )
365
355
 
356
+
366
357
  def in_signature(callable, name):
367
358
  has_full = hasattr(inspect, "getfullargspec")
368
- if has_full: spec = inspect.getfullargspec(callable)
369
- else: spec = inspect.getargspec(callable)
359
+ if has_full:
360
+ spec = inspect.getfullargspec(callable)
361
+ else:
362
+ spec = inspect.getargspec(callable)
370
363
  args, _varargs, kwargs = spec[:3]
371
364
  return (args and name in args) or (kwargs and "secure" in kwargs)
appier/meta.py CHANGED
@@ -2,7 +2,7 @@
2
2
  # -*- coding: utf-8 -*-
3
3
 
4
4
  # Hive Appier Framework
5
- # Copyright (c) 2008-2022 Hive Solutions Lda.
5
+ # Copyright (c) 2008-2024 Hive Solutions Lda.
6
6
  #
7
7
  # This file is part of Hive Appier Framework.
8
8
  #
@@ -22,16 +22,7 @@
22
22
  __author__ = "João Magalhães <joamag@hive.pt>"
23
23
  """ The author(s) of the module """
24
24
 
25
- __version__ = "1.0.0"
26
- """ The version of the module """
27
-
28
- __revision__ = "$LastChangedRevision$"
29
- """ The revision number of the module """
30
-
31
- __date__ = "$LastChangedDate$"
32
- """ The last change date of the module """
33
-
34
- __copyright__ = "Copyright (c) 2008-2022 Hive Solutions Lda."
25
+ __copyright__ = "Copyright (c) 2008-2024 Hive Solutions Lda."
35
26
  """ The copyright for the module """
36
27
 
37
28
  __license__ = "Apache License, Version 2.0"
@@ -40,6 +31,7 @@ __license__ = "Apache License, Version 2.0"
40
31
  from . import common
41
32
  from . import legacy
42
33
 
34
+
43
35
  class Ordered(type):
44
36
  """
45
37
  Metaclass to be used for classes where the
@@ -49,9 +41,12 @@ class Ordered(type):
49
41
 
50
42
  def __new__(cls, name, bases, attrs):
51
43
  new_cls = super(Ordered, cls).__new__(cls, name, bases, attrs)
52
- new_cls._ordered = [(name, attrs.pop(name)) for name, value in\
53
- legacy.eager(attrs.items()) if hasattr(value, "creation_counter")]
54
- new_cls._ordered.sort(key = lambda item: item[1].creation_counter)
44
+ new_cls._ordered = [
45
+ (name, attrs.pop(name))
46
+ for name, value in legacy.eager(attrs.items())
47
+ if hasattr(value, "creation_counter")
48
+ ]
49
+ new_cls._ordered.sort(key=lambda item: item[1].creation_counter)
55
50
  new_cls._ordered = [name for name, value in new_cls._ordered]
56
51
  return new_cls
57
52
 
@@ -59,11 +54,12 @@ class Ordered(type):
59
54
  super(Ordered, cls).__init__(name, bases, attrs)
60
55
 
61
56
  def __cmp__(self, value):
62
- return cmp(self.__name__, value.__name__) #@UndefinedVariable
57
+ return cmp(self.__name__, value.__name__) # @UndefinedVariable
63
58
 
64
59
  def __lt__(self, value):
65
60
  return self.__name__.__lt__(value.__name__)
66
61
 
62
+
67
63
  class Indexed(type):
68
64
  """
69
65
  Meta class data type for the indexing of the various route
@@ -78,21 +74,26 @@ class Indexed(type):
78
74
  # retrieves the complete set of elements in the current set of attributes
79
75
  # that are marked with the "creation counter" and then sorts these same
80
76
  # elements according to that value (sorting by order of definition)
81
- ordered = [(name, attrs.pop(name)) for name, value in\
82
- legacy.eager(attrs.items()) if hasattr(value, "creation_counter")]
83
- ordered.sort(key = lambda item: item[1].creation_counter)
77
+ ordered = [
78
+ (name, attrs.pop(name))
79
+ for name, value in legacy.eager(attrs.items())
80
+ if hasattr(value, "creation_counter")
81
+ ]
82
+ ordered.sort(key=lambda item: item[1].creation_counter)
84
83
 
85
84
  # in case there's no ordered related values there's nothing remaining
86
85
  # to be done under this class creation and so the created class must
87
86
  # be returned immediately to the caller method
88
- if not ordered: return new_cls
87
+ if not ordered:
88
+ return new_cls
89
89
 
90
90
  # retrieves the reference to the current global application instance
91
91
  # and verifies if the global (cache) base registered value is defined
92
92
  # in case it's not defines it as it's going to be used to avoid the
93
93
  # duplicated registration of routes
94
94
  app = common.base().App
95
- if not hasattr(app, "_BASE_REGISTERED"): app._BASE_REGISTERED = []
95
+ if not hasattr(app, "_BASE_REGISTERED"):
96
+ app._BASE_REGISTERED = []
96
97
  registered = app._BASE_REGISTERED
97
98
 
98
99
  # iterates over the complete set of ordered elements to be able to
@@ -102,7 +103,9 @@ class Indexed(type):
102
103
  # to be able to register each of them properly
103
104
  routes = function._routes if hasattr(function, "_routes") else []
104
105
  errors = function._errors if hasattr(function, "_errors") else []
105
- exceptions = function._exceptions if hasattr(function, "_exceptions") else []
106
+ exceptions = (
107
+ function._exceptions if hasattr(function, "_exceptions") else []
108
+ )
106
109
  customs = function._customs if hasattr(function, "_customs") else []
107
110
 
108
111
  # iterates over the complete set of routes associated with the current
@@ -121,7 +124,8 @@ class Indexed(type):
121
124
  # that's the situation continues the loop to be able to
122
125
  # avoid duplicated route registration (possible with imports)
123
126
  route_t = (method, url)
124
- if route_t in registered: continue
127
+ if route_t in registered:
128
+ continue
125
129
  registered.append(route_t)
126
130
 
127
131
  # adds the new route to the application using the provided/unpacked
@@ -130,11 +134,11 @@ class Indexed(type):
130
134
  method,
131
135
  url,
132
136
  function,
133
- asynchronous = asynchronous,
134
- json = json,
135
- opts = opts,
136
- context = new_name,
137
- priority = priority
137
+ asynchronous=asynchronous,
138
+ json=json,
139
+ opts=opts,
140
+ context=new_name,
141
+ priority=priority,
138
142
  )
139
143
 
140
144
  for error in errors:
@@ -142,11 +146,11 @@ class Indexed(type):
142
146
  app.add_error(
143
147
  code,
144
148
  function,
145
- scope = scope,
146
- json = json,
147
- opts = opts,
148
- context = new_name,
149
- priority = priority
149
+ scope=scope,
150
+ json=json,
151
+ opts=opts,
152
+ context=new_name,
153
+ priority=priority,
150
154
  )
151
155
 
152
156
  for exception in exceptions:
@@ -154,21 +158,17 @@ class Indexed(type):
154
158
  app.add_exception(
155
159
  exception,
156
160
  function,
157
- scope = scope,
158
- json = json,
159
- opts = opts,
160
- context = new_name,
161
- priority = priority
161
+ scope=scope,
162
+ json=json,
163
+ opts=opts,
164
+ context=new_name,
165
+ priority=priority,
162
166
  )
163
167
 
164
168
  for custom in customs:
165
169
  key, opts, priority = custom
166
170
  app.add_custom(
167
- key,
168
- function,
169
- opts = opts,
170
- context = new_name,
171
- priority = priority
171
+ key, function, opts=opts, context=new_name, priority=priority
172
172
  )
173
173
 
174
174
  return new_cls
appier/mock.py CHANGED
@@ -2,7 +2,7 @@
2
2
  # -*- coding: utf-8 -*-
3
3
 
4
4
  # Hive Appier Framework
5
- # Copyright (c) 2008-2022 Hive Solutions Lda.
5
+ # Copyright (c) 2008-2024 Hive Solutions Lda.
6
6
  #
7
7
  # This file is part of Hive Appier Framework.
8
8
  #
@@ -22,16 +22,7 @@
22
22
  __author__ = "João Magalhães <joamag@hive.pt>"
23
23
  """ The author(s) of the module """
24
24
 
25
- __version__ = "1.0.0"
26
- """ The version of the module """
27
-
28
- __revision__ = "$LastChangedRevision$"
29
- """ The revision number of the module """
30
-
31
- __date__ = "$LastChangedDate$"
32
- """ The last change date of the module """
33
-
34
- __copyright__ = "Copyright (c) 2008-2022 Hive Solutions Lda."
25
+ __copyright__ = "Copyright (c) 2008-2024 Hive Solutions Lda."
35
26
  """ The copyright for the module """
36
27
 
37
28
  __license__ = "Apache License, Version 2.0"
@@ -40,16 +31,18 @@ __license__ = "Apache License, Version 2.0"
40
31
  from . import util
41
32
  from . import legacy
42
33
 
43
- class MockObject(object):
44
34
 
35
+ class MockObject(object):
45
36
  def __init__(self, *args, **kwargs):
46
37
  self.model = kwargs
47
38
 
48
39
  def __getattribute__(self, name):
49
40
  try:
50
41
  model = object.__getattribute__(self, "model")
51
- if name in model: return model[name]
52
- except AttributeError: pass
42
+ if name in model:
43
+ return model[name]
44
+ except AttributeError:
45
+ pass
53
46
  return object.__getattribute__(self, name)
54
47
 
55
48
  def __getitem__(self, key):
@@ -61,8 +54,8 @@ class MockObject(object):
61
54
  def __delitem__(self, key):
62
55
  self.model.__delitem__(key)
63
56
 
64
- class MockResponse(MockObject):
65
57
 
58
+ class MockResponse(MockObject):
66
59
  def read(self):
67
60
  return self.data
68
61
 
@@ -78,8 +71,8 @@ class MockResponse(MockObject):
78
71
  def info(self):
79
72
  return self.headers
80
73
 
81
- class MockApp(object):
82
74
 
75
+ class MockApp(object):
83
76
  def get(self, *args, **kwargs):
84
77
  return self.method("GET", *args, **kwargs)
85
78
 
@@ -102,11 +95,11 @@ class MockApp(object):
102
95
  self,
103
96
  method,
104
97
  location,
105
- query = "",
106
- data = b"",
107
- scheme = "http",
108
- address = "127.0.0.1",
109
- headers = {}
98
+ query="",
99
+ data=b"",
100
+ scheme="http",
101
+ address="127.0.0.1",
102
+ headers={},
110
103
  ):
111
104
  # creates the dictionary that is going to hold the (initial)
112
105
  # response structure and the "encapsulates" the provided data
@@ -116,33 +109,37 @@ class MockApp(object):
116
109
 
117
110
  # verifies if the location contains a query part (question mark)
118
111
  # and if that's the case splits the location in the two parts
119
- if "?" in location: location, query = location.split("?", 1)
112
+ if "?" in location:
113
+ location, query = location.split("?", 1)
120
114
 
121
115
  # builds the map that is going to be used as the basis for the
122
116
  # construction of the request, this map should be compliant with
123
117
  # the WSGI standard and expectancy
124
118
  environ = {
125
- "REQUEST_METHOD" : method,
126
- "PATH_INFO" : location,
127
- "QUERY_STRING" : query,
128
- "SCRIPT_NAME" : location,
129
- "CONTENT_LENGTH" : len(data),
130
- "REMOTE_ADDR" : address,
131
- "wsgi.input" : input,
132
- "wsgi.url_scheme" : scheme
119
+ "REQUEST_METHOD": method,
120
+ "PATH_INFO": location,
121
+ "QUERY_STRING": query,
122
+ "SCRIPT_NAME": location,
123
+ "CONTENT_LENGTH": len(data),
124
+ "REMOTE_ADDR": address,
125
+ "wsgi.input": input,
126
+ "wsgi.url_scheme": scheme,
133
127
  }
134
128
 
135
129
  # iterates over the complete set of provided header value to set
136
130
  # them with the proper HTTP_ prefix in the environment map
137
- for name, value in headers: environ["HTTP_" + name.upper()] = value
131
+ for name, value in headers:
132
+ environ["HTTP_" + name.upper()] = value
138
133
 
139
134
  def start_response(code, headers):
140
135
  # splits the provided code string into its component
141
136
  # verifying defaulting the status of the code to an
142
137
  # empty string in case none is defined (only code)
143
138
  code_s = code.split(" ", 1)
144
- if len(code_s) == 1: code, status = code_s[0], ""
145
- else: code, status = code_s
139
+ if len(code_s) == 1:
140
+ code, status = code_s[0], ""
141
+ else:
142
+ code, status = code_s
146
143
 
147
144
  # converts the code into the integer representation
148
145
  # so that its type is coherent with specification
@@ -164,6 +161,7 @@ class MockApp(object):
164
161
  # "safe" context that replaces the current application's context
165
162
  # in a proper way so that at the end of the call it's properly
166
163
  # restored as expected by a possible control flow
167
- with util.ctx_request(self): result = self.application(environ, start_response)
164
+ with util.ctx_request(self):
165
+ result = self.application(environ, start_response)
168
166
  response["data"] = b"".join(result)
169
167
  return MockResponse(**response)