appier 1.33.1__tar.gz → 1.33.3__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.
Files changed (104) hide show
  1. {appier-1.33.1/src/appier.egg-info → appier-1.33.3}/PKG-INFO +1 -1
  2. {appier-1.33.1 → appier-1.33.3}/setup.py +2 -1
  3. appier-1.33.3/src/appier/asynchronous.pyi +3 -0
  4. {appier-1.33.1 → appier-1.33.3}/src/appier/base.py +13 -8
  5. appier-1.33.3/src/appier/base.pyi +85 -0
  6. appier-1.33.3/src/appier/bus.pyi +8 -0
  7. appier-1.33.3/src/appier/cache.pyi +7 -0
  8. appier-1.33.3/src/appier/component.pyi +1 -0
  9. {appier-1.33.1 → appier-1.33.3}/src/appier/config.py +49 -0
  10. appier-1.33.3/src/appier/data.pyi +6 -0
  11. {appier-1.33.1 → appier-1.33.3}/src/appier/legacy.py +1 -1
  12. {appier-1.33.1 → appier-1.33.3}/src/appier/log.py +1 -0
  13. {appier-1.33.1 → appier-1.33.3}/src/appier/model.py +8 -6
  14. appier-1.33.3/src/appier/model.pyi +48 -0
  15. appier-1.33.3/src/appier/part.pyi +1 -0
  16. appier-1.33.3/src/appier/preferences.pyi +6 -0
  17. appier-1.33.3/src/appier/scheduler.pyi +70 -0
  18. appier-1.33.3/src/appier/session.pyi +7 -0
  19. {appier-1.33.1 → appier-1.33.3}/src/appier/test/config.py +36 -0
  20. {appier-1.33.1 → appier-1.33.3/src/appier.egg-info}/PKG-INFO +1 -1
  21. {appier-1.33.1 → appier-1.33.3}/src/appier.egg-info/SOURCES.txt +11 -0
  22. {appier-1.33.1 → appier-1.33.3}/MANIFEST.in +0 -0
  23. {appier-1.33.1 → appier-1.33.3}/README.rst +0 -0
  24. {appier-1.33.1 → appier-1.33.3}/setup.cfg +0 -0
  25. {appier-1.33.1 → appier-1.33.3}/src/appier/__init__.py +0 -0
  26. {appier-1.33.1 → appier-1.33.3}/src/appier/amqp.py +0 -0
  27. {appier-1.33.1 → appier-1.33.3}/src/appier/api.py +0 -0
  28. {appier-1.33.1 → appier-1.33.3}/src/appier/asgi.py +0 -0
  29. {appier-1.33.1 → appier-1.33.3}/src/appier/async_neo.py +0 -0
  30. {appier-1.33.1 → appier-1.33.3}/src/appier/async_old.py +0 -0
  31. {appier-1.33.1 → appier-1.33.3}/src/appier/asynchronous.py +0 -0
  32. {appier-1.33.1 → appier-1.33.3}/src/appier/bus.py +0 -0
  33. {appier-1.33.1 → appier-1.33.3}/src/appier/cache.py +0 -0
  34. {appier-1.33.1 → appier-1.33.3}/src/appier/common.py +0 -0
  35. {appier-1.33.1 → appier-1.33.3}/src/appier/component.py +0 -0
  36. {appier-1.33.1 → appier-1.33.3}/src/appier/compress.py +0 -0
  37. {appier-1.33.1 → appier-1.33.3}/src/appier/controller.py +0 -0
  38. {appier-1.33.1 → appier-1.33.3}/src/appier/crypt.py +0 -0
  39. {appier-1.33.1 → appier-1.33.3}/src/appier/data.py +0 -0
  40. {appier-1.33.1 → appier-1.33.3}/src/appier/defines.py +0 -0
  41. {appier-1.33.1 → appier-1.33.3}/src/appier/exceptions.py +0 -0
  42. {appier-1.33.1 → appier-1.33.3}/src/appier/execution.py +0 -0
  43. {appier-1.33.1 → appier-1.33.3}/src/appier/export.py +0 -0
  44. {appier-1.33.1 → appier-1.33.3}/src/appier/extra.py +0 -0
  45. {appier-1.33.1 → appier-1.33.3}/src/appier/extra_neo.py +0 -0
  46. {appier-1.33.1 → appier-1.33.3}/src/appier/extra_old.py +0 -0
  47. {appier-1.33.1 → appier-1.33.3}/src/appier/geo.py +0 -0
  48. {appier-1.33.1 → appier-1.33.3}/src/appier/git.py +0 -0
  49. {appier-1.33.1 → appier-1.33.3}/src/appier/graph.py +0 -0
  50. {appier-1.33.1 → appier-1.33.3}/src/appier/http.py +0 -0
  51. {appier-1.33.1 → appier-1.33.3}/src/appier/meta.py +0 -0
  52. {appier-1.33.1 → appier-1.33.3}/src/appier/mock.py +0 -0
  53. {appier-1.33.1 → appier-1.33.3}/src/appier/model_a.py +0 -0
  54. {appier-1.33.1 → appier-1.33.3}/src/appier/mongo.py +0 -0
  55. {appier-1.33.1 → appier-1.33.3}/src/appier/observer.py +0 -0
  56. {appier-1.33.1 → appier-1.33.3}/src/appier/part.py +0 -0
  57. {appier-1.33.1 → appier-1.33.3}/src/appier/preferences.py +0 -0
  58. {appier-1.33.1 → appier-1.33.3}/src/appier/queuing.py +0 -0
  59. {appier-1.33.1 → appier-1.33.3}/src/appier/redisdb.py +0 -0
  60. {appier-1.33.1 → appier-1.33.3}/src/appier/request.py +0 -0
  61. {appier-1.33.1 → appier-1.33.3}/src/appier/res/static/css/base.css +0 -0
  62. {appier-1.33.1 → appier-1.33.3}/src/appier/res/static/images/favicon.ico +0 -0
  63. {appier-1.33.1 → appier-1.33.3}/src/appier/res/static/js/base.js +0 -0
  64. {appier-1.33.1 → appier-1.33.3}/src/appier/res/templates/error.html.tpl +0 -0
  65. {appier-1.33.1 → appier-1.33.3}/src/appier/res/templates/holder.html.tpl +0 -0
  66. {appier-1.33.1 → appier-1.33.3}/src/appier/res/templates/layout.html.tpl +0 -0
  67. {appier-1.33.1 → appier-1.33.3}/src/appier/scheduler.py +0 -0
  68. {appier-1.33.1 → appier-1.33.3}/src/appier/serialize.py +0 -0
  69. {appier-1.33.1 → appier-1.33.3}/src/appier/session.py +0 -0
  70. {appier-1.33.1 → appier-1.33.3}/src/appier/settings.py +0 -0
  71. {appier-1.33.1 → appier-1.33.3}/src/appier/smtp.py +0 -0
  72. {appier-1.33.1 → appier-1.33.3}/src/appier/storage.py +0 -0
  73. {appier-1.33.1 → appier-1.33.3}/src/appier/structures.py +0 -0
  74. {appier-1.33.1 → appier-1.33.3}/src/appier/test/__init__.py +0 -0
  75. {appier-1.33.1 → appier-1.33.3}/src/appier/test/base.py +0 -0
  76. {appier-1.33.1 → appier-1.33.3}/src/appier/test/cache.py +0 -0
  77. {appier-1.33.1 → appier-1.33.3}/src/appier/test/crypt.py +0 -0
  78. {appier-1.33.1 → appier-1.33.3}/src/appier/test/data.py +0 -0
  79. {appier-1.33.1 → appier-1.33.3}/src/appier/test/exceptions.py +0 -0
  80. {appier-1.33.1 → appier-1.33.3}/src/appier/test/export.py +0 -0
  81. {appier-1.33.1 → appier-1.33.3}/src/appier/test/graph.py +0 -0
  82. {appier-1.33.1 → appier-1.33.3}/src/appier/test/http.py +0 -0
  83. {appier-1.33.1 → appier-1.33.3}/src/appier/test/legacy.py +0 -0
  84. {appier-1.33.1 → appier-1.33.3}/src/appier/test/log.py +0 -0
  85. {appier-1.33.1 → appier-1.33.3}/src/appier/test/mock.py +0 -0
  86. {appier-1.33.1 → appier-1.33.3}/src/appier/test/model.py +0 -0
  87. {appier-1.33.1 → appier-1.33.3}/src/appier/test/part.py +0 -0
  88. {appier-1.33.1 → appier-1.33.3}/src/appier/test/preferences.py +0 -0
  89. {appier-1.33.1 → appier-1.33.3}/src/appier/test/queuing.py +0 -0
  90. {appier-1.33.1 → appier-1.33.3}/src/appier/test/request.py +0 -0
  91. {appier-1.33.1 → appier-1.33.3}/src/appier/test/scheduler.py +0 -0
  92. {appier-1.33.1 → appier-1.33.3}/src/appier/test/serialize.py +0 -0
  93. {appier-1.33.1 → appier-1.33.3}/src/appier/test/session.py +0 -0
  94. {appier-1.33.1 → appier-1.33.3}/src/appier/test/smtp.py +0 -0
  95. {appier-1.33.1 → appier-1.33.3}/src/appier/test/structures.py +0 -0
  96. {appier-1.33.1 → appier-1.33.3}/src/appier/test/typesf.py +0 -0
  97. {appier-1.33.1 → appier-1.33.3}/src/appier/test/util.py +0 -0
  98. {appier-1.33.1 → appier-1.33.3}/src/appier/test/validation.py +0 -0
  99. {appier-1.33.1 → appier-1.33.3}/src/appier/typesf.py +0 -0
  100. {appier-1.33.1 → appier-1.33.3}/src/appier/util.py +0 -0
  101. {appier-1.33.1 → appier-1.33.3}/src/appier/validation.py +0 -0
  102. {appier-1.33.1 → appier-1.33.3}/src/appier.egg-info/dependency_links.txt +0 -0
  103. {appier-1.33.1 → appier-1.33.3}/src/appier.egg-info/not-zip-safe +0 -0
  104. {appier-1.33.1 → appier-1.33.3}/src/appier.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.1
