Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
ded8adb
add new dev version
eupharis Mar 28, 2024
9ee4b83
add error_handler
eupharis Apr 8, 2024
1dd6e8e
add error_handler
eupharis Apr 8, 2024
6ce28d4
catch if import name is different than pip name
eupharis Apr 9, 2024
def20b5
lets hardcode pydantic 2.5.3 and see if that fixes
eupharis Apr 9, 2024
cdd9c63
Revert "lets hardcode pydantic 2.5.3 and see if that fixes"
eupharis Apr 9, 2024
395946c
0.2.3.dev4, actually its problem with kube_hunter, nvm
eupharis Apr 9, 2024
5626e58
maybe we need the new requirements
eupharis Apr 9, 2024
bcfe77f
woot client functions are done?
eupharis Apr 11, 2024
6947e87
fix tests
eupharis Apr 11, 2024
a6fe1b4
0.2.3.dev7, dont assume client function, must specify with --client
eupharis Apr 12, 2024
6ffd13d
0.2.3.dev8 fix small bug client functions
eupharis Apr 15, 2024
f10ac61
0.2.3.dev9, add fallbacks if unrecognized version of OpenAPI present …
eupharis Apr 15, 2024
e065e0d
add pyjwt to requirements
eupharis Apr 15, 2024
0d63475
add ability to do multiple error handlers!
eupharis Apr 17, 2024
3a24f7d
dont require pyjwt anymore
eupharis Apr 17, 2024
c9120ef
0.2.4.dev2, replace hacky manual mimetypes with real mimetypes
eupharis Apr 18, 2024
6d5a11e
add polycustom
eupharis Apr 19, 2024
44e63d6
multi webhook (#9)
eupharis Apr 22, 2024
76e4e82
update pyproject.toml
eupharis Apr 22, 2024
d9c79d6
0.2.4.dev5, accept non-200 and non-201 status codes from polyCustom
eupharis Apr 22, 2024
c4f0e5b
0.2.4.dev6 bring python client in line with execute server and consid…
eupharis Apr 22, 2024
3eaab8a
0.2.4.dev7, make TypedDict input and response types more picky if wro…
eupharis Apr 22, 2024
fbf9171
actually use args in webhook
eupharis Apr 23, 2024
60cad53
0.2.4.dev8, fix webhook stopping text
eupharis Apr 23, 2024
ad32f3e
Merge branch 'develop' into better-webhooks
eupharis Apr 23, 2024
39cc2c0
getting there
eupharis Apr 23, 2024
9631e64
0.2.4.dev9, handle already connected error on windows
eupharis Apr 23, 2024
51c33cd
0.2.4.deva1, better user facing messages for webhooks and error handlers
eupharis Apr 23, 2024
e6eff39
woops lets go version 10
eupharis Apr 23, 2024
1fe0b58
0.2.4.dev11
eupharis Apr 23, 2024
a49780e
move polyCustom to own file
eupharis Apr 24, 2024
628bd1f
Merge branch 'develop' into better-webhooks
eupharis Apr 25, 2024
5c66cfa
onward
eupharis Apr 25, 2024
9d8e053
fix it
eupharis Apr 25, 2024
cd087fb
0.2.4.dev13, fix client functions polluting other server functions
eupharis Apr 30, 2024
7a3ba63
merge
eupharis May 1, 2024
d24a8aa
new version
eupharis May 1, 2024
118f73e
Merge branch 'develop' into better-webhooks
eupharis May 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions polyapi/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ def {function_name}(
\"""
resp = execute("{function_type}", "{function_id}", {data})
return {api_response_type}(resp.json()) # type: ignore


"""


Expand Down
6 changes: 3 additions & 3 deletions polyapi/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@


class AuthFunctionResponse(TypedDict):
status: int
data: Any
headers: Dict[str, str]
status: int
data: Any
headers: Dict[str, str]


async def getToken(clientId: str, clientSecret: str, scopes: List[str], callback, options: Optional[Dict[str, Any]] = None):
Expand Down
4 changes: 4 additions & 0 deletions polyapi/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
"boolean": "bool",
"array": "List",
"object": "Dict",
"function": "Callable",
"void": "None",
}


Expand All @@ -15,6 +17,8 @@
"bool": "boolean",
"List": "array",
"Dict": "object",
"Callable": "function",
"None": "void",
}

BASIC_PYTHON_TYPES = set(PYTHON_TO_JSONSCHEMA_TYPE_MAP.keys())
Expand Down
4 changes: 3 additions & 1 deletion polyapi/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from polyapi.utils import camelCase, add_type_import_path, parse_arguments, get_type_and_def

