polyapi-python 0.1.0.dev0__tar.gz → 0.1.0.dev1__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.
Files changed (28) hide show
  1. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/PKG-INFO +1 -1
  2. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/polyapi/api.py +74 -47
  3. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/polyapi/constants.py +6 -1
  4. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/polyapi/execute.py +0 -1
  5. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/polyapi/schema.py +5 -1
  6. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/polyapi_python.egg-info/PKG-INFO +1 -1
  7. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/pyproject.toml +1 -1
  8. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/LICENSE +0 -0
  9. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/README.md +0 -0
  10. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/polyapi/__init__.py +0 -0
  11. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/polyapi/__main__.py +0 -0
  12. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/polyapi/cli.py +0 -0
  13. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/polyapi/config.py +0 -0
  14. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/polyapi/exceptions.py +0 -0
  15. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/polyapi/function_cli.py +0 -0
  16. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/polyapi/generate.py +0 -0
  17. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/polyapi/py.typed +0 -0
  18. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/polyapi/typedefs.py +0 -0
  19. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/polyapi/utils.py +0 -0
  20. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/polyapi/variables.py +0 -0
  21. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/polyapi_python.egg-info/SOURCES.txt +0 -0
  22. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/polyapi_python.egg-info/dependency_links.txt +0 -0
  23. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/polyapi_python.egg-info/requires.txt +0 -0
  24. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/polyapi_python.egg-info/top_level.txt +0 -0
  25. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/setup.cfg +0 -0
  26. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/tests/test_function_cli.py +0 -0
  27. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/tests/test_generate.py +0 -0
  28. {polyapi-python-0.1.0.dev0 → polyapi-python-0.1.0.dev1}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: polyapi-python
3
- Version: 0.1.0.dev0
3
+ Version: 0.1.0.dev1
4
4
  Summary: The PolyAPI Python Client
5
5
  Author-email: Dan Fellin <dan@polyapi.io>
6
6
  License: MIT License
@@ -1,7 +1,9 @@
1
1
  import os
2
2
  from typing import Any, Dict, List, Tuple
3
3
 
4
- from polyapi.constants import JSONSCHEMA_TO_PYTHON_TYPE_MAP
4
+ from regex import W
5
+
6
+ from polyapi.constants import BASIC_PYTHON_TYPES, JSONSCHEMA_TO_PYTHON_TYPE_MAP
5
7
  from polyapi.typedefs import PropertySpecification, PropertyType
6
8
  from polyapi.utils import append_init, camelCase
7
9
  from polyapi.schema import generate_schema_types, clean_title
@@ -12,47 +14,38 @@ TEMPLATE_FUNCTION_TYPE_MAP = {
12
14
  "serverFunction": "server",
13
15
  }
14
16
 
15
- SERVER_TEMPLATE = """
16
- import requests
17
- from typing import List, Dict, Any
18
- from polyapi.execute import execute
19
- from polyapi.exceptions import PolyApiException
17
+ SERVER_DEFS_TEMPLATE = """
18
+ from typing import List, Dict, Any, TypedDict
20
19
  {args_def}
21
20
  {return_type_def}
21
+ """
22
+
23
+ SERVER_FUNCTION_TEMPLATE = """
22
24
  def {function_name}(
23
25
  {args}
24
26
  ) -> {return_type_name}:
25
27
  "{function_description}"
26
28
  resp = execute("{function_type}", "{function_id}", {data})
27
- if resp.status_code != 200 and resp.status_code != 201:
28
- error_content = resp.content.decode("utf-8", errors="ignore")
29
- raise PolyApiException(f"{{resp.status_code}}: {{error_content}}")
30
-
31
29
  return {return_action}
32
30
  """
33
31
 
34
- API_TEMPLATE = """
35
- import requests
32
+ API_DEFS_TEMPLATE = """
36
33
  from typing import List, Dict, Any, TypedDict
37
- from polyapi.execute import execute
38
- from polyapi.exceptions import PolyApiException
39
34
  {args_def}
40
35
  {return_type_def}
41
- class ApiFunctionResponse(TypedDict):
36
+ class {api_response_type}(TypedDict):
42
37
  status: int
43
38
  headers: Dict
44
39
  data: {return_type_name}
40
+ """
45
41
 
46
-
42
+ API_FUNCTION_TEMPLATE = """
47
43
  def {function_name}(
48
44
  {args}
49
- ) -> ApiFunctionResponse:
45
+ ) -> {api_response_type}:
50
46
  "{function_description}"
51
47
  resp = execute("{function_type}", "{function_id}", {data})
52
- if resp.status_code != 200 and resp.status_code != 201:
53
- error_content = resp.content.decode("utf-8", errors="ignore")
54
- raise PolyApiException(f"{{resp.status_code}}: {{error_content}}")
55
- return ApiFunctionResponse(resp.json())
48
+ return {api_response_type}(resp.json()) # type: ignore
56
49
  """