2
2
  Name: appier
3
- Version: 1.33.1
3
+ Version: 1.33.3
4
4
  Summary: Appier Framework
5
5
  Home-page: http://appier.hive.pt
6
6
  Author: Hive Solutions Lda.
@@ -44,7 +44,7 @@ def read_file(path):
44
44
 
45
45
  setuptools.setup(
46
46
  name="appier",
47
- version="1.33.1",
47
+ version="1.33.3",
48
48
  author="Hive Solutions Lda.",
49
49
  author_email="development@hive.pt",
50
50
  description="Appier Framework",
@@ -57,6 +57,7 @@ setuptools.setup(
57
57
  package_dir={"": os.path.normpath("src")},
58
58
  package_data={
59
59
  "appier": [
60
+ "*.pyi",
60
61
  "res/static/css/*",
61
62
  "res/static/images/*",
62
63
  "res/static/js/*",
@@ -0,0 +1,3 @@
1
+ class AsyncManager: ...
2
+ class SimpleManager(AsyncManager): ...
3
+ class QueueManager(AsyncManager): ...
@@ -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.1"
97
+ VERSION = "1.33.3"
98
98
  """ The version of the framework that is currently installed
99
99
  this value may be used for debugging/diagnostic purposes """
100
100
 
@@ -2378,6 +2378,8 @@ class App(
2378
2378
  headers={},
2379
2379
  attachments=[],
2380
2380
  renderer=None,
2381
+ html=None,
2382
+ plain=None,
2381
2383
  html_handler=None,
2382
2384
  plain_handler=None,
2383
2385
  **kwargs
@@ -2452,13 +2454,16 @@ class App(
2452
2454
  subject=subject,
2453
2455
  )
2454
2456
 
2455
- html = renderer(template, detached=True, **parameters)
2456
- if plain_template:
2457
- plain = renderer(plain_template, detached=True, **parameters)
2458
- elif convert:
2459
- plain = util.html_to_text(html)
2460
- else:
2461
- plain = legacy.UNICODE("Email rendered using HTML")
2457
+ if html == None:
2458
+ html = renderer(template, detached=True, **parameters)
2459
+
2460
+ if plain == None:
2461
+ if plain_template:
2462
+ plain = renderer(plain_template, detached=True, **parameters)
2463
+ elif convert:
2464
+ plain = util.html_to_text(html)
2465
+ else:
2466
+ plain = legacy.UNICODE("Email rendered using HTML")
2462
2467
 
2463
2468
  if html_handler:
2464
2469
  html = html_handler(html)
@@ -0,0 +1,85 @@
1
+ from os import PathLike
2
+ from logging import Handler
3
+ from typing import Sequence, Type
4
+
5
+ from .bus import Bus
6
+ from .part import Part
7
+ from .cache import Cache
8
+ from .data import DataAdapter
9
+ from .session import Session
10
+ from .preferences import Preferences
11
+ from .asynchronous import AsyncManager
12
+ from .scheduler import SchedulerTask, JobFunction, Cron
13
+
14
+ class App:
15
+ def __init__(
16
+ self,
17
+ name: str | None = ...,
18
+ locales: Sequence[str] = ...,
19
+ parts: Sequence[Type[Part]] = ...,
20
+ level: str | int | None = ...,
21
+ handlers: Sequence[Handler] | None = ...,
22
+ service: bool = ...,
23
+ safe: bool = ...,
24
+ lazy: bool = ...,
25
+ payload: bool = ...,
26
+ cache_s: int = ...,
27
+ cache_c: Type[Cache] = ...,
28
+ preferences_c: Type[Preferences] = ...,
29
+ bus_c: Type[Bus] = ...,
30
+ session_c: Type[Session] = ...,
31
+ adapter_c: Type[DataAdapter] = ...,
32
+ manager_c: Type[AsyncManager] = ...,
33
+ ): ...
34
+ def start(self, refresh: bool = ...): ...
35
+ def stop(self, refresh: bool = ...): ...
36
+ def serve(
37
+ self,
38
+ server: str = ...,
39
+ host: str = ...,
40
+ port: int = ...,
41
+ ipv6: bool = ...,
42
+ ssl: bool = ...,
43
+ key_file: PathLike[str] | None = ...,
44
+ cer_file: PathLike[str] | None = ...,
45
+ backlog: int = ...,
46
+ threaded: bool = ...,
47
+ conf: bool = ...,
48
+ **kwargs
49
+ ): ...
50
+ def template(
51
+ self,
52
+ template: Template | PathLike[str] | str,
53
+ content_type: str = ...,
54
+ templates_path: PathLike[str] | str | None = ...,
55
+ cache: bool = ...,
56
+ detached: bool = ...,
57
+ locale: str | None = ...,
58
+ asynchronous: bool = ...,
59
+ **kwargs
60
+ ) -> str: ...
61
+ def cron(self, job: JobFunction, cron: Cron) -> SchedulerTask: ...
62
+ def url_for(
63
+ self,
64
+ type: str,
65
+ filename: str | None = ...,
66
+ prefix: str | None = ...,
67
+ query: str | None = ...,
68
+ params: str | None = ...,
69
+ absolute: bool = ...,
70
+ touch: bool = ...,
71
+ session: bool = ...,
72
+ compress: str | None = ...,
73
+ base_url: str | None = ...,
74
+ *args,
75
+ **kwargs
76
+ ) -> str | None: ...
77
+ ...
78
+
79
+ class APIApp(App): ...
80
+ class WebApp(App): ...
81
+ class Template: ...
82
+
83
+ def get_app() -> App: ...
84
+ def get_name() -> str | None: ...
85
+ def get_base_path() -> PathLike[str] | None: ...
@@ -0,0 +1,8 @@
1
+ from threading import Thread
2
+
3
+ from .component import Component
4
+
5
+ class Bus(Component): ...
6
+ class MemoryBus(Bus): ...
7
+ class RedisBus(Bus): ...
8
+ class RedisListener(Thread): ...
@@ -0,0 +1,7 @@
1
+ from .component import Component
2
+
3
+ class Cache(Component): ...
4
+ class MemoryCache(Cache): ...
5
+ class FileCache(Cache): ...
6
+ class RedisCache(Cache): ...
7
+ class SerializedCache: ...
@@ -0,0 +1 @@
1
+ class Component: ...
@@ -172,6 +172,7 @@ def load(names=(FILE_NAME,), path=None, encoding="utf-8", ctx=None):
172
172
  for path in paths:
173
173
  for name in names:
174
174
  load_file(name=name, path=path, encoding=encoding, ctx=ctx)
175
+ load_dot_env(ctx=ctx)
175
176
  load_env(ctx=ctx)
176
177
 
177
178
 
@@ -218,6 +219,54 @@ def load_file(name=FILE_NAME, path=None, encoding="utf-8", ctx=None):
218
219
  configs[key] = value
219
220
 
220
221
 
222
+ def load_dot_env(name=".env", encoding="utf-8", ctx=None):
223
+ configs = ctx["configs"] if ctx else CONFIGS
224
+ config_f = ctx["config_f"] if ctx else CONFIG_F
225
+
226
+ file_path = os.path.abspath(name)
227
+ file_path = os.path.normpath(file_path)
228
+
229
+ exists = os.path.exists(file_path)
230
+ if not exists:
231
+ return
232
+
233
+ exists = file_path in config_f
234
+ if exists:
235
+ config_f.remove(file_path)
236
+ config_f.append(file_path)
237
+
238
+ file = open(file_path, "rb")
239
+ try:
240
+ data = file.read()
241
+ finally:
242
+ file.close()
243
+ if not data:
244
+ return
245
+
246
+ data = data.decode(encoding)
247
+ data = data.strip()
248
+ lines = data.splitlines()
249
+ lines = [line.strip() for line in lines]
250
+
251
+ for line in lines:
252
+ line = line.strip()
253
+ if not line:
254
+ continue
255
+ if line.startswith("#"):
256
+ continue
257
+ key, value = line.split("=", 1)
258
+ key = key.strip()
259
+ value = value.strip()
260
+ if (
261
+ value.startswith('"')
262
+ and value.endswith('"')
263
+ or value.startswith("'")
264
+ and value.endswith("'")
265
+ ):
266
+ value = value[1:-1].replace('\\"', '"')
267
+ configs[key] = value
268
+
269
+
221
270
  def load_env(ctx=None):
222
271
  configs = ctx["configs"] if ctx else CONFIGS
223
272
 
@@ -0,0 +1,6 @@
1
+ class DataAdapter: ...
2
+ class MongoAdapter(DataAdapter): ...
3
+ class TinyAdapter(DataAdapter): ...
4
+ class Collection: ...
5
+ class MongoCollection(Collection): ...
6
+ class TinyCollection(Collection): ...
@@ -30,9 +30,9 @@ __license__ = "Apache License, Version 2.0"
30
30
 
31
31
  import os
32
32
  import sys
33
+ import inspect
33
34
  import calendar
34
35
  import datetime
35
- import inspect
36
36
  import functools
37
37
  import itertools
38
38
  import contextlib
@@ -241,6 +241,7 @@ class BaseFormatter(logging.Formatter):
241
241
  thread=record.thread,
242
242
  process=record.process,
243
243
  logger=record.name,
244
+ meta=getattr(record, "meta", None),
244
245
  )
245
246
  )
246
247
  record._wrapped = True
@@ -464,8 +464,10 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
464
464
  if not isinstance(model, dict):
465
465
  continue
466
466
  _model = cls(model=model, **kwargs)
467
- handler and handler(_model.model)
468
- build and cls.build(_model.model, map=False)
467
+ if handler:
468
+ handler(_model.model)
469
+ if build:
470
+ cls.build(_model.model, map=False)
469
471
  wrapping.append(_model)
470
472
  if is_sequence:
471
473
  return wrapping
@@ -2361,7 +2363,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2361
2363
  def copy(self, build=False, rules=True):
2362
2364
  cls = self.__class__
2363
2365
  _copy = copy.deepcopy(self)
2364
- build and cls.build(_copy.model, map=False, rules=rules)
2366
+ if build:
2367
+ cls.build(_copy.model, map=False, rules=rules)
2365
2368
  return _copy
2366
2369
 
2367
2370
  def clone(self, reset=True, deep=False):
@@ -2466,9 +2469,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2466
2469
  # should ensure that the model is ready to be saved in the
2467
2470
  # data source, without corruption of it, only run this process
2468
2471
  # in case the validate flag is correctly set
2469
- validate and self._validate(
2470
- pre_validate=pre_validate, post_validate=post_validate
2471
- )
2472
+ if validate:
2473
+ self._validate(pre_validate=pre_validate, post_validate=post_validate)
2472
2474
 
2473
2475
  # calls the complete set of event handlers for the current
2474
2476
  # save operation, this should trigger changes in the model
@@ -0,0 +1,48 @@
1
+ from typing import Callable, Self, Sequence
2
+ from .base import App
3
+
4
+ class Model:
5
+ owner: App
6
+
7
+ @classmethod
8
+ def singleton(
9
+ cls,
10
+ model: Self | None = ...,
11
+ form: bool = ...,
12
+ safe: bool = ...,
13
+ build: bool = ...,
14
+ *args,
15
+ **kwargs
16
+ ) -> Self | None: ...
17
+ @classmethod
18
+ def get(cls, *args, **kwargs) -> Self | None: ...
19
+ @classmethod
20
+ def find(cls, *args, **kwargs) -> Sequence[Self]: ...
21
+ @classmethod
22
+ def validate(cls) -> list[Callable]: ...
23
+ @classmethod
24
+ def _name(cls) -> str: ...
25
+ def save(
26
+ self,
27
+ validate: bool = ...,
28
+ verify: bool = ...,
29
+ is_new: bool | None = ...,
30
+ increment_a: bool | None = ...,
31
+ immutables_a: bool | None = ...,
32
+ pre_validate: bool = ...,
33
+ pre_save: bool = ...,
34
+ pre_create: bool = ...,
35
+ pre_update: bool = ...,
36
+ post_validate: bool = ...,
37
+ post_save: bool = ...,
38
+ post_create: bool = ...,
39
+ post_update: bool = ...,
40
+ before_callbacks: Sequence[Callable[[Self], None]] = ...,
41
+ after_callbacks: Sequence[Callable[[Self], None]] = ...,
42
+ ) -> Self: ...
43
+ ...
44
+
45
+ class Field:
46
+ def __init__(self, *args, **kwargs): ...
47
+
48
+ field = Field
@@ -0,0 +1 @@
1
+ class Part: ...
@@ -0,0 +1,6 @@
1
+ from .component import Component
2
+
3
+ class Preferences(Component): ...
4
+ class MemoryPreferences(Preferences): ...
5
+ class FilePreferences(Preferences): ...
6
+ class RedisPreferences(Preferences): ...
@@ -0,0 +1,70 @@
1
+ from datetime import datetime
2
+ from logging import Logger
3
+ from threading import Thread
4
+ from typing import Callable
5
+
6
+ from .base import App
7
+
8
+ LOOP_TIMEOUT: float = ...
9
+
10
+ JobFunction = Callable[[], None]
11
+ Cron = str | SchedulerDate
12
+ CronField = str | int | list | tuple
13
+
14
+ class Scheduler(Thread):
15
+ owner: App | None
16
+ timeout: float
17
+ daemon: bool
18
+
19
+ def __init__(self, owner: App | None, timeout: float = ..., daemon: bool = ...): ...
20
+ def run(self): ...
21
+ def stop(self): ...
22
+ def tick(self): ...
23
+ def load(self): ...
24
+ def awake(self): ...
25
+ @property
26
+ def logger(self) -> Logger: ...
27
+
28
+ class CronScheduler(Scheduler):
29
+ def __init__(self, owner: App | None, timeout: float = ..., daemon: bool = ...): ...
30
+ def tick(self, now_ts: float | None = ...): ...
31
+ def schedule(
32
+ self, job: JobFunction, cron: Cron, now: datetime | None = ...
33
+ ) -> SchedulerTask: ...
34
+ def next_run(self) -> datetime | None: ...
35
+ def next_timestamp(self) -> float | None: ...
36
+
37
+ class SchedulerTask(object):
38
+ job: JobFunction
39
+ date: SchedulerDate
40
+
41
+ def __init__(self, job: JobFunction, cron: Cron): ...
42
+ def enable(self): ...
43
+ def disable(self): ...
44
+ def next_run(self, now: datetime | None = ...) -> datetime: ...
45
+ def next_timestamp(self, now: datetime | None = ...) -> float: ...
46
+ @property
47
+ def enabled(self) -> bool: ...
48
+
49
+ class SchedulerDate(object):
50
+ minutes: set[int]
51
+ hours: set[int]
52
+ days_of_month: set[int]
53
+ months: set[int]
54
+ days_of_week: set[int]
55
+
56
+ def __init__(
57
+ self,
58
+ minutes: CronField = ...,
59
+ hours: CronField = ...,
60
+ days_of_month: CronField = ...,
61
+ months: CronField = ...,
62
+ days_of_week: CronField = ...,
63
+ ): ...
64
+ @classmethod
65
+ def from_cron(cls, cron: Cron) -> SchedulerDate: ...
66
+ def next_timestamp(self, now: datetime | None = None) -> float: ...
67
+ def next_run(self, now: datetime | None = None) -> datetime: ...
68
+ def _parse_field(
69
+ self, field: CronField, min_value: int, max_value: int
70
+ ) -> set[int]: ...
@@ -0,0 +1,7 @@
1
+ class Session: ...
2
+ class MockSession(Session): ...
3
+ class DataSession(Session): ...
4
+ class MemorySession(DataSession): ...
5
+ class FileSession(DataSession): ...
6
+ class RedisSession(DataSession): ...
7
+ class ClientSession(DataSession): ...
@@ -32,6 +32,11 @@ import unittest
32
32
 
33
33
  import appier
34
34
 
35
+ try:
36
+ import unittest.mock as mock
37
+ except ImportError:
38
+ mock = None
39
+
35
40
 
36
41
  class ConfigTest(unittest.TestCase):
37
42
  def test_basic(self):
@@ -79,3 +84,34 @@ class ConfigTest(unittest.TestCase):
79
84
  result = appier.conf("HEIGHT", cast=int)
80
85
 
81
86
  self.assertEqual(result, None)
87
+
88
+ def test_load_dot_env(self):
89
+ if mock == None:
90
+ self.skipTest("Skipping test: mock unavailable")
91
+
92
+ mock_data = mock.mock_open(
93
+ read_data=b"#This is a comment\nAGE=10\nNAME=colony\n"
94
+ )
95
+
96
+ with mock.patch("os.path.exists", return_value=True), mock.patch(
97
+ "builtins.open", mock_data, create=True
98
+ ) as mock_open:
99
+ ctx = dict(configs={}, config_f=[])
100
+
101
+ appier.config.load_dot_env(".env", "utf-8", ctx)
102
+
103
+ result = appier.conf("AGE", cast=int)
104
+ self.assertEqual(type(result), int)
105
+ self.assertEqual(result, 10)
106
+
107
+ result = appier.conf("AGE", cast=str)
108
+
109
+ self.assertEqual(result, "10")
110
+ self.assertEqual(type(result), str)
111
+
112
+ result = appier.conf("HEIGHT", cast=int)
113
+ self.assertEqual(result, None)
114
+
115
+ self.assertEqual(len(ctx["configs"]), 2)
116
+
117
+ self.assertEqual(mock_open.return_value.close.call_count, 1)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.1
2
2
  Name: appier
3
- Version: 1.33.1
3
+ Version: 1.33.3
4
4
  Summary: Appier Framework
5
5
  Home-page: http://appier.hive.pt
6
6
  Author: Hive Solutions Lda.
@@ -9,16 +9,22 @@ src/appier/asgi.py
9
9
  src/appier/async_neo.py
10
10
  src/appier/async_old.py
11
11
  src/appier/asynchronous.py
12
+ src/appier/asynchronous.pyi
12
13
  src/appier/base.py
14
+ src/appier/base.pyi
13
15
  src/appier/bus.py
16
+ src/appier/bus.pyi
14
17
  src/appier/cache.py
18
+ src/appier/cache.pyi
15
19
  src/appier/common.py
16
20
  src/appier/component.py
21
+ src/appier/component.pyi
17
22
  src/appier/compress.py
18
23
  src/appier/config.py
19
24
  src/appier/controller.py
20
25
  src/appier/crypt.py
21
26
  src/appier/data.py
27
+ src/appier/data.pyi
22
28
  src/appier/defines.py
23
29
  src/appier/exceptions.py
24
30
  src/appier/execution.py
@@ -35,17 +41,22 @@ src/appier/log.py
35
41
  src/appier/meta.py
36
42
  src/appier/mock.py
37
43
  src/appier/model.py
44
+ src/appier/model.pyi
38
45
  src/appier/model_a.py
39
46
  src/appier/mongo.py
40
47
  src/appier/observer.py
41
48
  src/appier/part.py
49
+ src/appier/part.pyi
42
50
  src/appier/preferences.py
51
+ src/appier/preferences.pyi
43
52
  src/appier/queuing.py
44
53
  src/appier/redisdb.py
45
54
  src/appier/request.py
46
55
  src/appier/scheduler.py
56
+ src/appier/scheduler.pyi
47
57
  src/appier/serialize.py
48
58
  src/appier/session.py
59
+ src/appier/session.pyi
49
60
  src/appier/settings.py
50
61
  src/appier/smtp.py
51
62
  src/appier/storage.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
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