Skip to content

Commit f8416ee

Browse files
fix schema generation (#64)
1 parent d32781a commit f8416ee

File tree

3 files changed

+53
-5
lines changed

3 files changed

+53
-5
lines changed

polyapi/poly_schemas.py

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,13 @@
2525

2626
def generate_schemas(specs: List[SchemaSpecDto], limit_ids: List[str] = None):
2727
failed_schemas = []
28+
successful_schemas = []
2829
if limit_ids:
2930
for spec in specs:
3031
if spec["id"] in limit_ids:
3132
try:
3233
create_schema(spec)
34+
successful_schemas.append(f"{spec.get('context', 'unknown')}.{spec.get('name', 'unknown')}")
3335
except Exception as e:
3436
schema_path = f"{spec.get('context', 'unknown')}.{spec.get('name', 'unknown')}"
3537
schema_id = spec.get('id', 'unknown')
@@ -40,6 +42,7 @@ def generate_schemas(specs: List[SchemaSpecDto], limit_ids: List[str] = None):
4042
for spec in specs:
4143
try:
4244
create_schema(spec)
45+
successful_schemas.append(f"{spec.get('context', 'unknown')}.{spec.get('name', 'unknown')}")
4346
except Exception as e:
4447
schema_path = f"{spec.get('context', 'unknown')}.{spec.get('name', 'unknown')}"
4548
schema_id = spec.get('id', 'unknown')
@@ -51,6 +54,37 @@ def generate_schemas(specs: List[SchemaSpecDto], limit_ids: List[str] = None):
5154
logging.warning(f"WARNING: {len(failed_schemas)} schema(s) failed to generate:")
5255
for failed_schema in failed_schemas:
5356
logging.warning(f" - {failed_schema}")
57+
logging.warning(f"Successfully generated {len(successful_schemas)} schema(s)")
58+
59+
60+
def validate_schema_content(schema_content: str, schema_name: str) -> bool:
61+
"""
62+
Validate that the schema content is meaningful and not just imports.
63+
Returns True if the schema is valid, False otherwise.
64+
"""
65+
if not schema_content or not schema_content.strip():
66+
logging.debug(f"Schema {schema_name} failed validation: Empty content")
67+
return False
68+
69+
lines = schema_content.strip().split('\n')
70+
71+
# Check if the content has any actual class definitions or type aliases
72+
has_class_definition = any(line.strip().startswith('class ') for line in lines)
73+
has_type_alias = any(schema_name in line and '=' in line and not line.strip().startswith('#') for line in lines)
74+
75+
# Check if it's essentially just imports (less than 5 lines and no meaningful definitions)
76+
meaningful_lines = [line for line in lines if line.strip() and not line.strip().startswith('from ') and not line.strip().startswith('import ') and not line.strip().startswith('#')]
77+
78+
# Enhanced logging for debugging
79+
if not (has_class_definition or has_type_alias) or len(meaningful_lines) < 1:
80+
# Determine the specific reason for failure
81+
if len(meaningful_lines) == 0:
82+
logging.debug(f"Schema {schema_name} failed validation: No meaningful content (only imports) - likely empty object or unresolved reference")
83+
elif not has_class_definition and not has_type_alias:
84+
logging.debug(f"Schema {schema_name} failed validation: No class definition or type alias found")
85+
return False
86+
87+
return True
5488

5589

5690
def add_schema_file(
@@ -75,9 +109,9 @@ def add_schema_file(
75109

76110
schema_defs = render_poly_schema(spec)
77111

78-
if not schema_defs:
79-
# If render_poly_schema failed and returned empty string, don't create any files
80-
raise Exception("Schema rendering failed - empty schema content returned")
112+
# Validate schema content before proceeding
113+
if not validate_schema_content(schema_defs, schema_name):
114+
raise Exception(f"Schema rendering failed or produced invalid content for {schema_name}")
81115

82116
# Prepare all content first before writing any files
83117
schema_namespace = to_func_namespace(schema_name)

polyapi/schema.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,26 @@ def generate_schema_types(input_data: Dict, root=None):
104104
# Regex to match everything between "# example: {\n" and "^}$"
105105
MALFORMED_EXAMPLES_PATTERN = re.compile(r"# example: \{\n.*?^\}$", flags=re.DOTALL | re.MULTILINE)
106106

107+
# Regex to fix invalid escape sequences in docstrings
108+
INVALID_ESCAPE_PATTERNS = [
109+
# Fix "\ " (backslash space) which is not a valid escape sequence
110+
(re.compile(r'\\(\s)', re.DOTALL), r'\1'),
111+
# Fix other common invalid escape sequences in docstrings
112+
(re.compile(r'\\([^nrtbfav"\'\\])', re.DOTALL), r'\\\\\1'),
113+
]
114+
107115

108116
def clean_malformed_examples(example: str) -> str:
109117
""" there is a bug in the `jsonschmea_gentypes` library where if an example from a jsonchema is an object,
110-
it will break the code because the object won't be properly commented out
118+
it will break the code because the object won't be properly commented out. Also fixes invalid escape sequences.
111119
"""
120+
# Remove malformed examples
112121
cleaned_example = MALFORMED_EXAMPLES_PATTERN.sub("", example)
122+
123+
# Fix invalid escape sequences in docstrings
124+
for pattern, replacement in INVALID_ESCAPE_PATTERNS:
125+
cleaned_example = pattern.sub(replacement, cleaned_example)
126+
113127
return cleaned_example
114128

115129

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ requires = ["setuptools>=61.2", "wheel"]
33

44
[project]
55
name = "polyapi-python"
6-
version = "0.3.8.dev9"
6+
version = "0.3.8.dev10"
77
description = "The Python Client for PolyAPI, the IPaaS by Developers for Developers"
88
authors = [{ name = "Dan Fellin", email = "dan@polyapi.io" }]
99
dependencies = [

0 commit comments

Comments
 (0)