iker-python-common 1.0.6__tar.gz → 1.0.8__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.
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/PKG-INFO +1 -1
- iker_python_common-1.0.8/src/iker/common/utils/argutils.py +76 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker/common/utils/dbutils.py +17 -13
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker/common/utils/sequtils.py +1 -1
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker/common/utils/strutils.py +1 -1
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker_python_common.egg-info/PKG-INFO +1 -1
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker_python_common.egg-info/SOURCES.txt +2 -0
- iker_python_common-1.0.8/test/iker_tests/common/utils/argutils_test.py +158 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/dbutils_test.py +45 -45
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/strutils_test.py +13 -6
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/.editorconfig +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/.github/workflows/pr.yml +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/.github/workflows/push.yml +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/.gitignore +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/MANIFEST.in +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/README.md +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/VERSION +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/pyproject.toml +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/resources/unittest/shutils/dir.baz/file.bar.baz +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/resources/unittest/shutils/dir.baz/file.foo.bar +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/resources/unittest/shutils/dir.baz/file.foo.baz +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/resources/unittest/shutils/dir.foo/dir.foo.bar/dir.foo.bar.baz/file.foo.bar.baz +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/resources/unittest/shutils/dir.foo/dir.foo.bar/file.bar.baz +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/resources/unittest/shutils/dir.foo/dir.foo.bar/file.foo.bar +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/resources/unittest/shutils/dir.foo/dir.foo.bar/file.foo.baz +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/resources/unittest/shutils/dir.foo/file.bar +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/resources/unittest/shutils/dir.foo/file.baz +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/resources/unittest/shutils/dir.foo/file.foo +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/setup.cfg +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/setup.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker/common/__init__.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker/common/utils/__init__.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker/common/utils/config.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker/common/utils/dockerutils.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker/common/utils/dtutils.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker/common/utils/funcutils.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker/common/utils/logger.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker/common/utils/numutils.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker/common/utils/randutils.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker/common/utils/retry.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker/common/utils/s3utils.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker/common/utils/shutils.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker/common/utils/span.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker/common/utils/testutils.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker_python_common.egg-info/dependency_links.txt +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker_python_common.egg-info/not-zip-safe +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker_python_common.egg-info/requires.txt +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker_python_common.egg-info/top_level.txt +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/__init__.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/config_test.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/dockerutils_test.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/dtutils_test.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/funcutils_test.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/logger_test.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/numutils_test.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/randutils_test.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/retry_test.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/s3utils_test.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/sequtils_test.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/shutils_test.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/span_test.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/testutils_test.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/docker_fixtures.py +0 -0
- {iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/iker_test.py +0 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
|
|
3
|
+
__all__ = [
|
|
4
|
+
"ParserTreeNode",
|
|
5
|
+
"ParserTree",
|
|
6
|
+
]
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ParserTreeNode(object):
|
|
10
|
+
def __init__(self, command: str, parser: argparse.ArgumentParser):
|
|
11
|
+
self.command = command
|
|
12
|
+
self.parser = parser
|
|
13
|
+
self.subparsers = None
|
|
14
|
+
self.child_nodes: list[ParserTreeNode] = []
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def construct_parser_tree(
|
|
18
|
+
root_node: ParserTreeNode,
|
|
19
|
+
command_chain: list[str],
|
|
20
|
+
command_key_prefix: str,
|
|
21
|
+
**kwargs,
|
|
22
|
+
) -> list[ParserTreeNode]:
|
|
23
|
+
node_path = [root_node]
|
|
24
|
+
if len(command_chain) == 0:
|
|
25
|
+
return node_path
|
|
26
|
+
|
|
27
|
+
node = root_node
|
|
28
|
+
for depth, command in enumerate(command_chain):
|
|
29
|
+
if node.subparsers is None:
|
|
30
|
+
node.subparsers = node.parser.add_subparsers(dest=f"{command_key_prefix}:{depth}")
|
|
31
|
+
for child_node in node.child_nodes:
|
|
32
|
+
if child_node.command == command:
|
|
33
|
+
node = child_node
|
|
34
|
+
break
|
|
35
|
+
else:
|
|
36
|
+
if depth == len(command_chain) - 1:
|
|
37
|
+
child_parser = node.subparsers.add_parser(command, **kwargs)
|
|
38
|
+
else:
|
|
39
|
+
child_parser = node.subparsers.add_parser(command)
|
|
40
|
+
child_node = ParserTreeNode(command, child_parser)
|
|
41
|
+
node.child_nodes.append(child_node)
|
|
42
|
+
node = child_node
|
|
43
|
+
node_path.append(node)
|
|
44
|
+
|
|
45
|
+
return node_path
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class ParserTree(object):
|
|
49
|
+
def __init__(self, root_parser: argparse.ArgumentParser, command_key_prefix: str = "command"):
|
|
50
|
+
self.root_node = ParserTreeNode("", root_parser)
|
|
51
|
+
self.command_key_prefix = command_key_prefix
|
|
52
|
+
|
|
53
|
+
def add_subcommand_parser(self, command_chain: list[str], **kwargs) -> argparse.ArgumentParser:
|
|
54
|
+
*_, last_node = construct_parser_tree(self.root_node, command_chain, self.command_key_prefix, **kwargs)
|
|
55
|
+
return last_node.parser
|
|
56
|
+
|
|
57
|
+
def parse_args(self, args: list[str] | None = None) -> tuple[list[str], argparse.Namespace]:
|
|
58
|
+
# Before Python 3.12 the 'exit_on_error' attribute does not take effect properly
|
|
59
|
+
# if unknown arguments encountered. We have to employ this workaround
|
|
60
|
+
# TODO: remove this workaround when bumping the Python versions to above Python 3.12
|
|
61
|
+
if self.root_node.parser.exit_on_error:
|
|
62
|
+
known_args_namespace = self.root_node.parser.parse_args(args)
|
|
63
|
+
else:
|
|
64
|
+
known_args_namespace, unknown_args = self.root_node.parser.parse_known_args(args)
|
|
65
|
+
if len(unknown_args or []) > 0:
|
|
66
|
+
raise argparse.ArgumentError(None, "unrecognized arguments: %s" % " ".join(unknown_args))
|
|
67
|
+
|
|
68
|
+
command_pairs = []
|
|
69
|
+
namespace = argparse.Namespace()
|
|
70
|
+
for key, value in dict(vars(known_args_namespace)).items():
|
|
71
|
+
if key.startswith(self.command_key_prefix) and value is not None:
|
|
72
|
+
command_pairs.append((key, value))
|
|
73
|
+
else:
|
|
74
|
+
setattr(namespace, key, value)
|
|
75
|
+
|
|
76
|
+
return list(command for _, command in sorted(command_pairs)), namespace
|
|
@@ -13,6 +13,7 @@ from iker.common.utils.sequtils import head_or_none
|
|
|
13
13
|
from iker.common.utils.strutils import is_blank
|
|
14
14
|
|
|
15
15
|
__all__ = [
|
|
16
|
+
"ConnectionMaker",
|
|
16
17
|
"DBAdapter",
|
|
17
18
|
"orm_to_dict",
|
|
18
19
|
"orm_clone",
|
|
@@ -21,9 +22,9 @@ __all__ = [
|
|
|
21
22
|
]
|
|
22
23
|
|
|
23
24
|
|
|
24
|
-
class
|
|
25
|
+
class ConnectionMaker(object):
|
|
25
26
|
"""
|
|
26
|
-
|
|
27
|
+
Provides utilities that make it easier to establish database connections and sessions
|
|
27
28
|
"""
|
|
28
29
|
|
|
29
30
|
class Drivers:
|
|
@@ -56,19 +57,19 @@ class DBAdapter(object):
|
|
|
56
57
|
url: str | urllib.parse.ParseResult,
|
|
57
58
|
engine_opts: dict[str, Any] | None = None,
|
|
58
59
|
session_opts: dict[str, Any] | None = None,
|
|
59
|
-
) -> "
|
|
60
|
+
) -> "ConnectionMaker":
|
|
60
61
|
if isinstance(url, str):
|
|
61
|
-
return
|
|
62
|
+
return ConnectionMaker.from_url(driver, urllib.parse.urlparse(url), engine_opts, session_opts)
|
|
62
63
|
if isinstance(url, urllib.parse.ParseResult):
|
|
63
|
-
return
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
raise ValueError("
|
|
64
|
+
return ConnectionMaker(driver,
|
|
65
|
+
url.hostname,
|
|
66
|
+
url.port,
|
|
67
|
+
url.username,
|
|
68
|
+
url.password,
|
|
69
|
+
url.path.strip("/"),
|
|
70
|
+
engine_opts,
|
|
71
|
+
session_opts)
|
|
72
|
+
raise ValueError("malformed parameter 'url'")
|
|
72
73
|
|
|
73
74
|
@property
|
|
74
75
|
def connection_string(self) -> str:
|
|
@@ -129,6 +130,9 @@ class DBAdapter(object):
|
|
|
129
130
|
return head_or_none(self.query_all(sql, **params))
|
|
130
131
|
|
|
131
132
|
|
|
133
|
+
DBAdapter = ConnectionMaker
|
|
134
|
+
|
|
135
|
+
|
|
132
136
|
def orm_to_dict(orm: sqlalchemy.orm.DeclarativeBase, exclude: set[str] = None) -> dict[str, Any]:
|
|
133
137
|
if not isinstance(orm, sqlalchemy.orm.DeclarativeBase):
|
|
134
138
|
raise TypeError('not a SQLAlchemy ORM declarative base')
|
|
@@ -101,7 +101,7 @@ def deduped(ms: Sequence[T], comp_func: Callable[[T, T], bool]) -> list[T]:
|
|
|
101
101
|
return deduped_ms
|
|
102
102
|
|
|
103
103
|
|
|
104
|
-
def batch_yield(ms: Iterable[T], batch_size: int) -> Generator[list[T]]:
|
|
104
|
+
def batch_yield(ms: Iterable[T], batch_size: int) -> Generator[list[T], None, None]:
|
|
105
105
|
"""
|
|
106
106
|
Splits the given input sequence into batches according to the specific batch size
|
|
107
107
|
|
|
@@ -131,7 +131,7 @@ def parse_params_string(s: str, delimiter: str = ",", kv_delimiter: str = "=") -
|
|
|
131
131
|
|
|
132
132
|
result = {}
|
|
133
133
|
for param in s.split(delimiter):
|
|
134
|
-
segments = param.split(kv_delimiter)
|
|
134
|
+
segments = param.split(kv_delimiter, 1)
|
|
135
135
|
if len(segments) == 1:
|
|
136
136
|
result[head(segments)] = str(True)
|
|
137
137
|
elif len(segments) == 2:
|
{iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker_python_common.egg-info/SOURCES.txt
RENAMED
|
@@ -19,6 +19,7 @@ resources/unittest/shutils/dir.foo/dir.foo.bar/file.foo.baz
|
|
|
19
19
|
resources/unittest/shutils/dir.foo/dir.foo.bar/dir.foo.bar.baz/file.foo.bar.baz
|
|
20
20
|
src/iker/common/__init__.py
|
|
21
21
|
src/iker/common/utils/__init__.py
|
|
22
|
+
src/iker/common/utils/argutils.py
|
|
22
23
|
src/iker/common/utils/config.py
|
|
23
24
|
src/iker/common/utils/dbutils.py
|
|
24
25
|
src/iker/common/utils/dockerutils.py
|
|
@@ -43,6 +44,7 @@ src/iker_python_common.egg-info/top_level.txt
|
|
|
43
44
|
test/iker_tests/__init__.py
|
|
44
45
|
test/iker_tests/docker_fixtures.py
|
|
45
46
|
test/iker_tests/iker_test.py
|
|
47
|
+
test/iker_tests/common/utils/argutils_test.py
|
|
46
48
|
test/iker_tests/common/utils/config_test.py
|
|
47
49
|
test/iker_tests/common/utils/dbutils_test.py
|
|
48
50
|
test/iker_tests/common/utils/dockerutils_test.py
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import unittest
|
|
3
|
+
|
|
4
|
+
import ddt
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from iker.common.utils.argutils import ParserTree
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def dummy_parser_tree():
|
|
11
|
+
parser_tree = ParserTree(argparse.ArgumentParser(description="dummy argument parser", exit_on_error=False))
|
|
12
|
+
|
|
13
|
+
for command_chain in [
|
|
14
|
+
[],
|
|
15
|
+
["foo"],
|
|
16
|
+
["foo", "bar"],
|
|
17
|
+
["foo", "baz"],
|
|
18
|
+
["bar"],
|
|
19
|
+
["bar", "foo"],
|
|
20
|
+
["bar", "baz"],
|
|
21
|
+
["baz", "foo"],
|
|
22
|
+
["baz", "bar"],
|
|
23
|
+
["baz", "bar", "foo"],
|
|
24
|
+
]:
|
|
25
|
+
parser = parser_tree.add_subcommand_parser(command_chain, exit_on_error=False)
|
|
26
|
+
|
|
27
|
+
option_infix = "-".join(command_chain)
|
|
28
|
+
if len(option_infix) == 0:
|
|
29
|
+
option_infix = "x"
|
|
30
|
+
|
|
31
|
+
parser.add_argument(f"--option-{option_infix}-str", type=str, default="")
|
|
32
|
+
parser.add_argument(f"--option-{option_infix}-int", type=int, default=0)
|
|
33
|
+
parser.add_argument(f"--option-{option_infix}-float", type=float, default=0.0)
|
|
34
|
+
parser.add_argument(f"--option-{option_infix}-switch", action="store_true")
|
|
35
|
+
parser.add_argument(f"--option-{option_infix}-nargs", type=str, action="append", default=[])
|
|
36
|
+
|
|
37
|
+
return parser_tree
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@ddt.ddt
|
|
41
|
+
class ArgUtilsTest(unittest.TestCase):
|
|
42
|
+
|
|
43
|
+
@ddt.data(
|
|
44
|
+
(
|
|
45
|
+
[],
|
|
46
|
+
[],
|
|
47
|
+
[
|
|
48
|
+
("option_x_str", ""),
|
|
49
|
+
("option_x_int", 0),
|
|
50
|
+
("option_x_float", 0.0),
|
|
51
|
+
("option_x_switch", False),
|
|
52
|
+
("option_x_nargs", []),
|
|
53
|
+
],
|
|
54
|
+
),
|
|
55
|
+
(
|
|
56
|
+
[
|
|
57
|
+
"--option-x-str", "dummy",
|
|
58
|
+
"--option-x-int", "1",
|
|
59
|
+
"--option-x-float", "1e6",
|
|
60
|
+
"--option-x-switch",
|
|
61
|
+
"--option-x-nargs", "dummy_1",
|
|
62
|
+
"--option-x-nargs", "dummy_2",
|
|
63
|
+
],
|
|
64
|
+
[],
|
|
65
|
+
[
|
|
66
|
+
("option_x_str", "dummy"),
|
|
67
|
+
("option_x_int", 1),
|
|
68
|
+
("option_x_float", 1e6),
|
|
69
|
+
("option_x_switch", True),
|
|
70
|
+
("option_x_nargs", ["dummy_1", "dummy_2"]),
|
|
71
|
+
],
|
|
72
|
+
),
|
|
73
|
+
(
|
|
74
|
+
["foo"],
|
|
75
|
+
["foo"],
|
|
76
|
+
[
|
|
77
|
+
("option_foo_str", ""),
|
|
78
|
+
("option_foo_int", 0),
|
|
79
|
+
("option_foo_float", 0.0),
|
|
80
|
+
("option_foo_switch", False),
|
|
81
|
+
("option_foo_nargs", []),
|
|
82
|
+
],
|
|
83
|
+
),
|
|
84
|
+
(
|
|
85
|
+
[
|
|
86
|
+
"foo", "baz",
|
|
87
|
+
"--option-foo-baz-str", "dummy",
|
|
88
|
+
"--option-foo-baz-int", "1",
|
|
89
|
+
"--option-foo-baz-float", "1e6",
|
|
90
|
+
"--option-foo-baz-switch",
|
|
91
|
+
"--option-foo-baz-nargs", "dummy_1",
|
|
92
|
+
"--option-foo-baz-nargs", "dummy_2",
|
|
93
|
+
],
|
|
94
|
+
["foo", "baz"],
|
|
95
|
+
[
|
|
96
|
+
("option_foo_baz_str", "dummy"),
|
|
97
|
+
("option_foo_baz_int", 1),
|
|
98
|
+
("option_foo_baz_float", 1e6),
|
|
99
|
+
("option_foo_baz_switch", True),
|
|
100
|
+
("option_foo_baz_nargs", ["dummy_1", "dummy_2"]),
|
|
101
|
+
],
|
|
102
|
+
),
|
|
103
|
+
(
|
|
104
|
+
[
|
|
105
|
+
"baz", "foo",
|
|
106
|
+
"--option-baz-foo-str", "dummy",
|
|
107
|
+
"--option-baz-foo-int", "1",
|
|
108
|
+
"--option-baz-foo-float", "1e6",
|
|
109
|
+
"--option-baz-foo-switch",
|
|
110
|
+
"--option-baz-foo-nargs", "dummy_1",
|
|
111
|
+
"--option-baz-foo-nargs", "dummy_2",
|
|
112
|
+
],
|
|
113
|
+
["baz", "foo"],
|
|
114
|
+
[
|
|
115
|
+
("option_baz_foo_str", "dummy"),
|
|
116
|
+
("option_baz_foo_int", 1),
|
|
117
|
+
("option_baz_foo_float", 1e6),
|
|
118
|
+
("option_baz_foo_switch", True),
|
|
119
|
+
("option_baz_foo_nargs", ["dummy_1", "dummy_2"]),
|
|
120
|
+
],
|
|
121
|
+
),
|
|
122
|
+
(
|
|
123
|
+
[
|
|
124
|
+
"baz", "bar", "foo",
|
|
125
|
+
"--option-baz-bar-foo-str", "dummy",
|
|
126
|
+
"--option-baz-bar-foo-int", "1",
|
|
127
|
+
"--option-baz-bar-foo-float", "1e6",
|
|
128
|
+
"--option-baz-bar-foo-switch",
|
|
129
|
+
"--option-baz-bar-foo-nargs", "dummy_1",
|
|
130
|
+
"--option-baz-bar-foo-nargs", "dummy_2",
|
|
131
|
+
],
|
|
132
|
+
["baz", "bar", "foo"],
|
|
133
|
+
[
|
|
134
|
+
("option_baz_bar_foo_str", "dummy"),
|
|
135
|
+
("option_baz_bar_foo_int", 1),
|
|
136
|
+
("option_baz_bar_foo_float", 1e6),
|
|
137
|
+
("option_baz_bar_foo_switch", True),
|
|
138
|
+
("option_baz_bar_foo_nargs", ["dummy_1", "dummy_2"]),
|
|
139
|
+
],
|
|
140
|
+
),
|
|
141
|
+
)
|
|
142
|
+
@ddt.unpack
|
|
143
|
+
def test_parser_tree(self, args, expect_commands, expect_options):
|
|
144
|
+
commands, args = dummy_parser_tree().parse_args(args)
|
|
145
|
+
self.assertEqual(commands, expect_commands)
|
|
146
|
+
for key, value in expect_options:
|
|
147
|
+
self.assertEqual(getattr(args, key), value)
|
|
148
|
+
|
|
149
|
+
@ddt.data(
|
|
150
|
+
(["foo", "foo"],),
|
|
151
|
+
(["foo", "--option-x-switch"],),
|
|
152
|
+
(["foo", "bar", "--option-bar-foo-switch"],),
|
|
153
|
+
(["baz", "foo", "bar"],),
|
|
154
|
+
)
|
|
155
|
+
@ddt.unpack
|
|
156
|
+
def test_parser_tree__exception(self, args):
|
|
157
|
+
with pytest.raises(argparse.ArgumentError):
|
|
158
|
+
dummy_parser_tree().parse_args(args)
|
{iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/dbutils_test.py
RENAMED
|
@@ -12,7 +12,7 @@ from sqlalchemy.exc import IntegrityError
|
|
|
12
12
|
from sqlalchemy.orm import DeclarativeBase, Mapped, MappedAsDataclass
|
|
13
13
|
from sqlalchemy.orm.exc import FlushError
|
|
14
14
|
|
|
15
|
-
from iker.common.utils.dbutils import
|
|
15
|
+
from iker.common.utils.dbutils import ConnectionMaker
|
|
16
16
|
from iker.common.utils.dbutils import mysql_insert_ignore, postgresql_insert_on_conflict_do_nothing
|
|
17
17
|
from iker.common.utils.dbutils import orm_clone
|
|
18
18
|
from iker.common.utils.funcutils import unique_returns
|
|
@@ -107,18 +107,18 @@ class PostgresqlDummyRecord(PostgresqlBaseModel):
|
|
|
107
107
|
|
|
108
108
|
|
|
109
109
|
@pytest.mark.skipif(sys.platform == "win32", reason="Test not applicable on Windows")
|
|
110
|
-
def
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
110
|
+
def test_mysql_connection_maker(fixture_mysql_test_proc, fixture_mysql_test):
|
|
111
|
+
maker = ConnectionMaker(ConnectionMaker.Drivers.Mysql,
|
|
112
|
+
"127.0.0.1",
|
|
113
|
+
fixture_mysql_test_proc.port,
|
|
114
|
+
fixture_mysql_test_proc.user,
|
|
115
|
+
None,
|
|
116
|
+
"test",
|
|
117
|
+
session_opts=dict(
|
|
118
|
+
expire_on_commit=False,
|
|
119
|
+
))
|
|
120
|
+
|
|
121
|
+
maker.create_model(MysqlBaseModel)
|
|
122
122
|
|
|
123
123
|
rng = randomizer()
|
|
124
124
|
|
|
@@ -144,28 +144,28 @@ def test_mysql_adapter(fixture_mysql_test_proc, fixture_mysql_test):
|
|
|
144
144
|
dummy_unique_string=dummy_unique_string(),
|
|
145
145
|
)
|
|
146
146
|
|
|
147
|
-
with
|
|
147
|
+
with maker.make_session() as session:
|
|
148
148
|
original_records = [random_record() for _ in range(0, 1000)]
|
|
149
149
|
session.bulk_save_objects(original_records, return_defaults=True)
|
|
150
150
|
session.commit()
|
|
151
151
|
|
|
152
|
-
with
|
|
152
|
+
with maker.make_session() as session:
|
|
153
153
|
count = session.query(sqlalchemy.func.count()).select_from(MysqlDummyRecord).scalar()
|
|
154
154
|
|
|
155
155
|
assert count == 1000
|
|
156
156
|
|
|
157
|
-
with
|
|
157
|
+
with maker.make_session() as session:
|
|
158
158
|
delete_rows = session.query(MysqlDummyRecord).order_by(MysqlDummyRecord.dummy_id).offset(500).all()
|
|
159
159
|
for delete_row in delete_rows:
|
|
160
160
|
session.delete(delete_row)
|
|
161
161
|
session.commit()
|
|
162
162
|
|
|
163
|
-
with
|
|
163
|
+
with maker.make_session() as session:
|
|
164
164
|
count = session.query(sqlalchemy.func.count()).select_from(MysqlDummyRecord).scalar()
|
|
165
165
|
|
|
166
166
|
assert count == 500
|
|
167
167
|
|
|
168
|
-
with
|
|
168
|
+
with maker.make_session() as session:
|
|
169
169
|
records = session.query(MysqlDummyRecord).order_by(MysqlDummyRecord.dummy_id).all()
|
|
170
170
|
|
|
171
171
|
for expect, actual in zip(original_records[:count], records[:count]):
|
|
@@ -189,12 +189,12 @@ def test_mysql_adapter(fixture_mysql_test_proc, fixture_mysql_test):
|
|
|
189
189
|
|
|
190
190
|
mysql_insert_ignore()
|
|
191
191
|
|
|
192
|
-
with
|
|
192
|
+
with maker.make_session() as session:
|
|
193
193
|
# PK violation, but suppressed by the compiler plugin
|
|
194
194
|
session.add(orm_clone(result))
|
|
195
195
|
session.commit()
|
|
196
196
|
|
|
197
|
-
with
|
|
197
|
+
with maker.make_session() as session:
|
|
198
198
|
# Unique index violation, but suppressed by the plugin
|
|
199
199
|
# Unlike the Postgresql implementation, MySQL will not raise a 'FlushError'.
|
|
200
200
|
# Instead, it will fill the auto increment column with zero
|
|
@@ -203,34 +203,34 @@ def test_mysql_adapter(fixture_mysql_test_proc, fixture_mysql_test):
|
|
|
203
203
|
|
|
204
204
|
mysql_insert_ignore(enabled=False)
|
|
205
205
|
|
|
206
|
-
with
|
|
206
|
+
with maker.make_session() as session:
|
|
207
207
|
# PK violation, which causes 'IntegrityError'
|
|
208
208
|
with pytest.raises(IntegrityError):
|
|
209
209
|
session.add(orm_clone(result))
|
|
210
210
|
session.commit()
|
|
211
211
|
|
|
212
|
-
with
|
|
212
|
+
with maker.make_session() as session:
|
|
213
213
|
# Unique index violation, which causes 'IntegrityError'
|
|
214
214
|
with pytest.raises(IntegrityError):
|
|
215
215
|
session.add(orm_clone(result, no_autoincrement=True))
|
|
216
216
|
session.commit()
|
|
217
217
|
|
|
218
|
-
|
|
218
|
+
maker.drop_model(MysqlBaseModel)
|
|
219
219
|
|
|
220
220
|
|
|
221
221
|
@pytest.mark.skipif(sys.platform == "win32", reason="Test not applicable on Windows")
|
|
222
|
-
def
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
222
|
+
def test_postgresql_connection_maker(fixture_postgresql_test_proc, fixture_postgresql_test):
|
|
223
|
+
maker = ConnectionMaker(ConnectionMaker.Drivers.Postgresql,
|
|
224
|
+
fixture_postgresql_test.info.host,
|
|
225
|
+
fixture_postgresql_test.info.port,
|
|
226
|
+
fixture_postgresql_test.info.user,
|
|
227
|
+
None,
|
|
228
|
+
fixture_postgresql_test.info.dbname,
|
|
229
|
+
session_opts=dict(
|
|
230
|
+
expire_on_commit=False,
|
|
231
|
+
))
|
|
232
|
+
|
|
233
|
+
maker.create_model(PostgresqlBaseModel)
|
|
234
234
|
|
|
235
235
|
rng = randomizer()
|
|
236
236
|
|
|
@@ -260,28 +260,28 @@ def test_postgresql_adapter(fixture_postgresql_test_proc, fixture_postgresql_tes
|
|
|
260
260
|
dummy_unique_string=dummy_unique_string(),
|
|
261
261
|
)
|
|
262
262
|
|
|
263
|
-
with
|
|
263
|
+
with maker.make_session() as session:
|
|
264
264
|
original_records = [random_record() for _ in range(0, 1000)]
|
|
265
265
|
session.bulk_save_objects(original_records, return_defaults=True)
|
|
266
266
|
session.commit()
|
|
267
267
|
|
|
268
|
-
with
|
|
268
|
+
with maker.make_session() as session:
|
|
269
269
|
count = session.query(sqlalchemy.func.count()).select_from(PostgresqlDummyRecord).scalar()
|
|
270
270
|
|
|
271
271
|
assert count == 1000
|
|
272
272
|
|
|
273
|
-
with
|
|
273
|
+
with maker.make_session() as session:
|
|
274
274
|
delete_rows = session.query(PostgresqlDummyRecord).order_by(PostgresqlDummyRecord.dummy_id).offset(500).all()
|
|
275
275
|
for delete_row in delete_rows:
|
|
276
276
|
session.delete(delete_row)
|
|
277
277
|
session.commit()
|
|
278
278
|
|
|
279
|
-
with
|
|
279
|
+
with maker.make_session() as session:
|
|
280
280
|
count = session.query(sqlalchemy.func.count()).select_from(PostgresqlDummyRecord).scalar()
|
|
281
281
|
|
|
282
282
|
assert count == 500
|
|
283
283
|
|
|
284
|
-
with
|
|
284
|
+
with maker.make_session() as session:
|
|
285
285
|
records = session.query(PostgresqlDummyRecord).order_by(PostgresqlDummyRecord.dummy_id).all()
|
|
286
286
|
|
|
287
287
|
for expect, actual in zip(original_records[:count], records[:count]):
|
|
@@ -309,12 +309,12 @@ def test_postgresql_adapter(fixture_postgresql_test_proc, fixture_postgresql_tes
|
|
|
309
309
|
|
|
310
310
|
postgresql_insert_on_conflict_do_nothing()
|
|
311
311
|
|
|
312
|
-
with
|
|
312
|
+
with maker.make_session() as session:
|
|
313
313
|
# PK violation, but suppressed by the compiler plugin
|
|
314
314
|
session.add(orm_clone(result))
|
|
315
315
|
session.commit()
|
|
316
316
|
|
|
317
|
-
with
|
|
317
|
+
with maker.make_session() as session:
|
|
318
318
|
# Unique index violation, but suppressed by the plugin
|
|
319
319
|
# However, since insertion is not performed, it fails to return and
|
|
320
320
|
# flush the auto-generated primary key of the ORM, which raises 'FlushError'
|
|
@@ -324,16 +324,16 @@ def test_postgresql_adapter(fixture_postgresql_test_proc, fixture_postgresql_tes
|
|
|
324
324
|
|
|
325
325
|
postgresql_insert_on_conflict_do_nothing(enabled=False)
|
|
326
326
|
|
|
327
|
-
with
|
|
327
|
+
with maker.make_session() as session:
|
|
328
328
|
# PK violation, which causes 'IntegrityError'
|
|
329
329
|
with pytest.raises(IntegrityError):
|
|
330
330
|
session.add(orm_clone(result))
|
|
331
331
|
session.commit()
|
|
332
332
|
|
|
333
|
-
with
|
|
333
|
+
with maker.make_session() as session:
|
|
334
334
|
# Unique index violation, which causes 'IntegrityError'
|
|
335
335
|
with pytest.raises(IntegrityError):
|
|
336
336
|
session.add(orm_clone(result, no_autoincrement=True))
|
|
337
337
|
session.commit()
|
|
338
338
|
|
|
339
|
-
|
|
339
|
+
maker.drop_model(PostgresqlBaseModel)
|
{iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/strutils_test.py
RENAMED
|
@@ -206,21 +206,28 @@ class StrUtilsTest(unittest.TestCase):
|
|
|
206
206
|
(" \t", {}),
|
|
207
207
|
("foo=bar", {"foo": "bar"}),
|
|
208
208
|
(
|
|
209
|
-
"dummy_key_1=
|
|
210
|
-
{"dummy_key_1": "
|
|
209
|
+
"dummy_key_1=dummy_value_1,dummy_key_2=dummy_value_2",
|
|
210
|
+
{"dummy_key_1": "dummy_value_1", "dummy_key_2": "dummy_value_2"},
|
|
211
211
|
),
|
|
212
212
|
(
|
|
213
|
-
"dummy_key_1=
|
|
214
|
-
{"dummy_key_1": "
|
|
213
|
+
"dummy_key_1=dummy_value_1,dummy_key_2=dummy_value_2,dummy_key_3",
|
|
214
|
+
{"dummy_key_1": "dummy_value_1", "dummy_key_2": "dummy_value_2", "dummy_key_3": "True"},
|
|
215
215
|
),
|
|
216
216
|
(
|
|
217
|
-
"dummy_key_1=
|
|
217
|
+
"dummy_key_1=dummy_value_1,dummy_key_2=dummy_value_2,dummy_key_3=do not use spaces in strings CLI",
|
|
218
218
|
{
|
|
219
|
-
"dummy_key_1": "
|
|
219
|
+
"dummy_key_1": "dummy_value_1",
|
|
220
220
|
"dummy_key_2": "dummy_value_2",
|
|
221
221
|
"dummy_key_3": "do not use spaces in strings CLI",
|
|
222
222
|
},
|
|
223
223
|
),
|
|
224
|
+
(
|
|
225
|
+
"dummy_key_1=dummy_value_1_key=dummy_value_1_value,dummy_key_2=dummy_value_2_key=dummy_value_2_value",
|
|
226
|
+
{
|
|
227
|
+
"dummy_key_1": "dummy_value_1_key=dummy_value_1_value",
|
|
228
|
+
"dummy_key_2": "dummy_value_2_key=dummy_value_2_value",
|
|
229
|
+
},
|
|
230
|
+
),
|
|
224
231
|
)
|
|
225
232
|
@ddt.unpack
|
|
226
233
|
def test_parse_params_string(self, s, params_dict):
|
|
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
|
{iker_python_common-1.0.6 → iker_python_common-1.0.8}/resources/unittest/shutils/dir.foo/file.bar
RENAMED
|
File without changes
|
{iker_python_common-1.0.6 → iker_python_common-1.0.8}/resources/unittest/shutils/dir.foo/file.baz
RENAMED
|
File without changes
|
{iker_python_common-1.0.6 → iker_python_common-1.0.8}/resources/unittest/shutils/dir.foo/file.foo
RENAMED
|
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
|
{iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker_python_common.egg-info/not-zip-safe
RENAMED
|
File without changes
|
{iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker_python_common.egg-info/requires.txt
RENAMED
|
File without changes
|
{iker_python_common-1.0.6 → iker_python_common-1.0.8}/src/iker_python_common.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
{iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/config_test.py
RENAMED
|
File without changes
|
|
File without changes
|
{iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/dtutils_test.py
RENAMED
|
File without changes
|
{iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/funcutils_test.py
RENAMED
|
File without changes
|
{iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/logger_test.py
RENAMED
|
File without changes
|
{iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/numutils_test.py
RENAMED
|
File without changes
|
{iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/randutils_test.py
RENAMED
|
File without changes
|
{iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/retry_test.py
RENAMED
|
File without changes
|
{iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/s3utils_test.py
RENAMED
|
File without changes
|
{iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/sequtils_test.py
RENAMED
|
File without changes
|
{iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/shutils_test.py
RENAMED
|
File without changes
|
{iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/span_test.py
RENAMED
|
File without changes
|
{iker_python_common-1.0.6 → iker_python_common-1.0.8}/test/iker_tests/common/utils/testutils_test.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|