polyapi-python 0.3.17.dev1__py3-none-any.whl → 0.3.18.dev1__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/generate.py CHANGED
@@ -399,7 +399,21 @@ def clear() -> None:
399
399
 
400
400
  def render_spec(spec: SpecificationDto) -> Tuple[str, str]:
401
401
  function_type = spec["type"]
402
- function_description = spec["description"]
402
+ raw_description = spec.get("description", "")
403
+ def _flatten_description(value: Any) -> List[str]:
404
+ if value is None:
405
+ return []
406
+ if isinstance(value, list):
407
+ flat: List[str] = []
408
+ for item in value:
409
+ flat.extend(_flatten_description(item))
410
+ return flat
411
+ return [str(value)]
412
+
413
+ if isinstance(raw_description, str):
414
+ function_description = raw_description
415
+ else:
416
+ function_description = "\n".join(_flatten_description(raw_description))
403
417
  function_name = spec["name"]
404
418
  function_context = spec["context"]
405
419
  function_id = spec["id"]
polyapi/poly_tables.py CHANGED
@@ -531,10 +531,27 @@ def _render_table(table: TableSpecDto) -> str:
531
531
  table_where_class = _render_table_where_class(
532
532
  table["name"], columns, required_columns
533
533
  )
534
- if table.get("description", ""):
534
+ raw_description = table.get("description", "")
535
+
536
+ def _flatten_description(value: Any) -> List[str]:
537
+ if value is None:
538
+ return []
539
+ if isinstance(value, list):
540
+ flat: List[str] = []
541
+ for item in value:
542
+ flat.extend(_flatten_description(item))
543
+ return flat
544
+ return [str(value)]
545
+
546
+ if isinstance(raw_description, str):
547
+ normalized_description = raw_description
548
+ else:
549
+ normalized_description = "\n".join(_flatten_description(raw_description))
550
+
551
+ if normalized_description:
535
552
  table_description = '\n """'
536
553
  table_description += "\n ".join(
537
- table["description"].replace('"', "'").split("\n")
554
+ normalized_description.replace('"', "'").split("\n")
538
555
  )
539
556
  table_description += '\n """'
540
557
  else:
polyapi/schema.py CHANGED
@@ -50,6 +50,13 @@ def wrapped_generate_schema_types(type_spec: dict, root, fallback_type):
50
50
  # if we have no root, just add "My"
51
51
  root = "My" + root
52
52
 
53
+ if isinstance(root, list):
54
+ root = "_".join([str(x) for x in root if x is not None]) or fallback_type
55
+ elif root is None:
56
+ root = fallback_type
57
+ elif not isinstance(root, str):
58
+ root = str(root)
59
+
53
60
  root = clean_title(root)
54
61
 
55
62
  try:
@@ -150,10 +157,19 @@ def clean_title(title: str) -> str:
150
157
  """ used by library generation, sometimes functions can be added with spaces in the title
151
158
  or other nonsense. fix them!
152
159
  """
160
+ if isinstance(title, list):
161
+ title = "_".join([str(x) for x in title if x is not None])
162
+ elif title is None:
163
+ title = ""
164
+ elif not isinstance(title, str):
165
+ title = str(title)
166
+
153
167
  title = title.replace(" ", "")
154
168
  # certain reserved words cant be titles, let's replace them
155
169
  if title == "List":
156
170
  title = "List_"
171
+ if not title:
172
+ title = "Dict"
157
173
  return title
158
174
 
159
175
 
polyapi/server.py CHANGED
@@ -62,7 +62,7 @@ def render_server_function(
62
62
  return_type_def=return_type_def,
63
63
  )
