diff --git a/polyapi/schema.py b/polyapi/schema.py index 3ebcc49..04353a5 100644 --- a/polyapi/schema.py +++ b/polyapi/schema.py @@ -1,3 +1,4 @@ +import logging import contextlib from typing import Dict from jsonschema_gentypes.cli import process_config @@ -31,6 +32,21 @@ def _temp_store_input_data(input_data: Dict) -> str: return temp_file.name +def wrapped_generate_schema_types(type_spec: dict, root, fallback_type): + if not root: + root = "MyList" if fallback_type == "List" else "MyDict" + + try: + return clean_title(root), generate_schema_types(type_spec, root=root) + except RecursionError: + # some schemas are so huge, our library cant handle it + # TODO identify critical recursion penalty and maybe switch underlying logic to iterative? + return fallback_type, "" + except: + logging.exception(f"Error when generating schema type: {type_spec}") + return fallback_type, "" + + def generate_schema_types(input_data: Dict, root=None): """takes in a Dict representing a schema as input then appends the resulting python code to the output file""" _cleanup_input_for_gentypes(input_data) diff --git a/polyapi/utils.py b/polyapi/utils.py index bba3463..d7b105b 100644 --- a/polyapi/utils.py +++ b/polyapi/utils.py @@ -1,16 +1,16 @@ import re import os -import logging from typing import Tuple, List from colorama import Fore, Style from polyapi.constants import BASIC_PYTHON_TYPES from polyapi.typedefs import PropertySpecification, PropertyType -from polyapi.schema import generate_schema_types, clean_title, map_primitive_types +from polyapi.schema import wrapped_generate_schema_types, clean_title, map_primitive_types # 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, 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" +FALLBACK_TYPES = {"Dict", "List"} def init_the_init(full_path: str) -> None: @@ -96,11 +96,7 @@ def get_type_and_def(type_spec: PropertyType) -> Tuple[str, str]: if type_spec.get("items"): items = type_spec["items"] if items.get("$ref"): - try: - return "ResponseType", generate_schema_types(type_spec, root="ResponseType") # type: ignore - except: - logging.exception(f"Error when generating schema type: {type_spec}") - return "Dict", "" + return wrapped_generate_schema_types(type_spec, "ResponseType", "Dict") # type: ignore else: item_type, _ = get_type_and_def(items) title = f"List[{item_type}]" @@ -116,12 +112,7 @@ def get_type_and_def(type_spec: PropertyType) -> Tuple[str, str]: title = schema.get("title", "") if title: assert isinstance(title, str) - title = clean_title(title) - try: - return title, generate_schema_types(schema, root=title) # type: ignore - except: - logging.exception(f"Error when generating schema type: {schema}") - return "Dict", "" + return wrapped_generate_schema_types(schema, title, "Dict") # type: ignore elif schema.get("items"): # fallback to schema $ref name if no explicit title @@ -132,16 +123,11 @@ def get_type_and_def(type_spec: PropertyType) -> Tuple[str, str]: title = items.get("$ref", "") # type: ignore title = title.rsplit("/", 1)[-1] - title = clean_title(title) if not title: return "List", "" title = f"List[{title}]" - try: - return title, generate_schema_types(schema, root=title) - except: - logging.exception(f"Error when generating schema type: {schema}") - return "List", "" + return wrapped_generate_schema_types(schema, title, "List") else: return "Any", "" else: diff --git a/pyproject.toml b/pyproject.toml index 59a416f..989d5db 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ requires = ["setuptools>=61.2", "wheel"] [project] name = "polyapi-python" -version = "0.2.5.dev8" +version = "0.2.5.dev9" description = "The Python Client for PolyAPI, the IPaaS by Developers for Developers" authors = [{ name = "Dan Fellin", email = "dan@polyapi.io" }] dependencies = [ diff --git a/tests/test_schema.py b/tests/test_schema.py index 965ac69..8602fd6 100644 --- a/tests/test_schema.py +++ b/tests/test_schema.py @@ -1,14 +1,20 @@ import unittest -from polyapi.schema import generate_schema_types +from polyapi.schema import wrapped_generate_schema_types + +SCHEMA = { + "$schema": "http://json-schema.org/draft-06/schema#", + "type": "object", + "properties": {"name": {"type": "string"}}, + "required": ["name"], + "additionalProperties": False, + "definitions": {}, +} class T(unittest.TestCase): def test_fix_titles(self): - # schema = json.loads(SCHEMA) - schema = {"$schema": "http://json-schema.org/draft-06/schema#"} - try: - a, b = generate_schema_types(schema) - except AssertionError: - pass - - # should not throw with unknown dialect error \ No newline at end of file + output = wrapped_generate_schema_types(SCHEMA, "", "Dict") + self.assertEqual("MyDict", output[0]) + self.assertIn("class MyDict", output[1]) + + # should not throw with unknown dialect error