polyapi-python 0.2.4.dev12__py3-none-any.whl → 0.2.5.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/api.py +2 -0
- polyapi/auth.py +3 -3
- polyapi/client.py +19 -0
- polyapi/constants.py +4 -0
- polyapi/generate.py +8 -5
- polyapi/server.py +3 -1
- polyapi/typedefs.py +1 -0
- polyapi/utils.py +24 -1
- polyapi/webhook.py +19 -4
- {polyapi_python-0.2.4.dev12.dist-info → polyapi_python-0.2.5.dev1.dist-info}/METADATA +1 -1
- polyapi_python-0.2.5.dev1.dist-info/RECORD +25 -0
- polyapi_python-0.2.4.dev12.dist-info/RECORD +0 -25
- {polyapi_python-0.2.4.dev12.dist-info → polyapi_python-0.2.5.dev1.dist-info}/LICENSE +0 -0
- {polyapi_python-0.2.4.dev12.dist-info → polyapi_python-0.2.5.dev1.dist-info}/WHEEL +0 -0
- {polyapi_python-0.2.4.dev12.dist-info → polyapi_python-0.2.5.dev1.dist-info}/top_level.txt +0 -0
polyapi/api.py
CHANGED
polyapi/auth.py
CHANGED
|
@@ -16,9 +16,9 @@ import asyncio
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class AuthFunctionResponse(TypedDict):
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
status: int
|
|
20
|
+
data: Any
|
|
21
|
+
headers: Dict[str, str]
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
async def getToken(clientId: str, clientSecret: str, scopes: List[str], callback, options: Optional[Dict[str, Any]] = None):
|
polyapi/client.py
CHANGED
|
@@ -10,6 +10,22 @@ from typing import List, Dict, Any, TypedDict
|
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
12
|
|
|
13
|
+
def _wrap_code_in_try_except(code: str) -> str:
|
|
14
|
+
""" this is necessary because client functions with imports will blow up ALL server functions,
|
|
15
|
+
even if they don't use them.
|
|
16
|
+
because the server function will try to load all client functions when loading the library
|
|
17
|
+
"""
|
|
18
|
+
prefix = """logger = logging.getLogger("poly")
|
|
19
|
+
try:
|
|
20
|
+
"""
|
|
21
|
+
suffix = """except ImportError as e:
|
|
22
|
+
logger.debug(e)"""
|
|
23
|
+
|
|
24
|
+
lines = code.split("\n")
|
|
25
|
+
code = "\n ".join(lines)
|
|
26
|
+
return "".join([prefix, code, "\n", suffix])
|
|
27
|
+
|
|
28
|
+
|
|
13
29
|
def render_client_function(
|
|
14
30
|
function_name: str,
|
|
15
31
|
code: str,
|
|
@@ -22,4 +38,7 @@ def render_client_function(
|
|
|
22
38
|
args_def=args_def,
|
|
23
39
|
return_type_def=return_type_def,
|
|
24
40
|
)
|
|
41
|
+
|
|
42
|
+
code = _wrap_code_in_try_except(code)
|
|
43
|
+
|
|
25
44
|
return code + "\n\n", func_type_defs
|
polyapi/constants.py
CHANGED
|
@@ -5,6 +5,8 @@ JSONSCHEMA_TO_PYTHON_TYPE_MAP = {
|
|
|
5
5
|
"boolean": "bool",
|
|
6
6
|
"array": "List",
|
|
7
7
|
"object": "Dict",
|
|
8
|
+
"function": "Callable",
|
|
9
|
+
"void": "None",
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
|
|
@@ -15,6 +17,8 @@ PYTHON_TO_JSONSCHEMA_TYPE_MAP = {
|
|
|
15
17
|
"bool": "boolean",
|
|
16
18
|
"List": "array",
|
|
17
19
|
"Dict": "object",
|
|
20
|
+
"Callable": "function",
|
|
21
|
+
"None": "void",
|
|
18
22
|
}
|
|
19
23
|
|
|
20
24
|
BASIC_PYTHON_TYPES = set(PYTHON_TO_JSONSCHEMA_TYPE_MAP.keys())
|
polyapi/generate.py
CHANGED
|
@@ -75,11 +75,14 @@ def cache_specs(specs: List[SpecificationDto]):
|
|
|
75
75
|
|
|
76
76
|
full_path = os.path.dirname(os.path.abspath(__file__))
|
|
77
77
|
full_path = os.path.join(full_path, "poly")
|
|
78
|
-
|
|
79
|
-
os.
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
try:
|
|
79
|
+
if not os.path.exists(full_path):
|
|
80
|
+
os.makedirs(full_path)
|
|
81
|
+
|
|
82
|
+
with open(os.path.join(full_path, "specs.json"), "w") as f:
|
|
83
|
+
f.write(json.dumps(supported))
|
|
84
|
+
except Exception as e:
|
|
85
|
+
print("Failed to cache specs", e)
|
|
83
86
|
|
|
84
87
|
|
|
85
88
|
def read_cached_specs() -> List[SpecificationDto]:
|
polyapi/server.py
CHANGED
|
@@ -4,7 +4,7 @@ from polyapi.typedefs import PropertySpecification
|
|
|
4
4
|
from polyapi.utils import camelCase, add_type_import_path, parse_arguments, get_type_and_def
|
|
5
5
|
|
|
6
6
|
SERVER_DEFS_TEMPLATE = """
|
|
7
|
-
from typing import List, Dict, Any, TypedDict
|
|
7
|
+
from typing import List, Dict, Any, TypedDict, Callable
|
|
8
8
|
{args_def}
|
|
9
9
|
{return_type_def}
|
|
10
10
|
"""
|
|
@@ -22,6 +22,8 @@ def {function_name}(
|
|
|
22
22
|
return {return_action}
|
|
23
23
|
except:
|
|
24
24
|
return resp.text
|
|
25
|
+
|
|
26
|
+
|
|
25
27
|
"""
|
|
26
28
|
|
|
27
29
|
|
polyapi/typedefs.py
CHANGED
|
@@ -12,6 +12,7 @@ class PropertySpecification(TypedDict):
|
|
|
12
12
|
|
|
13
13
|
class PropertyType(TypedDict):
|
|
14
14
|
kind: Literal['void', 'primitive', 'array', 'object', 'function', 'plain']
|
|
15
|
+
spec: NotRequired[Dict]
|
|
15
16
|
name: NotRequired[str]
|
|
16
17
|
type: NotRequired[str]
|
|
17
18
|
items: NotRequired['PropertyType']
|
polyapi/utils.py
CHANGED
|
@@ -10,7 +10,7 @@ from polyapi.schema import generate_schema_types, clean_title, map_primitive_typ
|
|
|
10
10
|
|
|
11
11
|
# this string should be in every __init__ file.
|
|
12
12
|
# it contains all the imports needed for the function or variable code to run
|
|
13
|
-
CODE_IMPORTS = "from typing import List, Dict, Any, TypedDict, Optional\nimport requests\nimport socketio # type: ignore\nfrom polyapi.config import get_api_key_and_url\nfrom polyapi.execute import execute, execute_post, variable_get, variable_update\n\n"
|
|
13
|
+
CODE_IMPORTS = "from typing import List, Dict, Any, TypedDict, Optional, Callable\nimport logging\nimport requests\nimport socketio # type: ignore\nfrom polyapi.config import get_api_key_and_url\nfrom polyapi.execute import execute, execute_post, variable_get, variable_update\n\n"
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def init_the_init(full_path: str) -> None:
|
|
@@ -61,6 +61,10 @@ def print_red(s: str):
|
|
|
61
61
|
def add_type_import_path(function_name: str, arg: str) -> str:
|
|
62
62
|
""" if not basic type, coerce to camelCase and add the import path
|
|
63
63
|
"""
|
|
64
|
+
# for now, just treat Callables as basic types
|
|
65
|
+
if arg.startswith("Callable"):
|
|
66
|
+
return arg
|
|
67
|
+
|
|
64
68
|
if arg in BASIC_PYTHON_TYPES:
|
|
65
69
|
return arg
|
|
66
70
|
|
|
@@ -142,6 +146,25 @@ def get_type_and_def(type_spec: PropertyType) -> Tuple[str, str]:
|
|
|
142
146
|
return "Any", ""
|
|
143
147
|
else:
|
|
144
148
|
return "Dict", ""
|
|
149
|
+
elif type_spec["kind"] == "function":
|
|
150
|
+
arg_types = []
|
|
151
|
+
arg_defs = []
|
|
152
|
+
if "spec" in type_spec:
|
|
153
|
+
return_type, _ = get_type_and_def(type_spec["spec"]["returnType"])
|
|
154
|
+
if return_type not in BASIC_PYTHON_TYPES:
|
|
155
|
+
# for now only Python only supports basic types as return types
|
|
156
|
+
return_type = "Any"
|
|
157
|
+
|
|
158
|
+
for argument in type_spec["spec"]["arguments"]:
|
|
159
|
+
arg_type, arg_def = get_type_and_def(argument["type"])
|
|
160
|
+
arg_types.append(arg_type)
|
|
161
|
+
if arg_def:
|
|
162
|
+
arg_defs.append(arg_def)
|
|
163
|
+
|
|
164
|
+
final_arg_type = "Callable[[{}], {}]".format(", ".join(arg_types), return_type)
|
|
165
|
+
return final_arg_type, "\n".join(arg_defs)
|
|
166
|
+
else:
|
|
167
|
+
return "Callable", ""
|
|
145
168
|
elif type_spec["kind"] == "any":
|
|
146
169
|
return "Any", ""
|
|
147
170
|
else:
|
polyapi/webhook.py
CHANGED
|
@@ -6,7 +6,7 @@ from typing import Any, Dict, List, Tuple
|
|
|
6
6
|
|
|
7
7
|
from polyapi.config import get_api_key_and_url
|
|
8
8
|
from polyapi.typedefs import PropertySpecification
|
|
9
|
-
from polyapi.utils import poly_full_path
|
|
9
|
+
from polyapi.utils import parse_arguments, poly_full_path
|
|
10
10
|
|
|
11
11
|
# all active webhook handlers, used by unregister_all to cleanup
|
|
12
12
|
active_handlers: List[Dict[str, Any]] = []
|
|
@@ -15,10 +15,18 @@ active_handlers: List[Dict[str, Any]] = []
|
|
|
15
15
|
client = None
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
WEBHOOK_DEFS_TEMPLATE = """
|
|
19
|
+
from typing import List, Dict, Any, TypedDict, Callable
|
|
20
|
+
{function_args_def}
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
|
|
18
24
|
WEBHOOK_TEMPLATE = """
|
|
19
25
|
|
|
20
26
|
|
|
21
|
-
async def {function_name}(
|
|
27
|
+
async def {function_name}(
|
|
28
|
+
{function_args}
|
|
29
|
+
):
|
|
22
30
|
\"""{description}
|
|
23
31
|
|
|
24
32
|
Function ID: {function_id}
|
|
@@ -112,15 +120,22 @@ def render_webhook_handle(
|
|
|
112
120
|
arguments: List[PropertySpecification],
|
|
113
121
|
return_type: Dict[str, Any],
|
|
114
122
|
) -> Tuple[str, str]:
|
|
123
|
+
function_args, function_args_def = parse_arguments(function_name, arguments)
|
|
124
|
+
|
|
125
|
+
if "WebhookEventType" in function_args:
|
|
126
|
+
# let's add the function name import!
|
|
127
|
+
function_args = function_args.replace("WebhookEventType", f"_{function_name}.WebhookEventType")
|
|
128
|
+
|
|
115
129
|
func_str = WEBHOOK_TEMPLATE.format(
|
|
116
130
|
description=function_description,
|
|
117
131
|
client_id=uuid.uuid4().hex,
|
|
118
132
|
function_id=function_id,
|
|
119
133
|
function_name=function_name,
|
|
134
|
+
function_args=function_args,
|
|
120
135
|
function_path=poly_full_path(function_context, function_name),
|
|
121
136
|
)
|
|
122
|
-
|
|
123
|
-
return func_str,
|
|
137
|
+
func_defs = WEBHOOK_DEFS_TEMPLATE.format(function_args_def=function_args_def)
|
|
138
|
+
return func_str, func_defs
|
|
124
139
|
|
|
125
140
|
|
|
126
141
|
def start(*args):
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
polyapi/__init__.py,sha256=5iujRodfgRyLxT-zY0L3xax3rKRvfSt4NZlZYKOz03w,608
|
|
2
|
+
polyapi/__main__.py,sha256=V4zhAh_YGxno5f_KSrlkELxcuDh9bR3WSd0n-2r-qQQ,93
|
|
3
|
+
polyapi/api.py,sha256=bE651P47RuhqNYkVyvTH_pA44JypRZED_2M5UG_qzDI,1863
|
|
4
|
+
polyapi/auth.py,sha256=zrIGatjba5GwUTNjKj1GHQWTEDP9B-HrSzCKbLFoqvc,5336
|
|
5
|
+
polyapi/cli.py,sha256=xlKH4cSmSo7eXbyXCLWyL4rXM1QFsltC_MxoxMPgt6I,2187
|
|
6
|
+
polyapi/client.py,sha256=w15XOABkwdL4V4r2iWY_nypzLjvoKVuux8jUKbA16pQ,1329
|
|
7
|
+
polyapi/config.py,sha256=S8TU10upy5OW1_vX-CqQTJD-ZOB6329aMjiUCmukfUI,2292
|
|
8
|
+
polyapi/constants.py,sha256=sc-FnS0SngBLvSu1ZWMs0UCf9EYD1u1Yhfr-sZXGLns,607
|
|
9
|
+
polyapi/error_handler.py,sha256=I_e0iz6VM23FLVQWJljxs2NGcl_OODbi43OcbnqBlp8,2398
|
|
10
|
+
polyapi/exceptions.py,sha256=Zh7i7eCUhDuXEdUYjatkLFTeZkrx1BJ1P5ePgbJ9eIY,89
|
|
11
|
+
polyapi/execute.py,sha256=kXnvlNQ7nz9cRlV2_5gXH09UCmyiDP5zi3wiAw0uDuk,1943
|
|
12
|
+
polyapi/function_cli.py,sha256=F0cb5MGcmFvspgwxptWq_2e50X5NNno0B0p8Vgu_oNI,9129
|
|
13
|
+
polyapi/generate.py,sha256=3-9gN596k9ZzcA-y970kVX2atlvJEKXJoEFvTQTMIik,8662
|
|
14
|
+
polyapi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
+
polyapi/schema.py,sha256=1a7nIO867Xy3bagmPUNdYMxtS5OoCAv8oKIbYgj55dk,2957
|
|
16
|
+
polyapi/server.py,sha256=n-nMGjXoq9T9ZwE2EBDkAaxJ7UytConGaHthkjbkCXA,1894
|
|
17
|
+
polyapi/typedefs.py,sha256=mRqwd2LKofxNn_VSKxBzixni2j-tai8mfTQ0Wi2aLNM,1487
|
|
18
|
+
polyapi/utils.py,sha256=CXzQC5u8vNMyS7f3E45plSuB2EodevDmkOXhHA2zxoc,7108
|
|
19
|
+
polyapi/variables.py,sha256=d36-trnfTL_8m2NkorMiImb4O3UrJbiFV38CHxV5i0A,4200
|
|
20
|
+
polyapi/webhook.py,sha256=GvnS49Vl4k5STTvv4KKUnUAyn27OhIHHXChFmiI53Cs,4849
|
|
21
|
+
polyapi_python-0.2.5.dev1.dist-info/LICENSE,sha256=Hi0kDr56Dsy0uYIwNt4r9G7tI8x8miXRTlyvbeplCP8,1068
|
|
22
|
+
polyapi_python-0.2.5.dev1.dist-info/METADATA,sha256=QatFso95-mIx3hLrLxKiTHXMm2nVibiBnwsqXZymd3Y,4867
|
|
23
|
+
polyapi_python-0.2.5.dev1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
24
|
+
polyapi_python-0.2.5.dev1.dist-info/top_level.txt,sha256=CEFllOnzowci_50RYJac-M54KD2IdAptFsayVVF_f04,8
|
|
25
|
+
polyapi_python-0.2.5.dev1.dist-info/RECORD,,
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
polyapi/__init__.py,sha256=5iujRodfgRyLxT-zY0L3xax3rKRvfSt4NZlZYKOz03w,608
|
|
2
|
-
polyapi/__main__.py,sha256=V4zhAh_YGxno5f_KSrlkELxcuDh9bR3WSd0n-2r-qQQ,93
|
|
3
|
-
polyapi/api.py,sha256=Pq_OT8egmtlzMjovN5GGZXWnF5oWMkrgR0rmrzJ6ifM,1861
|
|
4
|
-
polyapi/auth.py,sha256=p2KSLt6q52t9gnqPmgXTOQ2_lmdFilZkIoGmQrRTPLQ,5330
|
|
5
|
-
polyapi/cli.py,sha256=xlKH4cSmSo7eXbyXCLWyL4rXM1QFsltC_MxoxMPgt6I,2187
|
|
6
|
-
polyapi/client.py,sha256=8k50Vwg9HnmHHTyfKH1vfMJqF0jnnVMsWuWI9AfASkM,761
|
|
7
|
-
polyapi/config.py,sha256=S8TU10upy5OW1_vX-CqQTJD-ZOB6329aMjiUCmukfUI,2292
|
|
8
|
-
polyapi/constants.py,sha256=NGjso6K5rGnE8TGdrXmdEfvvr-HI3DTVGwOYiWO68LM,511
|
|
9
|
-
polyapi/error_handler.py,sha256=I_e0iz6VM23FLVQWJljxs2NGcl_OODbi43OcbnqBlp8,2398
|
|
10
|
-
polyapi/exceptions.py,sha256=Zh7i7eCUhDuXEdUYjatkLFTeZkrx1BJ1P5ePgbJ9eIY,89
|
|
11
|
-
polyapi/execute.py,sha256=kXnvlNQ7nz9cRlV2_5gXH09UCmyiDP5zi3wiAw0uDuk,1943
|
|
12
|
-
polyapi/function_cli.py,sha256=F0cb5MGcmFvspgwxptWq_2e50X5NNno0B0p8Vgu_oNI,9129
|
|
13
|
-
polyapi/generate.py,sha256=fNEBy3ALEu4m1GEEcly-5u-Y1i3G6EWMKKgCyBBJsqc,8568
|
|
14
|
-
polyapi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
-
polyapi/schema.py,sha256=1a7nIO867Xy3bagmPUNdYMxtS5OoCAv8oKIbYgj55dk,2957
|
|
16
|
-
polyapi/server.py,sha256=iXUR1Kd5TnWK-V5qHhvFvQuHx-3IcTv8WChXVY5Mbog,1882
|
|
17
|
-
polyapi/typedefs.py,sha256=a5WfHaAvjeql3y1iA3_SkpUztTbKvS5bPqkVxkCvr9E,1459
|
|
18
|
-
polyapi/utils.py,sha256=86OSrkXlaB0HZppkItT9Xp3m2LBfIT4nPIhyBkIJ0OU,6164
|
|
19
|
-
polyapi/variables.py,sha256=d36-trnfTL_8m2NkorMiImb4O3UrJbiFV38CHxV5i0A,4200
|
|
20
|
-
polyapi/webhook.py,sha256=KidW6J1R4pWsgJ9duPiG-kzO8S28zfVyPhSn8ypD30Y,4325
|
|
21
|
-
polyapi_python-0.2.4.dev12.dist-info/LICENSE,sha256=Hi0kDr56Dsy0uYIwNt4r9G7tI8x8miXRTlyvbeplCP8,1068
|
|
22
|
-
polyapi_python-0.2.4.dev12.dist-info/METADATA,sha256=qwLPcEy6wky4Oc_ZNQza_OE6XhcNPWtMnZGFKpm6bCc,4868
|
|
23
|
-
polyapi_python-0.2.4.dev12.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
24
|
-
polyapi_python-0.2.4.dev12.dist-info/top_level.txt,sha256=CEFllOnzowci_50RYJac-M54KD2IdAptFsayVVF_f04,8
|
|
25
|
-
polyapi_python-0.2.4.dev12.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|