SERVER_DEFS_TEMPLATE = """
from typing import List, Dict, Any, TypedDict
from typing import List, Dict, Any, TypedDict, Callable
{args_def}
{return_type_def}
"""
Expand All @@ -22,6 +22,8 @@ def {function_name}(
return {return_action}
except:
return resp.text


"""


Expand Down
1 change: 1 addition & 0 deletions polyapi/typedefs.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class PropertySpecification(TypedDict):

class PropertyType(TypedDict):
kind: Literal['void', 'primitive', 'array', 'object', 'function', 'plain']
spec: NotRequired[Dict]
name: NotRequired[str]
type: NotRequired[str]
items: NotRequired['PropertyType']
Expand Down
25 changes: 24 additions & 1 deletion polyapi/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

# this string should be in every __init__ file.
# it contains all the imports needed for the function or variable code to run
CODE_IMPORTS = "from typing import List, Dict, Any, TypedDict, Optional\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"
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"


def init_the_init(full_path: str) -> None:
Expand Down Expand Up @@ -61,6 +61,10 @@ def print_red(s: str):
def add_type_import_path(function_name: str, arg: str) -> str:
""" if not basic type, coerce to camelCase and add the import path
"""
# for now, just treat Callables as basic types
if arg.startswith("Callable"):
return arg

if arg in BASIC_PYTHON_TYPES:
return arg

Expand Down Expand Up @@ -142,6 +146,25 @@ def get_type_and_def(type_spec: PropertyType) -> Tuple[str, str]:
return "Any", ""
else:
return "Dict", ""
elif type_spec["kind"] == "function":
arg_types = []
arg_defs = []
if "spec" in type_spec:
return_type, _ = get_type_and_def(type_spec["spec"]["returnType"])
if return_type not in BASIC_PYTHON_TYPES:
# for now only Python only supports basic types as return types
return_type = "Any"

for argument in type_spec["spec"]["arguments"]:
arg_type, arg_def = get_type_and_def(argument["type"])
arg_types.append(arg_type)
if arg_def:
arg_defs.append(arg_def)

final_arg_type = "Callable[[{}], {}]".format(", ".join(arg_types), return_type)
return final_arg_type, "\n".join(arg_defs)
else:
return "Callable", ""
elif type_spec["kind"] == "any":
return "Any", ""
else:
Expand Down
23 changes: 19 additions & 4 deletions polyapi/webhook.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from polyapi.config import get_api_key_and_url
from polyapi.typedefs import PropertySpecification
from polyapi.utils import poly_full_path
from polyapi.utils import parse_arguments, poly_full_path

# all active webhook handlers, used by unregister_all to cleanup
active_handlers: List[Dict[str, Any]] = []
Expand All @@ -15,10 +15,18 @@
client = None


WEBHOOK_DEFS_TEMPLATE = """
from typing import List, Dict, Any, TypedDict, Callable
{function_args_def}
"""


WEBHOOK_TEMPLATE = """


async def {function_name}(callback, options=None):
async def {function_name}(
{function_args}
):
\"""{description}

Function ID: {function_id}
Expand Down Expand Up @@ -112,15 +120,22 @@ def render_webhook_handle(
arguments: List[PropertySpecification],
return_type: Dict[str, Any],
) -> Tuple[str, str]:
function_args, function_args_def = parse_arguments(function_name, arguments)

if "WebhookEventType" in function_args:
# let's add the function name import!
function_args = function_args.replace("WebhookEventType", f"_{function_name}.WebhookEventType")

func_str = WEBHOOK_TEMPLATE.format(
description=function_description,
client_id=uuid.uuid4().hex,
function_id=function_id,
function_name=function_name,
function_args=function_args,
function_path=poly_full_path(function_context, function_name),
)

return func_str, ""
func_defs = WEBHOOK_DEFS_TEMPLATE.format(function_args_def=function_args_def)
return func_str, func_defs


def start(*args):
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ requires = ["setuptools>=61.2", "wheel"]

[project]
name = "polyapi-python"
version = "0.2.4"
version = "0.2.5.dev1"
description = "The Python Client for PolyAPI, the IPaaS by Developers for Developers"
authors = [{ name = "Dan Fellin", email = "[email protected]" }]
dependencies = [
Expand Down
7 changes: 7 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import unittest
from polyapi.schema import _fix_title
from polyapi.utils import get_type_and_def

OPENAPI_FUNCTION = {'kind': 'function', 'spec': {'arguments': [{'name': 'event', 'required': False, 'type': {'kind': 'object', 'schema': {'$schema': 'http://json-schema.org/draft-06/schema#', 'type': 'array', 'items': {'$ref': '#/definitions/WebhookEventTypeElement'}, 'definitions': {'WebhookEventTypeElement': {'type': 'object', 'additionalProperties': False, 'properties': {'title': {'type': 'string'}, 'manufacturerName': {'type': 'string'}, 'carType': {'type': 'string'}, 'id': {'type': 'integer'}}, 'required': ['carType', 'id', 'manufacturerName', 'title'], 'title': 'WebhookEventTypeElement'}}}}}, {'name': 'headers', 'required': False, 'type': {'kind': 'object', 'typeName': 'Record<string, any>'}}, {'name': 'params', 'required': False, 'type': {'kind': 'object', 'typeName': 'Record<string, any>'}}, {'name': 'polyCustom', 'required': False, 'type': {'kind': 'object', 'properties': [{'name': 'responseStatusCode', 'type': {'type': 'number', 'kind': 'primitive'}, 'required': True}, {'name': 'responseContentType', 'type': {'type': 'string', 'kind': 'primitive'}, 'required': True, 'nullable': True}]}}], 'returnType': {'kind': 'void'}, 'synchronous': True}}


class T(unittest.TestCase):
Expand All @@ -8,3 +11,7 @@ def test_fix_titles(self):
output = 'from typing import TypedDict\nfrom typing_extensions import Required\n\n\nclass Numofcars(TypedDict, total=False):\n """ numOfCars. """\n\n requestNumber: Required[int]\n """\n Requestnumber.\n\n Required property\n """\n\n'
fixed = _fix_title(input_data, output)
self.assertIn("class numOfCars", fixed)

def test_get_type_and_def(self):
arg_type, arg_def = get_type_and_def(OPENAPI_FUNCTION)
self.assertEqual(arg_type, "Callable[[List[WebhookEventTypeElement], Dict, Dict, Dict], None]")