polyapi-python 0.3.15__tar.gz → 0.3.16.dev2__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.15/polyapi_python.egg-info → polyapi_python-0.3.16.dev2}/PKG-INFO +1 -1
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/generate.py +5 -3
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/http_client.py +16 -6
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/utils.py +11 -5
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2/polyapi_python.egg-info}/PKG-INFO +1 -1
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/pyproject.toml +1 -1
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/tests/test_api.py +5 -5
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/tests/test_async_proof.py +86 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/tests/test_generate.py +46 -2
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/tests/test_server.py +3 -3
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/LICENSE +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/README.md +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/__init__.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/__main__.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/api.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/auth.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/cli.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/cli_constants.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/client.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/config.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/constants.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/deployables.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/error_handler.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/exceptions.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/execute.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/function_cli.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/parser.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/poly_schemas.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/poly_tables.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/prepare.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/py.typed +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/rendered_spec.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/schema.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/server.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/sync.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/typedefs.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/variables.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi/webhook.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi_python.egg-info/SOURCES.txt +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi_python.egg-info/dependency_links.txt +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi_python.egg-info/requires.txt +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/polyapi_python.egg-info/top_level.txt +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/setup.cfg +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/tests/test_auth.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/tests/test_deployables.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/tests/test_parser.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/tests/test_poly_custom.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/tests/test_rendered_spec.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/tests/test_schema.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/tests/test_tabi.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/tests/test_utils.py +0 -0
- {polyapi_python-0.3.15 → polyapi_python-0.3.16.dev2}/tests/test_variables.py +0 -0
|
@@ -16,7 +16,7 @@ from .webhook import render_webhook_handle
|
|
|
16
16
|
from .typedefs import PropertySpecification, SchemaSpecDto, SpecificationDto, VariableSpecDto, TableSpecDto
|
|
17
17
|
from .api import render_api_function
|
|
18
18
|
from .server import render_server_function
|
|
19
|
-
from .utils import add_import_to_init, get_auth_headers, init_the_init, print_green, to_func_namespace
|
|
19
|
+
from .utils import add_import_to_init, get_auth_headers, init_the_init, print_green, to_func_namespace, to_type_module_alias
|
|
20
20
|
from .variables import generate_variables
|
|
21
21
|
from .poly_tables import generate_tables
|
|
22
22
|
from . import http_client
|
|
@@ -506,8 +506,10 @@ def add_function_file(
|
|
|
506
506
|
with open(init_path, "r", encoding='utf-8') as f:
|
|
507
507
|
init_content = f.read()
|
|
508
508
|
|
|
509
|
-
#
|
|
510
|
-
|
|
509
|
+
# Import the generated type module under a private alias so PascalCase function
|
|
510
|
+
# names do not shadow their own module symbol in __init__.py.
|
|
511
|
+
type_module_alias = to_type_module_alias(function_name)
|
|
512
|
+
new_init_content = init_content + f"\n\nfrom . import {func_namespace} as {type_module_alias}\n\n{func_str}"
|
|
511
513
|
|
|
512
514
|
# Use temporary files for atomic writes
|
|
513
515
|
# Write to __init__.py atomically
|
|
@@ -3,6 +3,7 @@ import httpx
|
|
|
3
3
|
|
|
4
4
|
_sync_client: httpx.Client | None = None
|
|
5
5
|
_async_client: httpx.AsyncClient | None = None
|
|
6
|
+
_async_client_loop: asyncio.AbstractEventLoop | None = None
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
def _get_sync_client() -> httpx.Client:
|
|
@@ -13,9 +14,11 @@ def _get_sync_client() -> httpx.Client:
|
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
def _get_async_client() -> httpx.AsyncClient:
|
|
16
|
-
global _async_client
|
|
17
|
-
|
|
17
|
+
global _async_client, _async_client_loop
|
|
18
|
+
current_loop = asyncio.get_running_loop()
|
|
19
|
+
if _async_client is None or _async_client_loop is not current_loop:
|
|
18
20
|
_async_client = httpx.AsyncClient(timeout=None)
|
|
21
|
+
_async_client_loop = current_loop
|
|
19
22
|
return _async_client
|
|
20
23
|
|
|
21
24
|
|
|
@@ -66,8 +69,15 @@ def close():
|
|
|
66
69
|
_sync_client = None
|
|
67
70
|
|
|
68
71
|
async def close_async():
|
|
69
|
-
global _sync_client, _async_client
|
|
72
|
+
global _sync_client, _async_client, _async_client_loop
|
|
70
73
|
close()
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
+
client = _async_client
|
|
75
|
+
client_loop = _async_client_loop
|
|
76
|
+
_async_client = None
|
|
77
|
+
_async_client_loop = None
|
|
78
|
+
if client is None:
|
|
79
|
+
return
|
|
80
|
+
|
|
81
|
+
current_loop = asyncio.get_running_loop()
|
|
82
|
+
if client_loop is current_loop:
|
|
83
|
+
await client.aclose()
|
|
@@ -71,11 +71,17 @@ def print_red(s: str):
|
|
|
71
71
|
print(Fore.RED + s + Style.RESET_ALL)
|
|
72
72
|
|
|
73
73
|
|
|
74
|
+
def to_type_module_alias(function_name: str) -> str:
|
|
75
|
+
"""Return the internal alias used for a function's generated type module."""
|
|
76
|
+
return f"_{to_func_namespace(function_name)}_types"
|
|
77
|
+
|
|
78
|
+
|
|
74
79
|
def add_type_import_path(function_name: str, arg: str) -> str:
|
|
75
80
|
"""if not basic type, coerce to camelCase and add the import path"""
|
|
76
81
|
# from now, we start qualifying non-basic types :))
|
|
77
82
|
# e.g. Callable[[EmailAddress, Dict, Dict, Dict], None]
|
|
78
83
|
# becomes Callable[[Set_profile_email.EmailAddress, Dict, Dict, Dict], None]
|
|
84
|
+
type_module_alias = to_type_module_alias(function_name)
|
|
79
85
|
|
|
80
86
|
if arg.startswith("Callable"):
|
|
81
87
|
inner = arg[len("Callable["):-1] # strip outer Callable[...]
|
|
@@ -84,7 +90,7 @@ def add_type_import_path(function_name: str, arg: str) -> str:
|
|
|
84
90
|
for p in parts:
|
|
85
91
|
clean = p.strip("[] ")
|
|
86
92
|
if clean and clean not in BASIC_PYTHON_TYPES:
|
|
87
|
-
replacement = f"{
|
|
93
|
+
replacement = f"{type_module_alias}.{camelCase(clean)}"
|
|
88
94
|
p = p.replace(clean, replacement)
|
|
89
95
|
qualified.append(p)
|
|
90
96
|
return "Callable[" + ",".join(qualified) + "]"
|
|
@@ -100,11 +106,11 @@ def add_type_import_path(function_name: str, arg: str) -> str:
|
|
|
100
106
|
else:
|
|
101
107
|
if '"' in sub:
|
|
102
108
|
sub = sub.replace('"', "")
|
|
103
|
-
return f'List["{
|
|
109
|
+
return f'List["{type_module_alias}.{camelCase(sub)}"]'
|
|
104
110
|
else:
|
|
105
|
-
return f"List[{
|
|
111
|
+
return f"List[{type_module_alias}.{camelCase(sub)}]"
|
|
106
112
|
|
|
107
|
-
return f"{
|
|
113
|
+
return f"{type_module_alias}.{camelCase(arg)}"
|
|
108
114
|
|
|
109
115
|
|
|
110
116
|
def get_type_and_def(
|
|
@@ -352,4 +358,4 @@ def return_type_already_defined_in_args(return_type_name: str, args_def: str) ->
|
|
|
352
358
|
basic_match = bool(re.search(basic_pattern, args_def, re.MULTILINE))
|
|
353
359
|
class_pattern = rf"^class {re.escape(return_type_name)}\(TypedDict"
|
|
354
360
|
class_match = bool(re.search(class_pattern, args_def, re.MULTILINE))
|
|
355
|
-
return basic_match or class_match
|
|
361
|
+
return basic_match or class_match
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "polyapi-python"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.16.dev2"
|
|
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 = [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import unittest
|
|
2
2
|
|
|
3
3
|
from polyapi.api import render_api_function
|
|
4
|
-
from polyapi.utils import
|
|
4
|
+
from polyapi.utils import to_type_module_alias
|
|
5
5
|
|
|
6
6
|
ACCUWEATHER = {
|
|
7
7
|
"id": "f7588018-2364-4586-b60d",
|
|
@@ -236,7 +236,7 @@ class T(unittest.TestCase):
|
|
|
236
236
|
)
|
|
237
237
|
self.assertIn(ACCUWEATHER["id"], func_str)
|
|
238
238
|
self.assertIn("locationId: int,", func_str)
|
|
239
|
-
self.assertIn(f"-> {
|
|
239
|
+
self.assertIn(f"-> {to_type_module_alias(name)}.{name}Response", func_str)
|
|
240
240
|
|
|
241
241
|
def test_render_function_zillow(self):
|
|
242
242
|
name = ZILLOW["name"]
|
|
@@ -250,7 +250,7 @@ class T(unittest.TestCase):
|
|
|
250
250
|
)
|
|
251
251
|
self.assertIn(ZILLOW["id"], func_str)
|
|
252
252
|
self.assertIn("locationId: int,", func_str)
|
|
253
|
-
self.assertIn(f"-> {
|
|
253
|
+
self.assertIn(f"-> {to_type_module_alias(name)}.{name}Response", func_str)
|
|
254
254
|
|
|
255
255
|
def test_render_function_twilio_api(self):
|
|
256
256
|
name = TWILIO["name"]
|
|
@@ -265,7 +265,7 @@ class T(unittest.TestCase):
|
|
|
265
265
|
self.assertIn(TWILIO["id"], func_str)
|
|
266
266
|
self.assertIn("conversationSID: str", func_str)
|
|
267
267
|
self.assertIn("authToken: str", func_str)
|
|
268
|
-
self.assertIn(f"-> {
|
|
268
|
+
self.assertIn(f"-> {to_type_module_alias(name)}.{name}Response", func_str)
|
|
269
269
|
|
|
270
270
|
def test_render_function_twilio_get_details(self):
|
|
271
271
|
# same test but try it as a serverFunction rather than an apiFunction
|
|
@@ -279,6 +279,6 @@ class T(unittest.TestCase):
|
|
|
279
279
|
TWILIO_GET_DETAILS["function"]["returnType"],
|
|
280
280
|
)
|
|
281
281
|
self.assertIn(TWILIO_GET_DETAILS["id"], func_str)
|
|
282
|
-
self.assertIn(f"-> {
|
|
282
|
+
self.assertIn(f"-> {to_type_module_alias(name)}.{name}Response", func_str)
|
|
283
283
|
self.assertIn("class SubresourceUris", func_type_defs)
|
|
284
284
|
# self.assertIn('Required["SubresourceUris"]', func_type_defs)
|
|
@@ -56,10 +56,12 @@ class TestHttpClientPairing:
|
|
|
56
56
|
# Reset singletons so each test starts fresh
|
|
57
57
|
http_client._sync_client = None
|
|
58
58
|
http_client._async_client = None
|
|
59
|
+
http_client._async_client_loop = None
|
|
59
60
|
|
|
60
61
|
def teardown_method(self):
|
|
61
62
|
http_client._sync_client = None
|
|
62
63
|
http_client._async_client = None
|
|
64
|
+
http_client._async_client_loop = None
|
|
63
65
|
|
|
64
66
|
@patch.object(httpx.Client, "post", return_value=_fake_response())
|
|
65
67
|
def test_sync_post_uses_sync_client(self, mock_post):
|
|
@@ -79,6 +81,90 @@ class TestHttpClientPairing:
|
|
|
79
81
|
mock_post.assert_called_once()
|
|
80
82
|
assert resp.status_code == 200
|
|
81
83
|
assert http_client._async_client is not None
|
|
84
|
+
assert http_client._async_client_loop is not None
|
|
85
|
+
|
|
86
|
+
def test_async_post_reuses_client_within_same_loop(self):
|
|
87
|
+
first_client = MagicMock()
|
|
88
|
+
first_client.post = AsyncMock(return_value=_fake_response())
|
|
89
|
+
|
|
90
|
+
with patch("polyapi.http_client.httpx.AsyncClient", return_value=first_client) as mock_async_client:
|
|
91
|
+
async def _run():
|
|
92
|
+
first_response = await http_client.async_post("https://example.com/first", json={})
|
|
93
|
+
second_response = await http_client.async_post("https://example.com/second", json={})
|
|
94
|
+
return first_response, second_response, asyncio.get_running_loop()
|
|
95
|
+
|
|
96
|
+
first_response, second_response, current_loop = asyncio.run(_run())
|
|
97
|
+
|
|
98
|
+
assert first_response.status_code == 200
|
|
99
|
+
assert second_response.status_code == 200
|
|
100
|
+
assert mock_async_client.call_count == 1
|
|
101
|
+
assert first_client.post.await_count == 2
|
|
102
|
+
assert http_client._async_client is first_client
|
|
103
|
+
assert http_client._async_client_loop is current_loop
|
|
104
|
+
|
|
105
|
+
def test_async_post_recreates_client_after_loop_change(self):
|
|
106
|
+
first_client = MagicMock()
|
|
107
|
+
first_client.post = AsyncMock(return_value=_fake_response())
|
|
108
|
+
second_client = MagicMock()
|
|
109
|
+
second_client.post = AsyncMock(return_value=_fake_response())
|
|
110
|
+
|
|
111
|
+
with patch(
|
|
112
|
+
"polyapi.http_client.httpx.AsyncClient",
|
|
113
|
+
side_effect=[first_client, second_client],
|
|
114
|
+
) as mock_async_client:
|
|
115
|
+
async def _run_once(url: str):
|
|
116
|
+
response = await http_client.async_post(url, json={})
|
|
117
|
+
return response, http_client._async_client, asyncio.get_running_loop()
|
|
118
|
+
|
|
119
|
+
first_response, first_cached_client, first_loop = asyncio.run(_run_once("https://example.com/first"))
|
|
120
|
+
second_response, second_cached_client, second_loop = asyncio.run(_run_once("https://example.com/second"))
|
|
121
|
+
|
|
122
|
+
assert first_response.status_code == 200
|
|
123
|
+
assert second_response.status_code == 200
|
|
124
|
+
assert mock_async_client.call_count == 2
|
|
125
|
+
assert first_client.post.await_count == 1
|
|
126
|
+
assert second_client.post.await_count == 1
|
|
127
|
+
assert first_cached_client is first_client
|
|
128
|
+
assert second_cached_client is second_client
|
|
129
|
+
assert first_loop is not second_loop
|
|
130
|
+
assert http_client._async_client is second_client
|
|
131
|
+
assert http_client._async_client_loop is second_loop
|
|
132
|
+
|
|
133
|
+
def test_close_async_clears_cached_client_for_current_loop(self):
|
|
134
|
+
async def _run():
|
|
135
|
+
cached_client = MagicMock()
|
|
136
|
+
cached_client.aclose = AsyncMock()
|
|
137
|
+
http_client._async_client = cached_client
|
|
138
|
+
http_client._async_client_loop = asyncio.get_running_loop()
|
|
139
|
+
|
|
140
|
+
await http_client.close_async()
|
|
141
|
+
|
|
142
|
+
return cached_client
|
|
143
|
+
|
|
144
|
+
cached_client = asyncio.run(_run())
|
|
145
|
+
|
|
146
|
+
cached_client.aclose.assert_awaited_once()
|
|
147
|
+
assert http_client._async_client is None
|
|
148
|
+
assert http_client._async_client_loop is None
|
|
149
|
+
|
|
150
|
+
def test_close_async_drops_stale_client_without_cross_loop_close(self):
|
|
151
|
+
stale_client = MagicMock()
|
|
152
|
+
stale_client.aclose = AsyncMock()
|
|
153
|
+
|
|
154
|
+
async def _seed_stale_client():
|
|
155
|
+
http_client._async_client = stale_client
|
|
156
|
+
http_client._async_client_loop = asyncio.get_running_loop()
|
|
157
|
+
|
|
158
|
+
asyncio.run(_seed_stale_client())
|
|
159
|
+
|
|
160
|
+
async def _close_on_new_loop():
|
|
161
|
+
await http_client.close_async()
|
|
162
|
+
|
|
163
|
+
asyncio.run(_close_on_new_loop())
|
|
164
|
+
|
|
165
|
+
stale_client.aclose.assert_not_awaited()
|
|
166
|
+
assert http_client._async_client is None
|
|
167
|
+
assert http_client._async_client_loop is None
|
|
82
168
|
|
|
83
169
|
@patch.object(httpx.Client, "get", return_value=_fake_response())
|
|
84
170
|
def test_sync_get(self, mock_get):
|
|
@@ -2,9 +2,11 @@ import unittest
|
|
|
2
2
|
import os
|
|
3
3
|
import shutil
|
|
4
4
|
import importlib.util
|
|
5
|
+
import tempfile
|
|
5
6
|
from unittest.mock import patch, MagicMock
|
|
6
|
-
from polyapi.
|
|
7
|
-
from polyapi.
|
|
7
|
+
from polyapi.typedefs import SpecificationDto
|
|
8
|
+
from polyapi.utils import get_type_and_def, rewrite_reserved, to_type_module_alias
|
|
9
|
+
from polyapi.generate import render_spec, create_empty_schemas_module, generate_functions, create_function, add_function_file
|
|
8
10
|
from polyapi.poly_schemas import generate_schemas, create_schema
|
|
9
11
|
from polyapi.variables import generate_variables, create_variable
|
|
10
12
|
|
|
@@ -660,3 +662,45 @@ def test_nested_function() -> schemas.api.v1.user.profile:
|
|
|
660
662
|
# The failed function directory should not exist
|
|
661
663
|
func_dir = os.path.join(context_dir, "failing_function")
|
|
662
664
|
self.assertFalse(os.path.exists(func_dir))
|
|
665
|
+
|
|
666
|
+
def test_add_function_file_aliases_pascal_case_type_module(self):
|
|
667
|
+
spec: SpecificationDto = {
|
|
668
|
+
"id": "test-func-id",
|
|
669
|
+
"name": "CreateAJsonPost",
|
|
670
|
+
"context": "test_context",
|
|
671
|
+
"type": "apiFunction",
|
|
672
|
+
"description": "Test function",
|
|
673
|
+
"language": "python",
|
|
674
|
+
"function": {
|
|
675
|
+
"arguments": [],
|
|
676
|
+
"returnType": {
|
|
677
|
+
"kind": "object",
|
|
678
|
+
"schema": {
|
|
679
|
+
"type": "object",
|
|
680
|
+
"properties": {
|
|
681
|
+
"id": {"type": "integer"},
|
|
682
|
+
},
|
|
683
|
+
"required": ["id"],
|
|
684
|
+
"title": "ReturnType",
|
|
685
|
+
},
|
|
686
|
+
},
|
|
687
|
+
},
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
691
|
+
add_function_file(temp_dir, spec["name"], spec)
|
|
692
|
+
|
|
693
|
+
init_path = os.path.join(temp_dir, "__init__.py")
|
|
694
|
+
with open(init_path, "r", encoding="utf-8") as file:
|
|
695
|
+
init_content = file.read()
|
|
696
|
+
|
|
697
|
+
type_module_alias = to_type_module_alias(spec["name"])
|
|
698
|
+
self.assertIn(
|
|
699
|
+
f"from . import {spec['name']} as {type_module_alias}",
|
|
700
|
+
init_content,
|
|
701
|
+
)
|
|
702
|
+
self.assertIn(f"def {spec['name']}(", init_content)
|
|
703
|
+
self.assertIn(
|
|
704
|
+
f"-> {type_module_alias}.{spec['name']}Response",
|
|
705
|
+
init_content,
|
|
706
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import unittest
|
|
2
2
|
|
|
3
|
-
from polyapi.utils import
|
|
3
|
+
from polyapi.utils import to_type_module_alias
|
|
4
4
|
|
|
5
5
|
from .test_api import TWILIO
|
|
6
6
|
from polyapi.server import render_server_function
|
|
@@ -81,7 +81,7 @@ class T(unittest.TestCase):
|
|
|
81
81
|
self.assertIn(TWILIO["id"], func_str)
|
|
82
82
|
self.assertIn("conversationSID: str", func_str)
|
|
83
83
|
self.assertIn("authToken: str", func_str)
|
|
84
|
-
self.assertIn(f"-> {
|
|
84
|
+
self.assertIn(f"-> {to_type_module_alias(name)}.ResponseType", func_str)
|
|
85
85
|
|
|
86
86
|
def test_render_function_get_products_count(self):
|
|
87
87
|
return_type = GET_PRODUCTS_COUNT["function"]["returnType"]
|
|
@@ -116,4 +116,4 @@ class T(unittest.TestCase):
|
|
|
116
116
|
|
|
117
117
|
# stay_date: Required[str]
|
|
118
118
|
# """ Required property """'''
|
|
119
|
-
# self.assertIn(expected_return_type, func_str)
|
|
119
|
+
# self.assertIn(expected_return_type, func_str)
|
|
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.15 → polyapi_python-0.3.16.dev2}/polyapi_python.egg-info/dependency_links.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
|