57
50
 
58
51
 
@@ -118,7 +111,7 @@ def _get_type(type_spec: PropertyType) -> Tuple[str, str]:
118
111
  return "Any", ""
119
112
 
120
113
 
121
- def _parse_arguments(arguments: List[PropertySpecification]) -> Tuple[str, str]:
114
+ def _parse_arguments(function_name: str, arguments: List[PropertySpecification]) -> Tuple[str, str]:
122
115
  args_def = []
123
116
  arg_string = ""
124
117
  for idx, a in enumerate(arguments):
@@ -126,7 +119,7 @@ def _parse_arguments(arguments: List[PropertySpecification]) -> Tuple[str, str]:
126
119
  if arg_def:
127
120
  args_def.append(arg_def)
128
121
  a["name"] = camelCase(a["name"])
129
- arg_string += f" {a['name']}: {arg_type}"
122
+ arg_string += f" {a['name']}: {_add_type_import_path(function_name, arg_type)}"
130
123
  description = a.get("description", "")
131
124
  if description:
132
125
  if idx == len(arguments) - 1:
@@ -138,6 +131,25 @@ def _parse_arguments(arguments: List[PropertySpecification]) -> Tuple[str, str]:
138
131
  return arg_string.rstrip("\n"), "\n\n".join(args_def)
139
132
 
140
133
 
134
+ def _add_type_import_path(function_name: str, arg: str) -> str:
135
+ """ if not basic type, coerce to camelCase and add the import path
136
+ """
137
+ if arg in BASIC_PYTHON_TYPES:
138
+ return arg
139
+
140
+ if arg.startswith("List["):
141
+ sub = arg[5:-1]
142
+ if sub in BASIC_PYTHON_TYPES:
143
+ return arg
144
+ else:
145
+ if '"' in sub:
146
+ return f'List[_{function_name}.{camelCase(sub)}]'
147
+ else:
148
+ return f'List["_{function_name}.{camelCase(sub)}"]'
149
+
150
+ return f'_{function_name}.{camelCase(arg)}'
151
+
152
+
141
153
  def render_function(
142
154
  function_type: str,
143
155
  function_name: str,
@@ -145,38 +157,44 @@ def render_function(
145
157
  function_description: str,
146
158
  arguments: List[PropertySpecification],
147
159
  return_type: Dict[str, Any],
148
- ) -> str:
160
+ ) -> Tuple[str, str]:
149
161
  arg_names = [a["name"] for a in arguments]
150
- args, args_def = _parse_arguments(arguments)
162
+ args, args_def = _parse_arguments(function_name, arguments)
151
163
  return_type_name, return_type_def = _get_type(return_type) # type: ignore
152
164
  data = "{" + ", ".join([f"'{arg}': {camelCase(arg)}" for arg in arg_names]) + "}"
153
165
  if function_type == "apiFunction":