64
64
  func_str = SERVER_FUNCTION_TEMPLATE.format(
65
- return_type_name=add_type_import_path(function_name, return_type_name),
65
+ return_type_name=_normalize_return_type_for_annotation(function_name, return_type_name),
66
66
  function_type="server",
67
67
  function_name=function_name,
68
68
  function_id=function_id,
@@ -74,9 +74,23 @@ def render_server_function(
74
74
  return func_str, func_type_defs
75
75
 
76
76
 
77
+ def _normalize_return_type_for_annotation(function_name: str, return_type_name: str) -> str:
78
+ if return_type_name == "ReturnType":
79
+ return "ReturnType"
80
+ return add_type_import_path(function_name, return_type_name)
81
+
82
+
77
83
  def _get_server_return_action(return_type_name: str) -> str:
78
- if return_type_name == "str":
84
+ normalized_type = return_type_name.replace(" ", "")
85
+
86
+ if normalized_type in {"str", "Optional[str]"}:
79
87
  return_action = "resp.text"
88
+ elif "|" in normalized_type:
89
+ union_parts = {part for part in normalized_type.split("|") if part}
90
+ if union_parts == {"str", "None"}:
91
+ return_action = "resp.text"
92
+ else:
93
+ return_action = "resp.json()"
80
94
  else:
81
95
  return_action = "resp.json()"
82
- return return_action
96
+ return return_action
polyapi/utils.py CHANGED
@@ -71,6 +71,43 @@ def print_red(s: str):
71
71
  print(Fore.RED + s + Style.RESET_ALL)
72
72
 
73
73
 
74
+ def normalize_cross_language_type(type_name: str) -> str:
75
+ value = (type_name or "").strip()
76
+ if not value:
77
+ return "Any"
78
+
79
+ primitive_map = {
80
+ "string": "str",
81
+ "number": "float",
82
+ "integer": "int",
83
+ "boolean": "bool",
84
+ "null": "None",
85
+ "void": "None",
86
+ "any": "Any",
87
+ "object": "Dict",
88
+ }
89
+
90
+ if value.startswith("Promise<") and value.endswith(">"):
91
+ return normalize_cross_language_type(value[len("Promise<"):-1])
92
+
93
+ if value.startswith("Awaited<") and value.endswith(">"):
94
+ return normalize_cross_language_type(value[len("Awaited<"):-1])
95
+
96
+ if value.endswith("[]"):
97
+ item_type = normalize_cross_language_type(value[:-2])
98
+ return f"List[{item_type}]"
99
+
100
+ if "|" in value:
101
+ parts = [p.strip() for p in value.split("|") if p.strip()]
102
+ normalized = [normalize_cross_language_type(part) for part in parts]
103
+ return " | ".join(normalized) if normalized else "Any"
104
+
105
+ if value == "ReturnType" or value.startswith("ReturnType<") or "typeof" in value:
106
+ return "Any"
107
+
108
+ return primitive_map.get(value, value)
109
+
110
+
74
111
  def to_type_module_alias(function_name: str) -> str:
75
112
  """Return the internal alias used for a function's generated type module."""
76
113
  return f"_{to_func_namespace(function_name)}_types"
@@ -81,6 +118,14 @@ def add_type_import_path(function_name: str, arg: str) -> str:
81
118
  # from now, we start qualifying non-basic types :))
82
119
  # e.g. Callable[[EmailAddress, Dict, Dict, Dict], None]
83
120
  # becomes Callable[[Set_profile_email.EmailAddress, Dict, Dict, Dict], None]
121
+ arg = normalize_cross_language_type(arg)
122
+
123
+ if "|" in arg:
124
+ return " | ".join(
125
+ add_type_import_path(function_name, token.strip())
126
+ for token in arg.split("|")
127
+ if token.strip()
128
+ )
84
129
  type_module_alias = to_type_module_alias(function_name)
85
130
 
86
131
  if arg.startswith("Callable"):
@@ -96,7 +141,7 @@ def add_type_import_path(function_name: str, arg: str) -> str:
96
141
  return "Callable[" + ",".join(qualified) + "]"
97
142
  # return arg
98
143
 
99
- if arg in BASIC_PYTHON_TYPES:
144
+ if arg == "Any" or arg in BASIC_PYTHON_TYPES:
100
145
  return arg
101
146
 
102
147
  if arg.startswith("List["):
@@ -127,14 +172,23 @@ def get_type_and_def(
127
172
  return "Any", ""
128
173
 
129
174
  if type_spec["kind"] == "plain":
130
- value = type_spec.get("value", "")
175
+ value = normalize_cross_language_type(type_spec.get("value", ""))
176
+
177
+ if "|" in value or value in BASIC_PYTHON_TYPES:
178
+ return value, ""
179
+
131
180
  if value.endswith("[]"):
132
- primitive = map_primitive_types(value[:-2])
181
+ primitive = normalize_cross_language_type(value[:-2])
182
+ if primitive not in BASIC_PYTHON_TYPES:
183
+ primitive = map_primitive_types(primitive)
133
184
  return f"List[{primitive}]", ""
134
185
  else:
135
186
  return map_primitive_types(value), ""
136
187
  elif type_spec["kind"] == "primitive":
137
- return map_primitive_types(type_spec.get("type", "any")), ""
188
+ primitive = normalize_cross_language_type(type_spec.get("type", "any"))
189
+ if primitive in BASIC_PYTHON_TYPES:
190
+ return primitive, ""
191
+ return map_primitive_types(primitive), ""
138
192
  elif type_spec["kind"] == "array":
139
193
  if type_spec.get("items"):
140
194
  items = type_spec["items"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: polyapi-python
3
- Version: 0.3.17.dev1
3
+ Version: 0.3.18.dev1
4
4
  Summary: The Python Client for PolyAPI, the IPaaS by Developers for Developers
5
5
  Author-email: Dan Fellin <dan@polyapi.io>
6
6
  License: MIT License
@@ -12,23 +12,23 @@ polyapi/error_handler.py,sha256=I_e0iz6VM23FLVQWJljxs2NGcl_OODbi43OcbnqBlp8,2398
12
12
  polyapi/exceptions.py,sha256=Zh7i7eCUhDuXEdUYjatkLFTeZkrx1BJ1P5ePgbJ9eIY,89
13
13
  polyapi/execute.py,sha256=MeAmc5qsMQfnQPiHJK9Khkn_wrBxMoyMYYqmuFFPsRg,8779
14
14
  polyapi/function_cli.py,sha256=kKrecKCDNMmYtcOOCVF2KKOGjFUfWD2TbiVsyYQ84y8,4323
15
- polyapi/generate.py,sha256=Bti1GlCi6yzv8pqsnJ95_KDES-L_1jwYGmsugZ4_hhA,21271
15
+ polyapi/generate.py,sha256=LzQBm2GKYfAwTsJ36ViLr1ypzrudijj1qR0DRzp-Be0,21764
16
16
  polyapi/http_client.py,sha256=Pd6FYHGB6plWlBbwZD9LPP6FEicdp0wyLWHd_9jxsaY,2273
17
17
  polyapi/parser.py,sha256=pAkeuwp1Kn6bHXiIoj-DuXQ518PztQThIa8vztgsKLQ,21525
18
18
  polyapi/poly_schemas.py,sha256=fZ6AGvHcOKQJtlrzSuzeBNed5DxPMA2dJGdJvuFCHWM,9066
19
- polyapi/poly_tables.py,sha256=T07j4H-HdcIFP5HwUq0uljpzzYzMtJvdqYvOdC0oZ4I,19728
19
+ polyapi/poly_tables.py,sha256=xFxR69dZNmePT9mUz3DvsoreQK7huIa07evEmOSixA0,20271
20
20
  polyapi/prepare.py,sha256=DBlrQu_A0PqdaQ3KlMs-C6PkV3qncatkAiBlC7j2hnk,7441
21
21
  polyapi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
22
  polyapi/rendered_spec.py,sha256=J2Num7MXnW_mKAe2MSVIL1coWopNYZ-6nNNwQRfseV0,2262
23
- polyapi/schema.py,sha256=2ehUgs4IcNvqsg5cUjZReg-X83hbh4l0eStKmJhFsBY,5921
24
- polyapi/server.py,sha256=35l3f9d6jWaa60MfX5n7KF4UCAQR-Xg8WLc0NL9dlfY,2479
23
+ polyapi/schema.py,sha256=PuLvu29rWWyN_DV6QLWHR5PNopfW2vpRsJ6mOTx7wao,6396
24
+ polyapi/server.py,sha256=_14lP4_BmRYMBXwaqXVWmiSTHH3h7ecCHxSalM9UiSc,3049
25
25
  polyapi/sync.py,sha256=t0Khh8B5GylxB7KWRP_xvkrvkuyVarSLCOvtmaz7lcc,6766
26
26
  polyapi/typedefs.py,sha256=mfll-KrngOW0wzbvDNiIDaDkFMwbsT-MY5y5hzWj9RE,5642
27
- polyapi/utils.py,sha256=Z4zx43bJ09ihKhcSrwXKcQrIFLUkF-0rEWI6PyqQ-rA,13542
27
+ polyapi/utils.py,sha256=SfzK86nhg1wuGzbI53DEFKJ3JkxZ0yU-CZBd_caKbrQ,15313
28
28
  polyapi/variables.py,sha256=hfSDPGQK6YphNCa9MqE0W88WIFfqCQWgpBDWkExMq-A,7582
29
29
  polyapi/webhook.py,sha256=0ceLwHNjNd2Yx_8MX5jOIxiQ5Lwhy2pe81ProAuKon0,5108
30
- polyapi_python-0.3.17.dev1.dist-info/licenses/LICENSE,sha256=6b_I7aPVp8JXhqQwdw7_B84Ca0S4JGjHj0sr_1VOdB4,1068
31
- polyapi_python-0.3.17.dev1.dist-info/METADATA,sha256=sc2djIZTQDXcshC1I3SBuDv0ec6lABq4ZP7BAEee8PM,5928
32
- polyapi_python-0.3.17.dev1.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
33
- polyapi_python-0.3.17.dev1.dist-info/top_level.txt,sha256=CEFllOnzowci_50RYJac-M54KD2IdAptFsayVVF_f04,8
34
- polyapi_python-0.3.17.dev1.dist-info/RECORD,,
30
+ polyapi_python-0.3.18.dev1.dist-info/licenses/LICENSE,sha256=6b_I7aPVp8JXhqQwdw7_B84Ca0S4JGjHj0sr_1VOdB4,1068
31
+ polyapi_python-0.3.18.dev1.dist-info/METADATA,sha256=myNaB-5pqSuKPjV68zELyCj4gTyJXgho7fnw-nexq30,5928
32
+ polyapi_python-0.3.18.dev1.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
33
+ polyapi_python-0.3.18.dev1.dist-info/top_level.txt,sha256=CEFllOnzowci_50RYJac-M54KD2IdAptFsayVVF_f04,8
34
+ polyapi_python-0.3.18.dev1.dist-info/RECORD,,