From 9ac98f6976ca7247f671bc6dad34d52e8f49c09d Mon Sep 17 00:00:00 2001 From: Daniel Estoll Date: Fri, 27 Jun 2025 11:12:14 -0600 Subject: [PATCH 1/3] Changed encoding to utf-8 and added unit test --- polyapi/poly_schemas.py | 6 +++--- polyapi/schema.py | 2 +- tests/test_schema.py | 18 ++++++++++++++++-- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/polyapi/poly_schemas.py b/polyapi/poly_schemas.py index 6b42ec7..f12f77a 100644 --- a/polyapi/poly_schemas.py +++ b/polyapi/poly_schemas.py @@ -48,12 +48,12 @@ def add_schema_file( if schema_defs: # add function to init init_path = os.path.join(full_path, "__init__.py") - with open(init_path, "a") as f: + with open(init_path, "a", encoding="utf-8") as f: f.write(f"\n\nfrom ._{to_func_namespace(schema_name)} import {schema_name}\n__all__.append('{schema_name}')\n") # add type_defs to underscore file file_path = os.path.join(full_path, f"_{to_func_namespace(schema_name)}.py") - with open(file_path, "w") as f: + with open(file_path, "w", encoding="utf-8") as f: f.write(schema_defs) @@ -85,7 +85,7 @@ def create_schema( def add_schema_to_init(full_path: str, spec: SchemaSpecDto): init_the_init(full_path, code_imports="") init_path = os.path.join(full_path, "__init__.py") - with open(init_path, "a") as f: + with open(init_path, "a", encoding='utf-8') as f: f.write(render_poly_schema(spec) + "\n\n") diff --git a/polyapi/schema.py b/polyapi/schema.py index 5db567a..1d48378 100644 --- a/polyapi/schema.py +++ b/polyapi/schema.py @@ -93,7 +93,7 @@ def generate_schema_types(input_data: Dict, root=None): with contextlib.redirect_stdout(None): process_config(config, [tmp_input]) - with open(tmp_output) as f: + with open(tmp_output, encoding='utf-8') as f: output = f.read() output = clean_malformed_examples(output) diff --git a/tests/test_schema.py b/tests/test_schema.py index 223ec39..ae23ce3 100644 --- a/tests/test_schema.py +++ b/tests/test_schema.py @@ -1,5 +1,5 @@ import unittest -from polyapi.schema import clean_malformed_examples, wrapped_generate_schema_types +from polyapi.schema import clean_malformed_examples, wrapped_generate_schema_types, generate_schema_types SCHEMA = { "$schema": "http://json-schema.org/draft-06/schema#", @@ -10,6 +10,14 @@ "definitions": {}, } +CHARACTER_SCHEMA = { + "$schema": "http://json-schema.org/draft-06/schema#", + "type": "object", + "properties": {"CHARACTER_SCHEMA_NAME": {"description": "This is — “bad”, right?", "type": "string"}}, + "additionalProperties": False, + "definitions": {}, +} + APALEO_MALFORMED_EXAMPLE = 'from typing import List, TypedDict, Union\nfrom typing_extensions import Required\n\n\n# Body.\n# \n# example: {\n "from": "2024-04-21",\n "to": "2024-04-24",\n "grossDailyRate": {\n "amount": 160.0,\n "currency": "EUR"\n },\n "timeSlices": [\n {\n "blockedUnits": 3\n },\n {\n "blockedUnits": 0\n },\n {\n "blockedUnits": 7\n }\n ]\n}\n# x-readme-ref-name: ReplaceBlockModel\nBody = TypedDict(\'Body\', {\n # Start date and time from which the inventory will be blockedSpecify either a pure date or a date and time (without fractional second part) in UTC or with UTC offset as defined in ISO8601:2004\n # \n # Required property\n \'from\': Required[str],\n # End date and time until which the inventory will be blocked. Cannot be more than 5 years after the start date.Specify either a pure date or a date and time (without fractional second part) in UTC or with UTC offset as defined in ISO8601:2004\n # \n # Required property\n \'to\': Required[str],\n # x-readme-ref-name: MonetaryValueModel\n # \n # Required property\n \'grossDailyRate\': Required["_BodygrossDailyRate"],\n # The list of time slices\n # \n # Required property\n \'timeSlices\': Required[List["_BodytimeSlicesitem"]],\n}, total=False)\n\n\nclass _BodygrossDailyRate(TypedDict, total=False):\n """ x-readme-ref-name: MonetaryValueModel """\n\n amount: Required[Union[int, float]]\n """\n format: double\n\n Required property\n """\n\n currency: Required[str]\n """ Required property """\n\n\n\nclass _BodytimeSlicesitem(TypedDict, total=False):\n """ x-readme-ref-name: CreateBlockTimeSliceModel """\n\n blockedUnits: Required[Union[int, float]]\n """\n Number of units blocked for the time slice\n\n format: int32\n\n Required property\n """\n\n' @@ -23,4 +31,10 @@ def test_fix_titles(self): def test_clean_malformed_examples(self): output = clean_malformed_examples(APALEO_MALFORMED_EXAMPLE) - self.assertNotIn("# example: {", output) \ No newline at end of file + self.assertNotIn("# example: {", output) + + def test_character_encoding(self): + output = generate_schema_types(CHARACTER_SCHEMA, "Dict") + expected = 'from typing import TypedDict\n\n\nclass Dict(TypedDict, total=False):\n CHARACTER_SCHEMA_NAME: str\n """ This is — “bad”, right? """\n\n' + self.assertEqual(output, expected) + \ No newline at end of file From 8793cf743da3e0b19883e31bc390e29bdcebd212 Mon Sep 17 00:00:00 2001 From: Daniel Estoll Date: Fri, 27 Jun 2025 11:14:33 -0600 Subject: [PATCH 2/3] changed version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 516a121..05cb142 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ requires = ["setuptools>=61.2", "wheel"] [project] name = "polyapi-python" -version = "0.3.8.dev7" +version = "0.3.8.dev8" description = "The Python Client for PolyAPI, the IPaaS by Developers for Developers" authors = [{ name = "Dan Fellin", email = "dan@polyapi.io" }] dependencies = [ From ed75a8607c3e384e6efcbaaf032e093ca7b53b7e Mon Sep 17 00:00:00 2001 From: Daniel Estoll Date: Mon, 7 Jul 2025 10:02:49 -0600 Subject: [PATCH 3/3] Updated version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f2daf3e..33131a4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ requires = ["setuptools>=61.2", "wheel"] [project] name = "polyapi-python" -version = "0.3.8.dev10" +version = "0.3.9.dev1" description = "The Python Client for PolyAPI, the IPaaS by Developers for Developers" authors = [{ name = "Dan Fellin", email = "dan@polyapi.io" }] dependencies = [