154
- rendered = API_TEMPLATE.format(
166
+ api_response_type = f"{function_name}Response"
167
+ func_type_defs = API_DEFS_TEMPLATE.format(
168
+ args_def=args_def,
169
+ api_response_type=api_response_type,
170
+ return_type_name=return_type_name,
171
+ return_type_def=return_type_def,
172
+ )
173
+ func_str = API_FUNCTION_TEMPLATE.format(
155
174
  function_type=TEMPLATE_FUNCTION_TYPE_MAP[function_type],
156
175
  function_name=function_name,
157
176
  function_id=function_id,
158
177
  function_description=function_description.replace('"', "'"),
159
178
  args=args,
160
- args_def=args_def,
161
- return_type_name=return_type_name,
162
- return_type_def=return_type_def,
163
179
  data=data,
180
+ api_response_type=_add_type_import_path(function_name, api_response_type),
164
181
  )
165
182
  else:
166
- return_action = _get_server_return_action(return_type_name)
167
- rendered = SERVER_TEMPLATE.format(
183
+ func_type_defs = SERVER_DEFS_TEMPLATE.format(
184
+ args_def=args_def,
185
+ return_type_def=return_type_def,
186
+ )
187
+ func_str = SERVER_FUNCTION_TEMPLATE.format(
188
+ return_type_name=_add_type_import_path(function_name, return_type_name),
168
189
  function_type=TEMPLATE_FUNCTION_TYPE_MAP[function_type],
169
190
  function_name=function_name,
170
191
  function_id=function_id,
171
192
  function_description=function_description.replace('"', "'"),
172
193
  args=args,
173
- args_def=args_def,
174
- return_type_name=return_type_name,
175
- return_type_def=return_type_def,
176
- return_action=return_action,
194
+ return_action=_get_server_return_action(return_type_name),
177
195
  data=data,
178
196
  )
179
- return rendered
197
+ return func_str, func_type_defs
180
198
 
181
199
 
182
200
  def _get_server_return_action(return_type_name: str) -> str:
@@ -206,22 +224,30 @@ def add_function_file(
206
224
  ):
207
225
  # first lets add the import to the __init__
208
226
  init_path = os.path.join(full_path, "__init__.py")
227
+ _init_the_init(init_path)
228
+
229
+ func_str, func_type_defs = render_function(
230
+ function_type,
231
+ function_name,
232
+ function_id,
233
+ function_description,
234
+ arguments,
235
+ return_type,
236
+ )
237
+
209
238
  with open(init_path, "a") as f:
210
- f.write(f"from ._{function_name} import {function_name}\n")
239
+ f.write(f"\n\nfrom . import _{function_name}\n\n{func_str}")
211
240
 
212
241
  # now lets add the code!
213
242
  file_path = os.path.join(full_path, f"_{function_name}.py")
214
243
  with open(file_path, "w") as f:
215
- f.write(
216
- render_function(
217
- function_type,
218
- function_name,
219
- function_id,
220
- function_description,
221
- arguments,
222
- return_type,
223
- )
224
- )
244
+ f.write(func_type_defs)
245
+
246
+
247
+ def _init_the_init(init_path: str) -> None:
248
+ if not os.path.exists(init_path):
249
+ with open(init_path, "w") as f:
250
+ f.write("from typing import List, Dict, Any, TypedDict\nfrom polyapi.execute import execute\nfrom polyapi.exceptions import PolyApiException\n")
225
251
 
226
252
 
227
253
  def create_function(
@@ -255,6 +281,7 @@ def create_function(
255
281
  # append to __init__.py file if nested folders
256
282
  next = folders[idx + 1] if idx + 2 < len(folders) else ""
257
283
  if next:
284
+ _init_the_init(os.path.join(full_path, "__init__.py"))
258
285
  append_init(full_path, next)
259
286
 
260
287
 
@@ -15,4 +15,9 @@ PYTHON_TO_JSONSCHEMA_TYPE_MAP = {
15
15
  "bool": "boolean",
16
16
  "List": "array",
17
17
  "Dict": "object",
18
- }
18
+ }
19
+
20
+ BASIC_PYTHON_TYPES = set(PYTHON_TO_JSONSCHEMA_TYPE_MAP.keys())
21
+
22
+ # TODO wire this up to config-variables in future so clients can modify
23
+ SUPPORT_EMAIL = 'support@polyapi.io'
@@ -4,7 +4,6 @@ from polyapi.config import get_api_key_and_url
4
4
  from polyapi.exceptions import PolyApiException
5
5
 
6
6
 
7
- # TODO use this to cleanup generated code
8
7
  def execute(function_type, function_id, data) -> Response:
9
8
  api_key, api_url = get_api_key_and_url()
10
9
  headers = {"Authorization": f"Bearer {api_key}"}
@@ -79,4 +79,8 @@ def clean_title(title: str) -> str:
79
79
  """ used by library generation, sometimes functions can be added with spaces in the title
80
80
  or other nonsense. fix them!
81
81
  """
82
- return title.replace(" ", "")
82
+ title = title.replace(" ", "")
83
+ # certain reserved words cant be titles, let's replace them
84
+ if title == "List":
85
+ title = "List_"
86
+ return title
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: polyapi-python
3
- Version: 0.1.0.dev0
3
+ Version: 0.1.0.dev1
4
4
  Summary: The PolyAPI Python Client
5
5
  Author-email: Dan Fellin <dan@polyapi.io>
6
6
  License: MIT License
@@ -3,7 +3,7 @@ requires = ["setuptools>=61.2", "wheel"]
3
3
 
4
4
  [project]
5
5
  name = "polyapi-python"
6
- version = "0.1.0.dev0"
6
+ version = "0.1.0.dev1"
7
7
  description = "The PolyAPI Python Client"
8
8
  authors = [{ name = "Dan Fellin", email = "dan@polyapi.io" }]
9
9
  dependencies = ["requests", "typing_extensions", "jsonschema-gentypes", "pydantic>=2.5.3", "stdlib_list"]