polyapi-python 0.1.0.dev0__py3-none-any.whl → 0.1.0.dev2__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.
polyapi/api.py CHANGED
@@ -1,7 +1,7 @@
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 polyapi.constants import BASIC_PYTHON_TYPES, JSONSCHEMA_TO_PYTHON_TYPE_MAP
5
5
  from polyapi.typedefs import PropertySpecification, PropertyType
6
6
  from polyapi.utils import append_init, camelCase
7
7
  from polyapi.schema import generate_schema_types, clean_title
@@ -12,47 +12,38 @@ TEMPLATE_FUNCTION_TYPE_MAP = {
12
12
  "serverFunction": "server",
13
13
  }
14
14
 
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
15
+ SERVER_DEFS_TEMPLATE = """
16
+ from typing import List, Dict, Any, TypedDict
20
17
  {args_def}
21
18
  {return_type_def}
19
+ """
20
+
21
+ SERVER_FUNCTION_TEMPLATE = """
22
22
  def {function_name}(
23
23
  {args}
24
24
  ) -> {return_type_name}:
25
25
  "{function_description}"
26
26
  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
27
  return {return_action}
32
28
  """
33
29
 
34
- API_TEMPLATE = """
35
- import requests
30
+ API_DEFS_TEMPLATE = """
36
31
  from typing import List, Dict, Any, TypedDict
37
- from polyapi.execute import execute
38
- from polyapi.exceptions import PolyApiException
39
32
  {args_def}
40
33
  {return_type_def}
41
- class ApiFunctionResponse(TypedDict):
34
+ class {api_response_type}(TypedDict):
42
35
  status: int
43
36
  headers: Dict
44
37
  data: {return_type_name}
38
+ """
45
39
 
46
-
40
+ API_FUNCTION_TEMPLATE = """
47
41
  def {function_name}(
48
42
  {args}
49
- ) -> ApiFunctionResponse:
43
+ ) -> {api_response_type}:
50
44
  "{function_description}"
51
45
  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())
