edq-utils 0.0.5__py3-none-any.whl → 0.0.6__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.
Potentially problematic release.
This version of edq-utils might be problematic. Click here for more details.
- edq/__init__.py +1 -1
- edq/cli/config/__init__.py +3 -0
- edq/cli/config/list.py +69 -0
- edq/cli/http/__init__.py +3 -0
- edq/cli/http/exchange-server.py +71 -0
- edq/cli/http/send-exchange.py +45 -0
- edq/cli/http/verify-exchanges.py +38 -0
- edq/cli/testing/__init__.py +3 -0
- edq/cli/testing/cli-test.py +8 -5
- edq/cli/version.py +2 -1
- edq/core/argparser.py +28 -3
- edq/core/config.py +268 -0
- edq/core/config_test.py +1038 -0
- edq/procedure/__init__.py +0 -0
- edq/procedure/verify_exchanges.py +85 -0
- edq/testing/asserts.py +0 -1
- edq/testing/cli.py +17 -1
- edq/testing/httpserver.py +553 -0
- edq/testing/httpserver_test.py +424 -0
- edq/testing/run.py +40 -10
- edq/testing/testdata/cli/data/configs/empty/edq-config.json +1 -0
- edq/testing/testdata/cli/data/configs/simple-1/edq-config.json +4 -0
- edq/testing/testdata/cli/data/configs/simple-2/edq-config.json +3 -0
- edq/testing/testdata/cli/data/configs/value-number/edq-config.json +3 -0
- edq/testing/testdata/cli/tests/config/list/config_list_base.txt +16 -0
- edq/testing/testdata/cli/tests/config/list/config_list_config_value_number.txt +10 -0
- edq/testing/testdata/cli/tests/config/list/config_list_ignore_config.txt +14 -0
- edq/testing/testdata/cli/tests/config/list/config_list_no_config.txt +8 -0
- edq/testing/testdata/cli/tests/config/list/config_list_show_origin.txt +13 -0
- edq/testing/testdata/cli/tests/config/list/config_list_skip_header.txt +10 -0
- edq/testing/testdata/http/exchanges/simple.httpex.json +5 -0
- edq/testing/testdata/http/exchanges/simple_anchor.httpex.json +5 -0
- edq/testing/testdata/http/exchanges/simple_file.httpex.json +10 -0
- edq/testing/testdata/http/exchanges/simple_file_binary.httpex.json +10 -0
- edq/testing/testdata/http/exchanges/simple_file_get_params.httpex.json +14 -0
- edq/testing/testdata/http/exchanges/simple_file_multiple.httpex.json +13 -0
- edq/testing/testdata/http/exchanges/simple_file_name.httpex.json +11 -0
- edq/testing/testdata/http/exchanges/simple_file_post_multiple.httpex.json +13 -0
- edq/testing/testdata/http/exchanges/simple_file_post_params.httpex.json +14 -0
- edq/testing/testdata/http/exchanges/simple_headers.httpex.json +8 -0
- edq/testing/testdata/http/exchanges/simple_jsonresponse_dict.httpex.json +7 -0
- edq/testing/testdata/http/exchanges/simple_jsonresponse_list.httpex.json +9 -0
- edq/testing/testdata/http/exchanges/simple_params.httpex.json +9 -0
- edq/testing/testdata/http/exchanges/simple_post.httpex.json +5 -0
- edq/testing/testdata/http/exchanges/simple_post_params.httpex.json +9 -0
- edq/testing/testdata/http/exchanges/simple_post_urlparams.httpex.json +5 -0
- edq/testing/testdata/http/exchanges/simple_urlparams.httpex.json +5 -0
- edq/testing/testdata/http/exchanges/specialcase_listparams_explicit.httpex.json +8 -0
- edq/testing/testdata/http/exchanges/specialcase_listparams_url.httpex.json +5 -0
- edq/testing/testdata/http/files/a.txt +1 -0
- edq/testing/testdata/http/files/tiny.png +0 -0
- edq/testing/unittest.py +12 -7
- edq/util/dirent.py +2 -0
- edq/util/json.py +21 -4
- edq/util/net.py +894 -0
- edq_utils-0.0.6.dist-info/METADATA +156 -0
- edq_utils-0.0.6.dist-info/RECORD +78 -0
- edq_utils-0.0.5.dist-info/METADATA +0 -63
- edq_utils-0.0.5.dist-info/RECORD +0 -34
- {edq_utils-0.0.5.dist-info → edq_utils-0.0.6.dist-info}/WHEEL +0 -0
- {edq_utils-0.0.5.dist-info → edq_utils-0.0.6.dist-info}/licenses/LICENSE +0 -0
- {edq_utils-0.0.5.dist-info → edq_utils-0.0.6.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
a
|
|
Binary file
|
edq/testing/unittest.py
CHANGED
|
@@ -14,12 +14,11 @@ class BaseTest(unittest.TestCase):
|
|
|
14
14
|
maxDiff = None
|
|
15
15
|
""" Don't limit the size of diffs. """
|
|
16
16
|
|
|
17
|
-
def assertJSONDictEqual(self, a: typing.Any, b: typing.Any) -> None: # pylint: disable=invalid-name
|
|
17
|
+
def assertJSONDictEqual(self, a: typing.Any, b: typing.Any, message: typing.Union[str, None] = None) -> None: # pylint: disable=invalid-name
|
|
18
18
|
"""
|
|
19
19
|
Like unittest.TestCase.assertDictEqual(),
|
|
20
20
|
but will try to convert each comparison argument to a dict if it is not already,
|
|
21
|
-
and uses
|
|
22
|
-
|
|
21
|
+
and uses a default assertion message containing the full JSON representation of the arguments.
|
|
23
22
|
"""
|
|
24
23
|
|
|
25
24
|
if (not isinstance(a, dict)):
|
|
@@ -37,17 +36,23 @@ class BaseTest(unittest.TestCase):
|
|
|
37
36
|
a_json = edq.util.json.dumps(a, indent = 4)
|
|
38
37
|
b_json = edq.util.json.dumps(b, indent = 4)
|
|
39
38
|
|
|
40
|
-
|
|
39
|
+
if (message is None):
|
|
40
|
+
message = FORMAT_STR % (a_json, b_json)
|
|
41
|
+
|
|
42
|
+
super().assertDictEqual(a, b, msg = message)
|
|
41
43
|
|
|
42
|
-
def assertJSONListEqual(self, a: typing.List[typing.Any], b: typing.List[typing.Any]) -> None: # pylint: disable=invalid-name
|
|
44
|
+
def assertJSONListEqual(self, a: typing.List[typing.Any], b: typing.List[typing.Any], message: typing.Union[str, None] = None) -> None: # pylint: disable=invalid-name
|
|
43
45
|
"""
|
|
44
|
-
Call
|
|
46
|
+
Call assertDictEqual(), but supply a default message containing the full JSON representation of the arguments.
|
|
45
47
|
"""
|
|
46
48
|
|
|
47
49
|
a_json = edq.util.json.dumps(a, indent = 4)
|
|
48
50
|
b_json = edq.util.json.dumps(b, indent = 4)
|
|
49
51
|
|
|
50
|
-
|
|
52
|
+
if (message is None):
|
|
53
|
+
message = FORMAT_STR % (a_json, b_json)
|
|
54
|
+
|
|
55
|
+
super().assertListEqual(a, b, msg = message)
|
|
51
56
|
|
|
52
57
|
def format_error_string(self, ex: typing.Union[BaseException, None]) -> str:
|
|
53
58
|
"""
|
edq/util/dirent.py
CHANGED
|
@@ -41,6 +41,8 @@ def get_temp_path(prefix: str = '', suffix: str = '', rm: bool = True) -> str:
|
|
|
41
41
|
while ((path is None) or exists(path)):
|
|
42
42
|
path = os.path.join(tempfile.gettempdir(), prefix + str(uuid.uuid4()) + suffix)
|
|
43
43
|
|
|
44
|
+
path = os.path.realpath(path)
|
|
45
|
+
|
|
44
46
|
if (rm):
|
|
45
47
|
atexit.register(remove, path)
|
|
46
48
|
|
edq/util/json.py
CHANGED
|
@@ -4,37 +4,45 @@ Specifically, we try to be flexible when reading (using JSON5),
|
|
|
4
4
|
and strict when writing (using vanilla JSON).
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
import abc
|
|
8
7
|
import enum
|
|
9
8
|
import json
|
|
9
|
+
import os
|
|
10
10
|
import typing
|
|
11
11
|
|
|
12
12
|
import json5
|
|
13
13
|
|
|
14
14
|
import edq.util.dirent
|
|
15
15
|
|
|
16
|
-
class DictConverter(
|
|
16
|
+
class DictConverter():
|
|
17
17
|
"""
|
|
18
18
|
A base class for class that can represent (serialize) and reconstruct (deserialize) themselves as/from a dict.
|
|
19
19
|
The intention is that the dict can then be cleanly converted to/from JSON.
|
|
20
|
+
|
|
21
|
+
General (but inefficient) implementations of several core Python equality, comparison, and representation methods are provided.
|
|
20
22
|
"""
|
|
21
23
|
|
|
22
|
-
@abc.abstractmethod
|
|
23
24
|
def to_dict(self) -> typing.Dict[str, typing.Any]:
|
|
24
25
|
"""
|
|
25
26
|
Return a dict that can be used to represent this object.
|
|
26
27
|
If the dict is passed to from_dict(), an identical object should be reconstructed.
|
|
28
|
+
|
|
29
|
+
A general (but inefficient) implementation is provided by default.
|
|
27
30
|
"""
|
|
28
31
|
|
|
32
|
+
return vars(self).copy()
|
|
33
|
+
|
|
29
34
|
@classmethod
|
|
30
|
-
@abc.abstractmethod
|
|
31
35
|
# Note that `typing.Self` is returned, but that is introduced in Python 3.12.
|
|
32
36
|
def from_dict(cls, data: typing.Dict[str, typing.Any]) -> typing.Any:
|
|
33
37
|
"""
|
|
34
38
|
Return an instance of this subclass created using the given dict.
|
|
35
39
|
If the dict came from to_dict(), the returned object should be identical to the original.
|
|
40
|
+
|
|
41
|
+
A general (but inefficient) implementation is provided by default.
|
|
36
42
|
"""
|
|
37
43
|
|
|
44
|
+
return cls(**data)
|
|
45
|
+
|
|
38
46
|
def __eq__(self, other: object) -> bool:
|
|
39
47
|
"""
|
|
40
48
|
Check for equality.
|
|
@@ -49,6 +57,12 @@ class DictConverter(abc.ABC):
|
|
|
49
57
|
|
|
50
58
|
return bool(self.to_dict() == other.to_dict()) # type: ignore[attr-defined]
|
|
51
59
|
|
|
60
|
+
def __lt__(self, other: 'DictConverter') -> bool:
|
|
61
|
+
return dumps(self) < dumps(other)
|
|
62
|
+
|
|
63
|
+
def __hash__(self) -> int:
|
|
64
|
+
return hash(dumps(self))
|
|
65
|
+
|
|
52
66
|
def __str__(self) -> str:
|
|
53
67
|
return dumps(self)
|
|
54
68
|
|
|
@@ -107,6 +121,9 @@ def load_path(
|
|
|
107
121
|
otherwise use JSON5.
|
|
108
122
|
"""
|
|
109
123
|
|
|
124
|
+
if (os.path.isdir(path)):
|
|
125
|
+
raise IsADirectoryError(f"Cannot open JSON file, expected a file but got a directory at '{path}'.")
|
|
126
|
+
|
|
110
127
|
try:
|
|
111
128
|
with open(path, 'r', encoding = encoding) as file:
|
|
112
129
|
return load(file, strict = strict, **kwargs)
|