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.
- appier/__init__.py +333 -52
- appier/amqp.py +29 -30
- appier/api.py +214 -212
- appier/asgi.py +54 -55
- appier/async_neo.py +46 -35
- appier/async_old.py +55 -42
- appier/asynchronous.py +7 -13
- appier/base.py +1762 -1429
- appier/bus.py +51 -52
- appier/cache.py +99 -84
- appier/common.py +9 -11
- appier/component.py +17 -19
- appier/compress.py +25 -28
- appier/config.py +96 -73
- appier/controller.py +9 -15
- appier/crypt.py +25 -21
- appier/data.py +73 -57
- appier/defines.py +191 -226
- appier/exceptions.py +103 -63
- appier/execution.py +94 -88
- appier/export.py +90 -88
- appier/extra.py +6 -13
- appier/extra_neo.py +8 -11
- appier/extra_old.py +18 -16
- appier/geo.py +57 -47
- appier/git.py +101 -90
- appier/graph.py +23 -24
- appier/http.py +520 -398
- appier/legacy.py +373 -180
- appier/log.py +90 -97
- appier/meta.py +42 -42
- appier/mock.py +32 -34
- appier/model.py +793 -681
- appier/model_a.py +208 -183
- appier/mongo.py +183 -107
- appier/observer.py +39 -31
- appier/part.py +23 -24
- appier/preferences.py +44 -47
- appier/queuing.py +78 -96
- appier/redisdb.py +40 -35
- appier/request.py +227 -175
- appier/scheduler.py +13 -18
- appier/serialize.py +37 -31
- appier/session.py +161 -147
- appier/settings.py +2 -11
- appier/smtp.py +53 -49
- appier/storage.py +39 -33
- appier/structures.py +50 -45
- appier/test/__init__.py +2 -11
- appier/test/base.py +111 -108
- appier/test/cache.py +28 -35
- appier/test/config.py +10 -19
- appier/test/crypt.py +3 -12
- appier/test/data.py +3 -12
- appier/test/exceptions.py +8 -17
- appier/test/export.py +16 -33
- appier/test/graph.py +27 -60
- appier/test/http.py +42 -54
- appier/test/legacy.py +20 -30
- appier/test/log.py +14 -35
- appier/test/mock.py +27 -123
- appier/test/model.py +79 -91
- appier/test/part.py +5 -14
- appier/test/preferences.py +5 -13
- appier/test/queuing.py +29 -37
- appier/test/request.py +61 -73
- appier/test/serialize.py +12 -23
- appier/test/session.py +10 -19
- appier/test/smtp.py +8 -14
- appier/test/structures.py +20 -24
- appier/test/typesf.py +14 -28
- appier/test/util.py +480 -438
- appier/typesf.py +251 -171
- appier/util.py +578 -407
- appier/validation.py +280 -143
- {appier-1.31.4.dist-info → appier-1.32.0.dist-info}/METADATA +6 -1
- appier-1.32.0.dist-info/RECORD +86 -0
- appier-1.31.4.dist-info/RECORD +0 -86
- {appier-1.31.4.dist-info → appier-1.32.0.dist-info}/LICENSE +0 -0
- {appier-1.31.4.dist-info → appier-1.32.0.dist-info}/WHEEL +0 -0
- {appier-1.31.4.dist-info → appier-1.32.0.dist-info}/top_level.txt +0 -0
appier/smtp.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
|
|
4
4
|
# Hive Appier Framework
|
|
5
|
-
# Copyright (c) 2008-
|
|
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
|
-
|
|
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"
|
|
@@ -46,19 +37,21 @@ import email.mime.application
|
|
|
46
37
|
from . import config
|
|
47
38
|
from . import legacy
|
|
48
39
|
|
|
40
|
+
|
|
49
41
|
def message(
|
|
50
42
|
sender,
|
|
51
43
|
receivers,
|
|
52
44
|
contents,
|
|
53
|
-
host
|
|
54
|
-
port
|
|
55
|
-
username
|
|
56
|
-
password
|
|
57
|
-
stls
|
|
58
|
-
safe
|
|
45
|
+
host=None,
|
|
46
|
+
port=25,
|
|
47
|
+
username=None,
|
|
48
|
+
password=None,
|
|
49
|
+
stls=False,
|
|
50
|
+
safe=True,
|
|
59
51
|
):
|
|
60
52
|
is_contents = isinstance(contents, legacy.STRINGS)
|
|
61
|
-
if not is_contents:
|
|
53
|
+
if not is_contents:
|
|
54
|
+
contents = contents.as_string()
|
|
62
55
|
if safe:
|
|
63
56
|
contents = contents.replace("\r\n", "\n")
|
|
64
57
|
contents = contents.replace("\n", "\r\n")
|
|
@@ -69,72 +62,83 @@ def message(
|
|
|
69
62
|
sender,
|
|
70
63
|
receivers,
|
|
71
64
|
contents,
|
|
72
|
-
host
|
|
73
|
-
port
|
|
74
|
-
username
|
|
75
|
-
password
|
|
76
|
-
stls
|
|
77
|
-
helo_host
|
|
65
|
+
host=host,
|
|
66
|
+
port=port,
|
|
67
|
+
username=username,
|
|
68
|
+
password=password,
|
|
69
|
+
stls=stls,
|
|
70
|
+
helo_host=helo_host,
|
|
78
71
|
)
|
|
79
72
|
|
|
73
|
+
|
|
80
74
|
def message_base(
|
|
81
75
|
sender,
|
|
82
76
|
receivers,
|
|
83
77
|
contents,
|
|
84
|
-
host
|
|
85
|
-
port
|
|
86
|
-
username
|
|
87
|
-
password
|
|
88
|
-
stls
|
|
89
|
-
helo_host
|
|
78
|
+
host=None,
|
|
79
|
+
port=25,
|
|
80
|
+
username=None,
|
|
81
|
+
password=None,
|
|
82
|
+
stls=False,
|
|
83
|
+
helo_host=None,
|
|
90
84
|
*args,
|
|
91
85
|
**kwargs
|
|
92
86
|
):
|
|
93
87
|
pass
|
|
94
88
|
|
|
89
|
+
|
|
95
90
|
def message_netius(
|
|
96
91
|
sender,
|
|
97
92
|
receivers,
|
|
98
93
|
contents,
|
|
99
|
-
host
|
|
100
|
-
port
|
|
101
|
-
username
|
|
102
|
-
password
|
|
103
|
-
stls
|
|
104
|
-
helo_host
|
|
94
|
+
host=None,
|
|
95
|
+
port=25,
|
|
96
|
+
username=None,
|
|
97
|
+
password=None,
|
|
98
|
+
stls=False,
|
|
99
|
+
helo_host=None,
|
|
105
100
|
*args,
|
|
106
101
|
**kwargs
|
|
107
102
|
):
|
|
108
103
|
import netius.clients
|
|
109
|
-
|
|
104
|
+
|
|
105
|
+
smtp_client = netius.clients.SMTPClient(auto_close=True, host=helo_host)
|
|
110
106
|
smtp_client.message(
|
|
111
107
|
[sender],
|
|
112
108
|
receivers,
|
|
113
109
|
contents,
|
|
114
|
-
host
|
|
115
|
-
port
|
|
116
|
-
username
|
|
117
|
-
password
|
|
118
|
-
stls
|
|
110
|
+
host=host,
|
|
111
|
+
port=port,
|
|
112
|
+
username=username,
|
|
113
|
+
password=password,
|
|
114
|
+
stls=stls,
|
|
119
115
|
)
|
|
120
116
|
|
|
117
|
+
|
|
121
118
|
def smtp_engine():
|
|
122
|
-
if legacy.has_module("netius"):
|
|
119
|
+
if legacy.has_module("netius"):
|
|
120
|
+
return "netius"
|
|
123
121
|
return "base"
|
|
124
122
|
|
|
123
|
+
|
|
125
124
|
def multipart():
|
|
126
125
|
return email.mime.multipart.MIMEMultipart("alternative")
|
|
127
126
|
|
|
128
|
-
|
|
127
|
+
|
|
128
|
+
def plain(contents, encoding="utf-8"):
|
|
129
129
|
return email.mime.text.MIMEText(contents, "plain", encoding)
|
|
130
130
|
|
|
131
|
-
|
|
131
|
+
|
|
132
|
+
def html(contents, encoding="utf-8"):
|
|
132
133
|
return email.mime.text.MIMEText(contents, "html", encoding)
|
|
133
134
|
|
|
134
|
-
def application(contents, name = "unnamed"):
|
|
135
|
-
return email.mime.application.MIMEApplication(contents, Name = name)
|
|
136
135
|
|
|
137
|
-
def
|
|
136
|
+
def application(contents, name="unnamed"):
|
|
137
|
+
return email.mime.application.MIMEApplication(contents, Name=name)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def header(value, encoding="utf-8", encode=True):
|
|
138
141
|
header = email.header.Header(value, encoding)
|
|
139
|
-
if encode:
|
|
142
|
+
if encode:
|
|
143
|
+
header = header.encode()
|
|
140
144
|
return header
|
appier/storage.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
|
|
4
4
|
# Hive Appier Framework
|
|
5
|
-
# Copyright (c) 2008-
|
|
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
|
-
|
|
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"
|
|
@@ -43,8 +34,8 @@ import tempfile
|
|
|
43
34
|
from . import config
|
|
44
35
|
from . import exceptions
|
|
45
36
|
|
|
46
|
-
class StorageEngine(object):
|
|
47
37
|
|
|
38
|
+
class StorageEngine(object):
|
|
48
39
|
@classmethod
|
|
49
40
|
def load(cls, file, *args, **kwargs):
|
|
50
41
|
raise exceptions.NotImplementedError()
|
|
@@ -81,21 +72,25 @@ class StorageEngine(object):
|
|
|
81
72
|
def _compute(cls, file, *args, **kwargs):
|
|
82
73
|
file._compute(*args, **kwargs)
|
|
83
74
|
|
|
84
|
-
class BaseEngine(StorageEngine):
|
|
85
75
|
|
|
76
|
+
class BaseEngine(StorageEngine):
|
|
86
77
|
@classmethod
|
|
87
78
|
def load(cls, file, *args, **kwargs):
|
|
88
79
|
force = kwargs.get("force", False)
|
|
89
|
-
if not file.file_name:
|
|
90
|
-
|
|
80
|
+
if not file.file_name:
|
|
81
|
+
return
|
|
82
|
+
if file.data and not force:
|
|
83
|
+
return
|
|
91
84
|
|
|
92
85
|
path = tempfile.mkdtemp()
|
|
93
86
|
path_f = os.path.join(path, file.file_name)
|
|
94
87
|
file.file.save(path_f)
|
|
95
88
|
|
|
96
89
|
handle = open(path_f, "rb")
|
|
97
|
-
try:
|
|
98
|
-
|
|
90
|
+
try:
|
|
91
|
+
file.data = handle.read()
|
|
92
|
+
finally:
|
|
93
|
+
handle.close()
|
|
99
94
|
|
|
100
95
|
cls._compute()
|
|
101
96
|
|
|
@@ -113,14 +108,16 @@ class BaseEngine(StorageEngine):
|
|
|
113
108
|
# reading in case none is defined the handled flag
|
|
114
109
|
# handling is ignored and the data returned immediately
|
|
115
110
|
size = kwargs.get("size", None)
|
|
116
|
-
if not size:
|
|
111
|
+
if not size:
|
|
112
|
+
return file.data
|
|
117
113
|
|
|
118
114
|
# verifies if the handled flag is already set (data)
|
|
119
115
|
# has been already retrieved and if that's not the
|
|
120
116
|
# case sets the handled flag and returns the data
|
|
121
117
|
handled = hasattr(file, "_handled")
|
|
122
118
|
file._handled = True
|
|
123
|
-
if not handled:
|
|
119
|
+
if not handled:
|
|
120
|
+
return file.data
|
|
124
121
|
|
|
125
122
|
# runs the final cleanup operation and returns an empty
|
|
126
123
|
# value to end the reading sequence
|
|
@@ -129,22 +126,25 @@ class BaseEngine(StorageEngine):
|
|
|
129
126
|
|
|
130
127
|
@classmethod
|
|
131
128
|
def cleanup(cls, file, *args, **kwargs):
|
|
132
|
-
if not hasattr(file, "handled"):
|
|
129
|
+
if not hasattr(file, "handled"):
|
|
130
|
+
return
|
|
133
131
|
del file._handled
|
|
134
132
|
|
|
135
133
|
@classmethod
|
|
136
134
|
def is_stored(self):
|
|
137
135
|
return True
|
|
138
136
|
|
|
139
|
-
class FsEngine(StorageEngine):
|
|
140
137
|
|
|
138
|
+
class FsEngine(StorageEngine):
|
|
141
139
|
@classmethod
|
|
142
140
|
def store(cls, file, *args, **kwargs):
|
|
143
141
|
file_path = cls._file_path(file)
|
|
144
142
|
file_data = file.data or b""
|
|
145
143
|
handle = open(file_path, "wb")
|
|
146
|
-
try:
|
|
147
|
-
|
|
144
|
+
try:
|
|
145
|
+
handle.write(file_data)
|
|
146
|
+
finally:
|
|
147
|
+
handle.close()
|
|
148
148
|
|
|
149
149
|
@classmethod
|
|
150
150
|
def load(cls, file, *args, **kwargs):
|
|
@@ -152,7 +152,7 @@ class FsEngine(StorageEngine):
|
|
|
152
152
|
|
|
153
153
|
@classmethod
|
|
154
154
|
def delete(cls, file, *args, **kwargs):
|
|
155
|
-
file_path = cls._file_path(file, ensure
|
|
155
|
+
file_path = cls._file_path(file, ensure=False)
|
|
156
156
|
os.remove(file_path)
|
|
157
157
|
|
|
158
158
|
@classmethod
|
|
@@ -160,7 +160,8 @@ class FsEngine(StorageEngine):
|
|
|
160
160
|
data = None
|
|
161
161
|
size = kwargs.get("size", None)
|
|
162
162
|
handle = cls._handle(file)
|
|
163
|
-
try:
|
|
163
|
+
try:
|
|
164
|
+
data = handle.read(size or -1)
|
|
164
165
|
finally:
|
|
165
166
|
is_final = True if not size or not data else False
|
|
166
167
|
is_final and cls.cleanup(file)
|
|
@@ -169,13 +170,15 @@ class FsEngine(StorageEngine):
|
|
|
169
170
|
@classmethod
|
|
170
171
|
def seek(cls, file, *args, **kwargs):
|
|
171
172
|
offset = kwargs.get("offset", None)
|
|
172
|
-
if offset == None:
|
|
173
|
+
if offset == None:
|
|
174
|
+
return
|
|
173
175
|
handle = cls._handle(file)
|
|
174
176
|
handle.seek(offset)
|
|
175
177
|
|
|
176
178
|
@classmethod
|
|
177
179
|
def cleanup(cls, file, *args, **kwargs):
|
|
178
|
-
if not hasattr(file, "_handle"):
|
|
180
|
+
if not hasattr(file, "_handle"):
|
|
181
|
+
return
|
|
179
182
|
file._handle.close()
|
|
180
183
|
del file._handle
|
|
181
184
|
|
|
@@ -185,7 +188,7 @@ class FsEngine(StorageEngine):
|
|
|
185
188
|
|
|
186
189
|
@classmethod
|
|
187
190
|
def _compute(cls, file):
|
|
188
|
-
file_path = cls._file_path(file, ensure
|
|
191
|
+
file_path = cls._file_path(file, ensure=False)
|
|
189
192
|
size = os.path.getsize(file_path)
|
|
190
193
|
mtime = os.path.getmtime(file_path)
|
|
191
194
|
file.hash = str(mtime)
|
|
@@ -194,14 +197,15 @@ class FsEngine(StorageEngine):
|
|
|
194
197
|
|
|
195
198
|
@classmethod
|
|
196
199
|
def _handle(cls, file):
|
|
197
|
-
file_path = cls._file_path(file, ensure
|
|
200
|
+
file_path = cls._file_path(file, ensure=False)
|
|
198
201
|
handle = hasattr(file, "_handle") and file._handle
|
|
199
|
-
if not handle:
|
|
202
|
+
if not handle:
|
|
203
|
+
handle = open(file_path, "rb")
|
|
200
204
|
file._handle = handle
|
|
201
205
|
return handle
|
|
202
206
|
|
|
203
207
|
@classmethod
|
|
204
|
-
def _file_path(cls, file, ensure
|
|
208
|
+
def _file_path(cls, file, ensure=True, base=None):
|
|
205
209
|
# verifies that the standard params value is defined and
|
|
206
210
|
# if that's no the case defaults the value, then tries to
|
|
207
211
|
# retrieve a series of parameters for file path discovery
|
|
@@ -225,8 +229,10 @@ class FsEngine(StorageEngine):
|
|
|
225
229
|
# verifies if the ensure flag is not set of if the directory
|
|
226
230
|
# path associated with the current file path exists and if
|
|
227
231
|
# that's the case returns the file path immediately
|
|
228
|
-
if not ensure:
|
|
229
|
-
|
|
232
|
+
if not ensure:
|
|
233
|
+
return file_path
|
|
234
|
+
if os.path.exists(dir_path):
|
|
235
|
+
return file_path
|
|
230
236
|
|
|
231
237
|
# creates the directories (concrete and parents) as requested
|
|
232
238
|
# and then returns the "final" file path value to the caller
|
appier/structures.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
|
|
4
4
|
# Hive Appier Framework
|
|
5
|
-
# Copyright (c) 2008-
|
|
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
|
-
|
|
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"
|
|
@@ -39,15 +30,16 @@ __license__ = "Apache License, Version 2.0"
|
|
|
39
30
|
|
|
40
31
|
import os
|
|
41
32
|
|
|
42
|
-
class OrderedDict(dict):
|
|
43
33
|
|
|
44
|
-
|
|
34
|
+
class OrderedDict(dict):
|
|
35
|
+
def __init__(self, value=None, *args, **kwargs):
|
|
45
36
|
object.__init__(self, *args, **kwargs)
|
|
46
37
|
self._list = list()
|
|
47
38
|
self._dict = dict()
|
|
48
39
|
self._items = dict()
|
|
49
40
|
is_dict = isinstance(value, dict)
|
|
50
|
-
if not is_dict:
|
|
41
|
+
if not is_dict:
|
|
42
|
+
return
|
|
51
43
|
self._from_dict(value)
|
|
52
44
|
|
|
53
45
|
def __str__(self):
|
|
@@ -82,16 +74,16 @@ class OrderedDict(dict):
|
|
|
82
74
|
self._verify()
|
|
83
75
|
return self._dict.__contains__(item)
|
|
84
76
|
|
|
85
|
-
def __iter__(self, verify
|
|
86
|
-
self._verify(force
|
|
77
|
+
def __iter__(self, verify=True):
|
|
78
|
+
self._verify(force=verify)
|
|
87
79
|
return self._list.__iter__()
|
|
88
80
|
|
|
89
|
-
def items(self, verify
|
|
90
|
-
self._verify(force
|
|
81
|
+
def items(self, verify=True):
|
|
82
|
+
self._verify(force=verify)
|
|
91
83
|
return self
|
|
92
84
|
|
|
93
|
-
def iteritems(self, verify
|
|
94
|
-
self._verify(force
|
|
85
|
+
def iteritems(self, verify=True):
|
|
86
|
+
self._verify(force=verify)
|
|
95
87
|
return self
|
|
96
88
|
|
|
97
89
|
def item(self, key):
|
|
@@ -106,7 +98,7 @@ class OrderedDict(dict):
|
|
|
106
98
|
self._verify()
|
|
107
99
|
return self.push(value)
|
|
108
100
|
|
|
109
|
-
def pop(self, index
|
|
101
|
+
def pop(self, index=-1):
|
|
110
102
|
self._verify()
|
|
111
103
|
value = self._list.pop(index)
|
|
112
104
|
key, _value = value
|
|
@@ -119,9 +111,10 @@ class OrderedDict(dict):
|
|
|
119
111
|
key, value = value
|
|
120
112
|
self.set(key, value)
|
|
121
113
|
|
|
122
|
-
def get(self, key, default
|
|
114
|
+
def get(self, key, default=None):
|
|
123
115
|
self._verify()
|
|
124
|
-
if not key in self._dict:
|
|
116
|
+
if not key in self._dict:
|
|
117
|
+
return default
|
|
125
118
|
return self._dict[key]
|
|
126
119
|
|
|
127
120
|
def set(self, key, value):
|
|
@@ -147,7 +140,7 @@ class OrderedDict(dict):
|
|
|
147
140
|
self._dict.clear()
|
|
148
141
|
self._items.clear()
|
|
149
142
|
|
|
150
|
-
def _from_dict(self, base, empty
|
|
143
|
+
def _from_dict(self, base, empty=True):
|
|
151
144
|
"""
|
|
152
145
|
Builds the ordered dictionary from a base (unordered) one
|
|
153
146
|
sorting all of its items accordingly.
|
|
@@ -164,15 +157,17 @@ class OrderedDict(dict):
|
|
|
164
157
|
to an empty state before using the dictionary.
|
|
165
158
|
"""
|
|
166
159
|
|
|
167
|
-
if empty:
|
|
160
|
+
if empty:
|
|
161
|
+
self.empty()
|
|
168
162
|
keys = list(base.keys())
|
|
169
163
|
keys.sort()
|
|
170
164
|
for key in keys:
|
|
171
165
|
value = base[key]
|
|
172
166
|
self.set(key, value)
|
|
173
|
-
if empty:
|
|
167
|
+
if empty:
|
|
168
|
+
self._dict = base
|
|
174
169
|
|
|
175
|
-
def _verify(self, force
|
|
170
|
+
def _verify(self, force=False):
|
|
176
171
|
"""
|
|
177
172
|
Runs the consistency check on the current structure so that
|
|
178
173
|
if any change occurs in the base dictionary (either adding
|
|
@@ -187,51 +182,57 @@ class OrderedDict(dict):
|
|
|
187
182
|
exactly the same.
|
|
188
183
|
"""
|
|
189
184
|
|
|
190
|
-
if not force and len(self._list) == len(self._dict):
|
|
185
|
+
if not force and len(self._list) == len(self._dict):
|
|
186
|
+
return
|
|
191
187
|
|
|
192
188
|
for value in list(self._list):
|
|
193
189
|
key, _value = value
|
|
194
190
|
exists = True
|
|
195
191
|
exists &= key in self._dict
|
|
196
192
|
exists &= key in self._items
|
|
197
|
-
if exists:
|
|
193
|
+
if exists:
|
|
194
|
+
continue
|
|
198
195
|
self._list.remove(value)
|
|
199
196
|
|
|
200
|
-
if len(self._list) == len(self._dict):
|
|
197
|
+
if len(self._list) == len(self._dict):
|
|
198
|
+
return
|
|
201
199
|
|
|
202
200
|
for key, value in self._dict.items():
|
|
203
201
|
item = [key, value]
|
|
204
|
-
if item in self._list:
|
|
202
|
+
if item in self._list:
|
|
203
|
+
continue
|
|
205
204
|
self._list.append(item)
|
|
206
205
|
self._items[key] = item
|
|
207
206
|
|
|
208
|
-
class LazyDict(dict):
|
|
209
207
|
|
|
210
|
-
|
|
208
|
+
class LazyDict(dict):
|
|
209
|
+
def __getitem__(self, key, force=False, resolve=False):
|
|
211
210
|
value = dict.__getitem__(self, key)
|
|
212
|
-
if force:
|
|
213
|
-
|
|
214
|
-
|
|
211
|
+
if force:
|
|
212
|
+
return value
|
|
213
|
+
if not isinstance(value, LazyValue):
|
|
214
|
+
return value
|
|
215
|
+
return value.resolve(force=resolve)
|
|
215
216
|
|
|
216
|
-
def resolve(self, force
|
|
217
|
+
def resolve(self, force=False):
|
|
217
218
|
result = dict()
|
|
218
219
|
for key in self:
|
|
219
|
-
value = self.__getitem__(key, resolve
|
|
220
|
+
value = self.__getitem__(key, resolve=force)
|
|
220
221
|
result[key] = value
|
|
221
222
|
return result
|
|
222
223
|
|
|
223
|
-
def to_dict(self, force
|
|
224
|
-
return self.resolve(force
|
|
224
|
+
def to_dict(self, force=True):
|
|
225
|
+
return self.resolve(force=force)
|
|
225
226
|
|
|
226
|
-
class LazyValue(object):
|
|
227
227
|
|
|
228
|
+
class LazyValue(object):
|
|
228
229
|
def __init__(self, callable):
|
|
229
230
|
self.callable = callable
|
|
230
231
|
|
|
231
232
|
def __call__(self):
|
|
232
233
|
return self.call()
|
|
233
234
|
|
|
234
|
-
def resolve(self, force
|
|
235
|
+
def resolve(self, force=False):
|
|
235
236
|
if hasattr(self, "_value") and not force:
|
|
236
237
|
return self._value
|
|
237
238
|
self._value = self.callable()
|
|
@@ -240,6 +241,7 @@ class LazyValue(object):
|
|
|
240
241
|
def call(self):
|
|
241
242
|
return self.resolve()
|
|
242
243
|
|
|
244
|
+
|
|
243
245
|
class GeneratorFile(object):
|
|
244
246
|
"""
|
|
245
247
|
File like class that encapsulates an underlying
|
|
@@ -256,7 +258,7 @@ class GeneratorFile(object):
|
|
|
256
258
|
self._size = next(generator)
|
|
257
259
|
self._position = 0
|
|
258
260
|
|
|
259
|
-
def seek(self, offset, whence
|
|
261
|
+
def seek(self, offset, whence=os.SEEK_SET):
|
|
260
262
|
if whence == os.SEEK_SET:
|
|
261
263
|
self._position = offset
|
|
262
264
|
if whence == os.SEEK_CUR:
|
|
@@ -268,12 +270,15 @@ class GeneratorFile(object):
|
|
|
268
270
|
return self._position
|
|
269
271
|
|
|
270
272
|
def read(self, size):
|
|
271
|
-
try:
|
|
272
|
-
|
|
273
|
+
try:
|
|
274
|
+
data = next(self._generator)
|
|
275
|
+
except StopIteration:
|
|
276
|
+
data = b""
|
|
273
277
|
return data
|
|
274
278
|
|
|
275
279
|
def close(self):
|
|
276
280
|
self._generator.close()
|
|
277
281
|
|
|
282
|
+
|
|
278
283
|
lazy_dict = LazyDict
|
|
279
284
|
lazy = LazyValue
|
appier/test/__init__.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
|
|
4
4
|
# Hive Appier Framework
|
|
5
|
-
# Copyright (c) 2008-
|
|
5
|
+
# Copyright (c) 2008-2024 Hive Solutions Lda.
|
|
6
6
|
#
|
|
7
7
|
# This file is part of Hive Appier Framework.
|
|
8
8
|
#
|
|
@@ -19,16 +19,7 @@
|
|
|
19
19
|
# You should have received a copy of the Apache License along with
|
|
20
20
|
# Hive Appier Framework. If not, see <http://www.apache.org/licenses/>.
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
""" The version of the module """
|
|
24
|
-
|
|
25
|
-
__revision__ = "$LastChangedRevision$"
|
|
26
|
-
""" The revision number of the module """
|
|
27
|
-
|
|
28
|
-
__date__ = "$LastChangedDate$"
|
|
29
|
-
""" The last change date of the module """
|
|
30
|
-
|
|
31
|
-
__copyright__ = "Copyright (c) 2008-2022 Hive Solutions Lda."
|
|
22
|
+
__copyright__ = "Copyright (c) 2008-2024 Hive Solutions Lda."
|
|
32
23
|
""" The copyright for the module """
|
|
33
24
|
|
|
34
25
|
__license__ = "Apache License, Version 2.0"
|