46
+ return {api_response_type}(resp.json()) # type: ignore
56
47
  """
57
48
 
58
49
 
@@ -118,7 +109,7 @@ def _get_type(type_spec: PropertyType) -> Tuple[str, str]:
118
109
  return "Any", ""
119
110
 
120
111
 
121
- def _parse_arguments(arguments: List[PropertySpecification]) -> Tuple[str, str]:
112
+ def _parse_arguments(function_name: str, arguments: List[PropertySpecification]) -> Tuple[str, str]:
122
113
  args_def = []
123
114
  arg_string = ""
124
115
  for idx, a in enumerate(arguments):
@@ -126,7 +117,7 @@ def _parse_arguments(arguments: List[PropertySpecification]) -> Tuple[str, str]:
126
117
  if arg_def:
127
118
  args_def.append(arg_def)
128
119
  a["name"] = camelCase(a["name"])
129
- arg_string += f" {a['name']}: {arg_type}"
120
+ arg_string += f" {a['name']}: {_add_type_import_path(function_name, arg_type)}"
130
121
  description = a.get("description", "")
131
122
  if description:
132
123
  if idx == len(arguments) - 1:
@@ -138,6 +129,25 @@ def _parse_arguments(arguments: List[PropertySpecification]) -> Tuple[str, str]:
138
129
  return arg_string.rstrip("\n"), "\n\n".join(args_def)
139
130
 
140
131
 
132
+ def _add_type_import_path(function_name: str, arg: str) -> str:
133
+ """ if not basic type, coerce to camelCase and add the import path
134
+ """
135
+ if arg in BASIC_PYTHON_TYPES:
136
+ return arg
137
+
138
+ if arg.startswith("List["):
139
+ sub = arg[5:-1]
140
+ if sub in BASIC_PYTHON_TYPES:
141
+ return arg
142
+ else:
143
+ if '"' in sub:
144
+ return f'List[_{function_name}.{camelCase(sub)}]'
145
+ else:
146
+ return f'List["_{function_name}.{camelCase(sub)}"]'
147
+
148
+ return f'_{function_name}.{camelCase(arg)}'
149
+
150
+
141
151
  def render_function(
142
152
  function_type: str,
143
153
  function_name: str,
@@ -145,38 +155,44 @@ def render_function(
145
155
  function_description: str,
146
156
  arguments: List[PropertySpecification],
147
157
  return_type: Dict[str, Any],
148
- ) -> str:
158
+ ) -> Tuple[str, str]:
149
159
  arg_names = [a["name"] for a in arguments]
150
- args, args_def = _parse_arguments(arguments)
160
+ args, args_def = _parse_arguments(function_name, arguments)
151
161
  return_type_name, return_type_def = _get_type(return_type) # type: ignore
152
162
  data = "{" + ", ".join([f"'{arg}': {camelCase(arg)}" for arg in arg_names]) + "}"
153
163
  if function_type == "apiFunction":
154
- rendered = API_TEMPLATE.format(
164
+ api_response_type = f"{function_name}Response"
165
+ func_type_defs = API_DEFS_TEMPLATE.format(
166
+ args_def=args_def,
167
+ api_response_type=api_response_type,
168
+ return_type_name=return_type_name,
169
+ return_type_def=return_type_def,
170
+ )
171
+ func_str = API_FUNCTION_TEMPLATE.format(
155
172
  function_type=TEMPLATE_FUNCTION_TYPE_MAP[function_type],
156
173
  function_name=function_name,
157
174
  function_id=function_id,
158
175
  function_description=function_description.replace('"', "'"),
159
176
  args=args,
160
- args_def=args_def,
161
- return_type_name=return_type_name,
162
- return_type_def=return_type_def,
163
177
  data=data,
178
+ api_response_type=_add_type_import_path(function_name, api_response_type),
164
179
  )
165
180
  else:
166
- return_action = _get_server_return_action(return_type_name)
167
- rendered = SERVER_TEMPLATE.format(
181
+ func_type_defs = SERVER_DEFS_TEMPLATE.format(
182
+ args_def=args_def,
183
+ return_type_def=return_type_def,
184
+ )
185
+ func_str = SERVER_FUNCTION_TEMPLATE.format(
186
+ return_type_name=_add_type_import_path(function_name, return_type_name),
168
187
  function_type=TEMPLATE_FUNCTION_TYPE_MAP[function_type],
169
188
  function_name=function_name,
170
189
  function_id=function_id,
171
190
  function_description=function_description.replace('"', "'"),
172
191
  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,
192
+ return_action=_get_server_return_action(return_type_name),
177
193
  data=data,
178
194
  )
179
- return rendered
195
+ return func_str, func_type_defs
180
196
 
181
197
 
182
198
  def _get_server_return_action(return_type_name: str) -> str:
@@ -206,22 +222,30 @@ def add_function_file(
206
222
  ):
207
223
  # first lets add the import to the __init__
208
224
  init_path = os.path.join(full_path, "__init__.py")
225
+ _init_the_init(init_path)
226
+
227
+ func_str, func_type_defs = render_function(
228
+ function_type,
229
+ function_name,
230
+ function_id,
231
+ function_description,
232
+ arguments,
233
+ return_type,
234
+ )
235
+
209
236
  with open(init_path, "a") as f:
210
- f.write(f"from ._{function_name} import {function_name}\n")
237
+ f.write(f"\n\nfrom . import _{function_name}\n\n{func_str}")
211
238
 
212
239
  # now lets add the code!
213
240
  file_path = os.path.join(full_path, f"_{function_name}.py")
214
241
  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
- )
242
+ f.write(func_type_defs)
243
+
244
+
245
+ def _init_the_init(init_path: str) -> None:
246
+ if not os.path.exists(init_path):
247
+ with open(init_path, "w") as f:
248
+ f.write("from typing import List, Dict, Any, TypedDict\nfrom polyapi.execute import execute\nfrom polyapi.exceptions import PolyApiException\n")
225
249
 
226
250
 
227
251
  def create_function(
@@ -255,6 +279,7 @@ def create_function(
255
279
  # append to __init__.py file if nested folders
256
280
  next = folders[idx + 1] if idx + 2 < len(folders) else ""
257
281
  if next:
282
+ _init_the_init(os.path.join(full_path, "__init__.py"))
258
283
  append_init(full_path, next)
259
284
 
260
285
 
polyapi/constants.py CHANGED
@@ -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'
polyapi/execute.py CHANGED
@@ -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}"}
polyapi/schema.py CHANGED
@@ -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.dev2
4
4
  Summary: The PolyAPI Python Client
5
5
  Author-email: Dan Fellin <dan@polyapi.io>
6
6
  License: MIT License
@@ -1,20 +1,20 @@
1
1
  polyapi/__init__.py,sha256=BbXhEtZ3TSGBfAagj62oRxrc5yFNz5fO0FMoGqS-ENQ,366
2
2
  polyapi/__main__.py,sha256=V4zhAh_YGxno5f_KSrlkELxcuDh9bR3WSd0n-2r-qQQ,93
3
- polyapi/api.py,sha256=9C-JiWtKryTrLWQBtBWnbgNLRd4FaGscViOAkKdL7iw,8875
3
+ polyapi/api.py,sha256=hUE-XrrCjJutQ5cvji9jcY8Sjga_HgZV9pZg8-UoqlY,9734
4
4
  polyapi/cli.py,sha256=XafGV_MGYWHOSbn7KZ03GKrSihirT2LVLDhFh_FgyF0,1425
5
5
  polyapi/config.py,sha256=RMg8OUKXKFENtS17l4rkaZhfGrwXN-_-F1V1HKJGbYU,2006
6
- polyapi/constants.py,sha256=SKDdSaG6NUZHsyBxGxBGYm85y82hSE_M1ytKv1hp5gk,337
6
+ polyapi/constants.py,sha256=NGjso6K5rGnE8TGdrXmdEfvvr-HI3DTVGwOYiWO68LM,511
7
7
  polyapi/exceptions.py,sha256=Zh7i7eCUhDuXEdUYjatkLFTeZkrx1BJ1P5ePgbJ9eIY,89
8
- polyapi/execute.py,sha256=nbZGmjPRBT2U-YFFLRNlOf9HP0vTn1yUDKSQVykZ5PQ,687
8
+ polyapi/execute.py,sha256=VtdFU0HraviVtseg8X-o34yqx1XRy3rufcHDibtDppU,645
9
9
  polyapi/function_cli.py,sha256=qMWZm07F0PP1d-LeHnUw2oJzIea0YEwYJG809zYJeqY,6557
10
10
  polyapi/generate.py,sha256=0ZYXParP_vm9YXWfMl6Rn7MKrpdUXfgHb4UUzgJ1HKk,4114
11
11
  polyapi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- polyapi/schema.py,sha256=ljXDoXDY5570onOEAzWyVTF7Cc76WK48dG6u51xCIxQ,2626
12
+ polyapi/schema.py,sha256=LBBj2_qR793-4dhp0xyywtctbYMnS85lPwitldGJ5yo,2756
13
13
  polyapi/typedefs.py,sha256=zh4F36fZSZ6r4YqkcjDjNo_z__kIdiX7fLkC3QniDK0,1082
14
14
  polyapi/utils.py,sha256=mvkuJU27QMLKdcqyPktlDD-iO0OI3gbA7xhWCjR4UeM,709
15
15
  polyapi/variables.py,sha256=z1zfR3imJ735G2V89BMOYdzEdXiEHKZ5Q58O4ipWcpk,2897
16
- polyapi_python-0.1.0.dev0.dist-info/LICENSE,sha256=Hi0kDr56Dsy0uYIwNt4r9G7tI8x8miXRTlyvbeplCP8,1068
17
- polyapi_python-0.1.0.dev0.dist-info/METADATA,sha256=MZKXtg2ZvvOiWjCBwtPwZ0Y4eNs3dcUiEDGnpZORMsI,4243
18
- polyapi_python-0.1.0.dev0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
19
- polyapi_python-0.1.0.dev0.dist-info/top_level.txt,sha256=CEFllOnzowci_50RYJac-M54KD2IdAptFsayVVF_f04,8
20
- polyapi_python-0.1.0.dev0.dist-info/RECORD,,
16
+ polyapi_python-0.1.0.dev2.dist-info/LICENSE,sha256=Hi0kDr56Dsy0uYIwNt4r9G7tI8x8miXRTlyvbeplCP8,1068
17
+ polyapi_python-0.1.0.dev2.dist-info/METADATA,sha256=Vsi2Fa7OJfWZNr3MCqwUrIjiIcuTuFf3xrXW8jr6hXg,4243
18
+ polyapi_python-0.1.0.dev2.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
19
+ polyapi_python-0.1.0.dev2.dist-info/top_level.txt,sha256=CEFllOnzowci_50RYJac-M54KD2IdAptFsayVVF_f04,8
20
+ polyapi_python-0.1.0.dev2.dist-info/RECORD,,