polyapi-python 0.3.14.dev2__tar.gz → 0.3.14.dev4__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.
- {polyapi_python-0.3.14.dev2/polyapi_python.egg-info → polyapi_python-0.3.14.dev4}/PKG-INFO +1 -1
- polyapi_python-0.3.14.dev4/polyapi/__init__.py +163 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/cli.py +1 -3
- polyapi_python-0.3.14.dev4/polyapi/cli_constants.py +10 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4/polyapi_python.egg-info}/PKG-INFO +1 -1
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi_python.egg-info/SOURCES.txt +2 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/pyproject.toml +1 -1
- polyapi_python-0.3.14.dev4/tests/test_poly_custom.py +130 -0
- polyapi_python-0.3.14.dev2/polyapi/__init__.py +0 -101
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/LICENSE +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/README.md +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/__main__.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/api.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/auth.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/client.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/config.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/constants.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/deployables.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/error_handler.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/exceptions.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/execute.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/function_cli.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/generate.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/http_client.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/parser.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/poly_schemas.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/poly_tables.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/prepare.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/py.typed +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/rendered_spec.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/schema.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/server.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/sync.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/typedefs.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/utils.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/variables.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi/webhook.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi_python.egg-info/dependency_links.txt +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi_python.egg-info/requires.txt +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi_python.egg-info/top_level.txt +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/setup.cfg +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/tests/test_api.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/tests/test_async_proof.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/tests/test_auth.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/tests/test_deployables.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/tests/test_generate.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/tests/test_parser.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/tests/test_rendered_spec.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/tests/test_schema.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/tests/test_server.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/tests/test_tabi.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/tests/test_utils.py +0 -0
- {polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/tests/test_variables.py +0 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
from contextvars import ContextVar, Token
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Any, Dict, Literal, Optional, overload
|
|
7
|
+
|
|
8
|
+
import truststore
|
|
9
|
+
from typing_extensions import TypedDict
|
|
10
|
+
|
|
11
|
+
from .cli_constants import CLI_COMMANDS
|
|
12
|
+
|
|
13
|
+
truststore.inject_into_ssl()
|
|
14
|
+
|
|
15
|
+
__all__ = ["poly"]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
if len(sys.argv) > 1 and sys.argv[1] not in CLI_COMMANDS:
|
|
19
|
+
currdir = os.path.dirname(os.path.abspath(__file__))
|
|
20
|
+
if not os.path.isdir(os.path.join(currdir, "poly")):
|
|
21
|
+
print("No 'poly' found. Please run 'python3 -m polyapi generate' to generate the 'poly' library for your tenant.")
|
|
22
|
+
sys.exit(1)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class PolyCustomDict(TypedDict, total=False):
|
|
26
|
+
"""Type definition for polyCustom dictionary."""
|
|
27
|
+
|
|
28
|
+
executionId: Optional[str] # Read-only unless explicitly unlocked
|
|
29
|
+
executionApiKey: Optional[str]
|
|
30
|
+
userSessionId: Optional[str]
|
|
31
|
+
responseStatusCode: Optional[int]
|
|
32
|
+
responseContentType: Optional[str]
|
|
33
|
+
responseHeaders: Dict[str, Any]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@dataclass
|
|
37
|
+
class _PolyCustomState:
|
|
38
|
+
internal_store: Dict[str, Any]
|
|
39
|
+
execution_id_locked: bool = False
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class PolyCustom:
|
|
43
|
+
def __init__(self) -> None:
|
|
44
|
+
object.__setattr__(
|
|
45
|
+
self,
|
|
46
|
+
"_default_store",
|
|
47
|
+
{
|
|
48
|
+
"executionId": None,
|
|
49
|
+
"executionApiKey": None,
|
|
50
|
+
"userSessionId": None,
|
|
51
|
+
"responseStatusCode": 200,
|
|
52
|
+
"responseContentType": None,
|
|
53
|
+
"responseHeaders": {},
|
|
54
|
+
},
|
|
55
|
+
)
|
|
56
|
+
object.__setattr__(self, "_state_var", ContextVar("_poly_custom_state", default=None))
|
|
57
|
+
|
|
58
|
+
def _make_state(self) -> _PolyCustomState:
|
|
59
|
+
return _PolyCustomState(internal_store=copy.deepcopy(self._default_store))
|
|
60
|
+
|
|
61
|
+
def _get_state(self) -> _PolyCustomState:
|
|
62
|
+
state = self._state_var.get()
|
|
63
|
+
if state is None:
|
|
64
|
+
state = self._make_state()
|
|
65
|
+
self._state_var.set(state)
|
|
66
|
+
return state
|
|
67
|
+
|
|
68
|
+
def push_scope(self, initial_values: Optional[Dict[str, Any]] = None) -> Token:
|
|
69
|
+
state = self._make_state()
|
|
70
|
+
if initial_values:
|
|
71
|
+
state.internal_store.update(copy.deepcopy(initial_values))
|
|
72
|
+
if state.internal_store.get("executionId") is not None:
|
|
73
|
+
state.execution_id_locked = True
|
|
74
|
+
return self._state_var.set(state)
|
|
75
|
+
|
|
76
|
+
def pop_scope(self, token: Token) -> None:
|
|
77
|
+
self._state_var.reset(token)
|
|
78
|
+
|
|
79
|
+
def set_once(self, key: str, value: Any) -> None:
|
|
80
|
+
state = self._get_state()
|
|
81
|
+
if key == "executionId" and state.execution_id_locked:
|
|
82
|
+
return
|
|
83
|
+
state.internal_store[key] = value
|
|
84
|
+
if key == "executionId":
|
|
85
|
+
state.execution_id_locked = True
|
|
86
|
+
|
|
87
|
+
def get(self, key: str, default: Any = None) -> Any:
|
|
88
|
+
return self._get_state().internal_store.get(key, default)
|
|
89
|
+
|
|
90
|
+
def lock_execution_id(self) -> None:
|
|
91
|
+
self._get_state().execution_id_locked = True
|
|
92
|
+
|
|
93
|
+
def unlock_execution_id(self) -> None:
|
|
94
|
+
self._get_state().execution_id_locked = False
|
|
95
|
+
|
|
96
|
+
@overload
|
|
97
|
+
def __getitem__(self, key: Literal["executionId"]) -> Optional[str]: ...
|
|
98
|
+
|
|
99
|
+
@overload
|
|
100
|
+
def __getitem__(self, key: Literal["executionApiKey"]) -> Optional[str]: ...
|
|
101
|
+
|
|
102
|
+
@overload
|
|
103
|
+
def __getitem__(self, key: Literal["userSessionId"]) -> Optional[str]: ...
|
|
104
|
+
|
|
105
|
+
@overload
|
|
106
|
+
def __getitem__(self, key: Literal["responseStatusCode"]) -> Optional[int]: ...
|
|
107
|
+
|
|
108
|
+
@overload
|
|
109
|
+
def __getitem__(self, key: Literal["responseContentType"]) -> Optional[str]: ...
|
|
110
|
+
|
|
111
|
+
@overload
|
|
112
|
+
def __getitem__(self, key: Literal["responseHeaders"]) -> Dict[str, Any]: ...
|
|
113
|
+
|
|
114
|
+
def __getitem__(self, key: str) -> Any:
|
|
115
|
+
return self.get(key)
|
|
116
|
+
|
|
117
|
+
@overload
|
|
118
|
+
def __setitem__(self, key: Literal["executionApiKey"], value: Optional[str]) -> None: ...
|
|
119
|
+
|
|
120
|
+
@overload
|
|
121
|
+
def __setitem__(self, key: Literal["userSessionId"], value: Optional[str]) -> None: ...
|
|
122
|
+
|
|
123
|
+
@overload
|
|
124
|
+
def __setitem__(self, key: Literal["responseStatusCode"], value: Optional[int]) -> None: ...
|
|
125
|
+
|
|
126
|
+
@overload
|
|
127
|
+
def __setitem__(self, key: Literal["responseContentType"], value: Optional[str]) -> None: ...
|
|
128
|
+
|
|
129
|
+
@overload
|
|
130
|
+
def __setitem__(self, key: Literal["responseHeaders"], value: Dict[str, Any]) -> None: ...
|
|
131
|
+
|
|
132
|
+
def __setitem__(self, key: str, value: Any) -> None:
|
|
133
|
+
self.set_once(key, value)
|
|
134
|
+
|
|
135
|
+
def __getattr__(self, key: str) -> Any:
|
|
136
|
+
if key in self._default_store:
|
|
137
|
+
return self.get(key)
|
|
138
|
+
raise AttributeError(f"{type(self).__name__!r} object has no attribute {key!r}")
|
|
139
|
+
|
|
140
|
+
def __setattr__(self, key: str, value: Any) -> None:
|
|
141
|
+
if key.startswith("_"):
|
|
142
|
+
object.__setattr__(self, key, value)
|
|
143
|
+
return
|
|
144
|
+
self.set_once(key, value)
|
|
145
|
+
|
|
146
|
+
def __repr__(self) -> str:
|
|
147
|
+
return f"PolyCustom({self._get_state().internal_store})"
|
|
148
|
+
|
|
149
|
+
def copy(self) -> "PolyCustom":
|
|
150
|
+
new = PolyCustom()
|
|
151
|
+
state = self._get_state()
|
|
152
|
+
new._state_var.set(
|
|
153
|
+
_PolyCustomState(
|
|
154
|
+
internal_store=copy.deepcopy(state.internal_store),
|
|
155
|
+
execution_id_locked=state.execution_id_locked,
|
|
156
|
+
)
|
|
157
|
+
)
|
|
158
|
+
return new
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
_PolyCustom = PolyCustom
|
|
162
|
+
|
|
163
|
+
polyCustom: PolyCustom = PolyCustom()
|
|
@@ -3,6 +3,7 @@ import argparse
|
|
|
3
3
|
|
|
4
4
|
from polyapi.utils import print_green, print_red
|
|
5
5
|
|
|
6
|
+
from .cli_constants import CLI_COMMANDS
|
|
6
7
|
from .config import initialize_config, set_api_key_and_url
|
|
7
8
|
from .generate import generate, clear
|
|
8
9
|
from .function_cli import function_add_or_update, function_execute
|
|
@@ -11,9 +12,6 @@ from .prepare import prepare_deployables
|
|
|
11
12
|
from .sync import sync_deployables
|
|
12
13
|
|
|
13
14
|
|
|
14
|
-
CLI_COMMANDS = ["setup", "generate", "function", "clear", "help", "update_rendered_spec"]
|
|
15
|
-
|
|
16
|
-
|
|
17
15
|
def _get_version_string():
|
|
18
16
|
"""Get the version string for the package."""
|
|
19
17
|
try:
|
{polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi_python.egg-info/SOURCES.txt
RENAMED
|
@@ -6,6 +6,7 @@ polyapi/__main__.py
|
|
|
6
6
|
polyapi/api.py
|
|
7
7
|
polyapi/auth.py
|
|
8
8
|
polyapi/cli.py
|
|
9
|
+
polyapi/cli_constants.py
|
|
9
10
|
polyapi/client.py
|
|
10
11
|
polyapi/config.py
|
|
11
12
|
polyapi/constants.py
|
|
@@ -40,6 +41,7 @@ tests/test_auth.py
|
|
|
40
41
|
tests/test_deployables.py
|
|
41
42
|
tests/test_generate.py
|
|
42
43
|
tests/test_parser.py
|
|
44
|
+
tests/test_poly_custom.py
|
|
43
45
|
tests/test_rendered_spec.py
|
|
44
46
|
tests/test_schema.py
|
|
45
47
|
tests/test_server.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "polyapi-python"
|
|
7
|
-
version = "0.3.14.
|
|
7
|
+
version = "0.3.14.dev4"
|
|
8
8
|
description = "The Python Client for PolyAPI, the IPaaS by Developers for Developers"
|
|
9
9
|
authors = [{ name = "Dan Fellin", email = "dan@polyapi.io" }]
|
|
10
10
|
dependencies = [
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import importlib
|
|
3
|
+
import sys
|
|
4
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def _reload_polyapi():
|
|
8
|
+
sys.modules.pop("polyapi", None)
|
|
9
|
+
sys.modules.pop("polyapi.cli", None)
|
|
10
|
+
return importlib.import_module("polyapi")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_import_polyapi_does_not_import_cli():
|
|
14
|
+
polyapi = _reload_polyapi()
|
|
15
|
+
|
|
16
|
+
assert polyapi is not None
|
|
17
|
+
assert "polyapi.cli" not in sys.modules
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def test_cli_constants_shared_between_runtime_and_cli():
|
|
21
|
+
cli_constants = importlib.import_module("polyapi.cli_constants")
|
|
22
|
+
cli_module = importlib.import_module("polyapi.cli")
|
|
23
|
+
|
|
24
|
+
assert tuple(cli_module.CLI_COMMANDS) == cli_constants.CLI_COMMANDS
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def test_poly_custom_nested_scopes_restore_previous_state():
|
|
28
|
+
polyapi = _reload_polyapi()
|
|
29
|
+
poly_custom = polyapi.polyCustom
|
|
30
|
+
|
|
31
|
+
outer_token = poly_custom.push_scope(
|
|
32
|
+
{
|
|
33
|
+
"executionId": "outer",
|
|
34
|
+
"responseHeaders": {"x-scope": "outer"},
|
|
35
|
+
"responseStatusCode": None,
|
|
36
|
+
}
|
|
37
|
+
)
|
|
38
|
+
try:
|
|
39
|
+
assert poly_custom["executionId"] == "outer"
|
|
40
|
+
|
|
41
|
+
inner_token = poly_custom.push_scope(
|
|
42
|
+
{
|
|
43
|
+
"executionId": "inner",
|
|
44
|
+
"responseHeaders": {"x-scope": "inner"},
|
|
45
|
+
"responseStatusCode": 202,
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
try:
|
|
49
|
+
assert poly_custom["executionId"] == "inner"
|
|
50
|
+
assert poly_custom["responseHeaders"] == {"x-scope": "inner"}
|
|
51
|
+
assert poly_custom.responseStatusCode == 202
|
|
52
|
+
|
|
53
|
+
poly_custom["executionId"] = "should-not-overwrite"
|
|
54
|
+
assert poly_custom["executionId"] == "inner"
|
|
55
|
+
|
|
56
|
+
poly_custom.unlock_execution_id()
|
|
57
|
+
poly_custom["executionId"] = "inner-updated"
|
|
58
|
+
assert poly_custom["executionId"] == "inner-updated"
|
|
59
|
+
finally:
|
|
60
|
+
poly_custom.pop_scope(inner_token)
|
|
61
|
+
|
|
62
|
+
assert poly_custom["executionId"] == "outer"
|
|
63
|
+
assert poly_custom["responseHeaders"] == {"x-scope": "outer"}
|
|
64
|
+
assert poly_custom["responseStatusCode"] is None
|
|
65
|
+
finally:
|
|
66
|
+
poly_custom.pop_scope(outer_token)
|
|
67
|
+
|
|
68
|
+
assert poly_custom["executionId"] is None
|
|
69
|
+
assert poly_custom["responseHeaders"] == {}
|
|
70
|
+
assert poly_custom["responseStatusCode"] == 200
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def test_poly_custom_isolated_across_async_tasks():
|
|
74
|
+
polyapi = _reload_polyapi()
|
|
75
|
+
poly_custom = polyapi.polyCustom
|
|
76
|
+
|
|
77
|
+
async def worker(execution_id: str) -> tuple[str, str]:
|
|
78
|
+
token = poly_custom.push_scope(
|
|
79
|
+
{
|
|
80
|
+
"executionId": execution_id,
|
|
81
|
+
"responseHeaders": {"worker": execution_id},
|
|
82
|
+
"responseStatusCode": None,
|
|
83
|
+
}
|
|
84
|
+
)
|
|
85
|
+
try:
|
|
86
|
+
await asyncio.sleep(0)
|
|
87
|
+
poly_custom["responseHeaders"]["seen"] = execution_id
|
|
88
|
+
await asyncio.sleep(0)
|
|
89
|
+
return poly_custom["executionId"], poly_custom["responseHeaders"]["seen"]
|
|
90
|
+
finally:
|
|
91
|
+
poly_custom.pop_scope(token)
|
|
92
|
+
|
|
93
|
+
async def run_workers() -> tuple[tuple[str, str], tuple[str, str]]:
|
|
94
|
+
first_result, second_result = await asyncio.gather(worker("async-a"), worker("async-b"))
|
|
95
|
+
return first_result, second_result
|
|
96
|
+
|
|
97
|
+
first, second = asyncio.run(run_workers())
|
|
98
|
+
|
|
99
|
+
assert first == ("async-a", "async-a")
|
|
100
|
+
assert second == ("async-b", "async-b")
|
|
101
|
+
assert poly_custom["executionId"] is None
|
|
102
|
+
assert poly_custom["responseHeaders"] == {}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def test_poly_custom_isolated_across_threads():
|
|
106
|
+
polyapi = _reload_polyapi()
|
|
107
|
+
poly_custom = polyapi.polyCustom
|
|
108
|
+
|
|
109
|
+
def worker(execution_id: str) -> tuple[str, str]:
|
|
110
|
+
token = poly_custom.push_scope(
|
|
111
|
+
{
|
|
112
|
+
"executionId": execution_id,
|
|
113
|
+
"responseHeaders": {"worker": execution_id},
|
|
114
|
+
"responseStatusCode": None,
|
|
115
|
+
}
|
|
116
|
+
)
|
|
117
|
+
try:
|
|
118
|
+
poly_custom["responseHeaders"]["seen"] = execution_id
|
|
119
|
+
return poly_custom["executionId"], poly_custom["responseHeaders"]["seen"]
|
|
120
|
+
finally:
|
|
121
|
+
poly_custom.pop_scope(token)
|
|
122
|
+
|
|
123
|
+
with ThreadPoolExecutor(max_workers=2) as executor:
|
|
124
|
+
first = executor.submit(worker, "thread-a").result()
|
|
125
|
+
second = executor.submit(worker, "thread-b").result()
|
|
126
|
+
|
|
127
|
+
assert first == ("thread-a", "thread-a")
|
|
128
|
+
assert second == ("thread-b", "thread-b")
|
|
129
|
+
assert poly_custom["executionId"] is None
|
|
130
|
+
assert poly_custom["responseHeaders"] == {}
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import sys
|
|
3
|
-
import copy
|
|
4
|
-
import truststore
|
|
5
|
-
from typing import Any, Dict, Optional, overload, Literal
|
|
6
|
-
from typing_extensions import TypedDict
|
|
7
|
-
truststore.inject_into_ssl()
|
|
8
|
-
from .cli import CLI_COMMANDS
|
|
9
|
-
|
|
10
|
-
__all__ = ["poly"]
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
if len(sys.argv) > 1 and sys.argv[1] not in CLI_COMMANDS:
|
|
14
|
-
currdir = os.path.dirname(os.path.abspath(__file__))
|
|
15
|
-
if not os.path.isdir(os.path.join(currdir, "poly")):
|
|
16
|
-
print("No 'poly' found. Please run 'python3 -m polyapi generate' to generate the 'poly' library for your tenant.")
|
|
17
|
-
sys.exit(1)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class PolyCustomDict(TypedDict, total=False):
|
|
21
|
-
"""Type definition for polyCustom dictionary."""
|
|
22
|
-
executionId: Optional[str] # Read-only
|
|
23
|
-
executionApiKey: Optional[str]
|
|
24
|
-
responseStatusCode: int
|
|
25
|
-
responseContentType: Optional[str]
|
|
26
|
-
responseHeaders: Dict[str, str]
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
class _PolyCustom:
|
|
30
|
-
def __init__(self):
|
|
31
|
-
self._internal_store = {
|
|
32
|
-
"executionId": None,
|
|
33
|
-
"executionApiKey": None,
|
|
34
|
-
"responseStatusCode": 200,
|
|
35
|
-
"responseContentType": None,
|
|
36
|
-
"responseHeaders": {},
|
|
37
|
-
}
|
|
38
|
-
self._execution_id_locked = False
|
|
39
|
-
|
|
40
|
-
def set_once(self, key: str, value: Any) -> None:
|
|
41
|
-
if key == "executionId" and self._execution_id_locked:
|
|
42
|
-
# Silently ignore attempts to overwrite locked executionId
|
|
43
|
-
return
|
|
44
|
-
self._internal_store[key] = value
|
|
45
|
-
if key == "executionId":
|
|
46
|
-
# Lock executionId after setting it
|
|
47
|
-
self.lock_execution_id()
|
|
48
|
-
|
|
49
|
-
def get(self, key: str, default: Any = None) -> Any:
|
|
50
|
-
return self._internal_store.get(key, default)
|
|
51
|
-
|
|
52
|
-
def lock_execution_id(self) -> None:
|
|
53
|
-
self._execution_id_locked = True
|
|
54
|
-
|
|
55
|
-
def unlock_execution_id(self) -> None:
|
|
56
|
-
self._execution_id_locked = False
|
|
57
|
-
|
|
58
|
-
@overload
|
|
59
|
-
def __getitem__(self, key: Literal["executionId"]) -> Optional[str]: ...
|
|
60
|
-
|
|
61
|
-
@overload
|
|
62
|
-
def __getitem__(self, key: Literal["executionApiKey"]) -> Optional[str]: ...
|
|
63
|
-
|
|
64
|
-
@overload
|
|
65
|
-
def __getitem__(self, key: Literal["responseStatusCode"]) -> int: ...
|
|
66
|
-
|
|
67
|
-
@overload
|
|
68
|
-
def __getitem__(self, key: Literal["responseContentType"]) -> Optional[str]: ...
|
|
69
|
-
|
|
70
|
-
@overload
|
|
71
|
-
def __getitem__(self, key: Literal["responseHeaders"]) -> Dict[str, str]: ...
|
|
72
|
-
|
|
73
|
-
def __getitem__(self, key: str) -> Any:
|
|
74
|
-
return self.get(key)
|
|
75
|
-
|
|
76
|
-
@overload
|
|
77
|
-
def __setitem__(self, key: Literal["executionApiKey"], value: Optional[str]) -> None: ...
|
|
78
|
-
|
|
79
|
-
@overload
|
|
80
|
-
def __setitem__(self, key: Literal["responseStatusCode"], value: int) -> None: ...
|
|
81
|
-
|
|
82
|
-
@overload
|
|
83
|
-
def __setitem__(self, key: Literal["responseContentType"], value: Optional[str]) -> None: ...
|
|
84
|
-
|
|
85
|
-
@overload
|
|
86
|
-
def __setitem__(self, key: Literal["responseHeaders"], value: Dict[str, str]) -> None: ...
|
|
87
|
-
|
|
88
|
-
def __setitem__(self, key: str, value: Any) -> None:
|
|
89
|
-
self.set_once(key, value)
|
|
90
|
-
|
|
91
|
-
def __repr__(self) -> str:
|
|
92
|
-
return f"PolyCustom({self._internal_store})"
|
|
93
|
-
|
|
94
|
-
def copy(self) -> '_PolyCustom':
|
|
95
|
-
new = _PolyCustom()
|
|
96
|
-
new._internal_store = copy.deepcopy(self._internal_store)
|
|
97
|
-
new._execution_id_locked = self._execution_id_locked
|
|
98
|
-
return new
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
polyCustom: PolyCustomDict = _PolyCustom()
|
|
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
|
{polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi_python.egg-info/requires.txt
RENAMED
|
File without changes
|
{polyapi_python-0.3.14.dev2 → polyapi_python-0.3.14.dev4}/polyapi_python.egg-info/top_level.txt
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
|