Skip to content

Commit 3563804

Browse files
feat: Add new client parameters: encoding
1 parent af09640 commit 3563804

File tree

4 files changed

+70
-28
lines changed

4 files changed

+70
-28
lines changed

openapi_python_client/__init__.py

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,19 @@ class Project:
4444
project_name_override: Optional[str] = None
4545
package_name_override: Optional[str] = None
4646
package_version_override: Optional[str] = None
47-
48-
def __init__(self, *, openapi: GeneratorData, meta: MetaType, custom_template_path: Optional[Path] = None) -> None:
47+
encoding: Optional[str] = None
48+
49+
def __init__(
50+
self,
51+
*,
52+
openapi: GeneratorData,
53+
meta: MetaType,
54+
custom_template_path: Optional[Path] = None,
55+
encoding: Optional[str] = None,
56+
) -> None:
4957
self.openapi: GeneratorData = openapi
5058
self.meta: MetaType = meta
59+
self.encoding = encoding
5160

5261
package_loader = PackageLoader(__package__)
5362
loader: BaseLoader
@@ -137,15 +146,17 @@ def _create_package(self) -> None:
137146
package_init = self.package_dir / "__init__.py"
138147

139148
package_init_template = self.env.get_template("package_init.py.jinja")
140-
package_init.write_text(package_init_template.render(description=self.package_description))
149+
package_init.write_text(
150+
package_init_template.render(description=self.package_description), encoding=self.encoding
151+
)
141152

142153
if self.meta != MetaType.NONE:
143154
pytyped = self.package_dir / "py.typed"
144-
pytyped.write_text("# Marker file for PEP 561")
155+
pytyped.write_text("# Marker file for PEP 561", encoding=self.encoding)
145156

146157
types_template = self.env.get_template("types.py.jinja")
147158
types_path = self.package_dir / "types.py"
148-
types_path.write_text(types_template.render())
159+
types_path.write_text(types_template.render(), encoding=self.encoding)
149160

150161
def _build_metadata(self) -> None:
151162
if self.meta == MetaType.NONE:
@@ -167,7 +178,7 @@ def _build_metadata(self) -> None:
167178
# .gitignore
168179
git_ignore_path = self.project_dir / ".gitignore"
169180
git_ignore_template = self.env.get_template(".gitignore.jinja")
170-
git_ignore_path.write_text(git_ignore_template.render())
181+
git_ignore_path.write_text(git_ignore_template.render(), encoding=self.encoding)
171182

172183
def _build_pyproject_toml(self, *, use_poetry: bool) -> None:
173184
template = "pyproject.toml.jinja" if use_poetry else "pyproject_no_poetry.toml.jinja"
@@ -204,7 +215,7 @@ def _build_models(self) -> None:
204215
model_template = self.env.get_template("model.py.jinja")
205216
for model in self.openapi.models.values():
206217
module_path = models_dir / f"{model.reference.module_name}.py"
207-
module_path.write_text(model_template.render(model=model))
218+
module_path.write_text(model_template.render(model=model), encoding=self.encoding)
208219
imports.append(import_string_from_reference(model.reference))
209220

210221
# Generate enums
@@ -213,25 +224,25 @@ def _build_models(self) -> None:
213224
for enum in self.openapi.enums.values():
214225
module_path = models_dir / f"{enum.reference.module_name}.py"
215226
if enum.value_type is int:
216-
module_path.write_text(int_enum_template.render(enum=enum))
227+
module_path.write_text(int_enum_template.render(enum=enum), encoding=self.encoding)
217228
else:
218-
module_path.write_text(str_enum_template.render(enum=enum))
229+
module_path.write_text(str_enum_template.render(enum=enum), encoding=self.encoding)
219230
imports.append(import_string_from_reference(enum.reference))
220231

221232
models_init_template = self.env.get_template("models_init.py.jinja")
222-
models_init.write_text(models_init_template.render(imports=imports))
233+
models_init.write_text(models_init_template.render(imports=imports), encoding=self.encoding)
223234

224235
def _build_api(self) -> None:
225236
# Generate Client
226237
client_path = self.package_dir / "client.py"
227238
client_template = self.env.get_template("client.py.jinja")
228-
client_path.write_text(client_template.render())
239+
client_path.write_text(client_template.render(), encoding=self.encoding)
229240

230241
# Generate endpoints
231242
api_dir = self.package_dir / "api"
232243
api_dir.mkdir()
233244
api_init = api_dir / "__init__.py"
234-
api_init.write_text('""" Contains methods for accessing the API """')
245+
api_init.write_text('""" Contains methods for accessing the API """', encoding=self.encoding)
235246

236247
endpoint_template = self.env.get_template("endpoint_module.py.jinja")
237248
for tag, collection in self.openapi.endpoint_collections_by_tag.items():
@@ -242,31 +253,42 @@ def _build_api(self) -> None:
242253

243254
for endpoint in collection.endpoints:
244255
module_path = tag_dir / f"{snake_case(endpoint.name)}.py"
245-
module_path.write_text(endpoint_template.render(endpoint=endpoint))
256+
module_path.write_text(endpoint_template.render(endpoint=endpoint), encoding=self.encoding)
246257

247258

248259
def _get_project_for_url_or_path(
249-
url: Optional[str], path: Optional[Path], meta: MetaType, custom_template_path: Optional[Path] = None
260+
url: Optional[str],
261+
path: Optional[Path],
262+
meta: MetaType,
263+
custom_template_path: Optional[Path] = None,
264+
encoding: Optional[str] = None,
250265
) -> Union[Project, GeneratorError]:
251266
data_dict = _get_document(url=url, path=path)
252267
if isinstance(data_dict, GeneratorError):
253268
return data_dict
254269
openapi = GeneratorData.from_dict(data_dict)
255270
if isinstance(openapi, GeneratorError):
256271
return openapi
257-
return Project(openapi=openapi, custom_template_path=custom_template_path, meta=meta)
272+
return Project(openapi=openapi, custom_template_path=custom_template_path, meta=meta, encoding=encoding)
258273

259274

260275
def create_new_client(
261-
*, url: Optional[str], path: Optional[Path], meta: MetaType, custom_template_path: Optional[Path] = None
276+
*,
277+
url: Optional[str],
278+
path: Optional[Path],
279+
meta: MetaType,
280+
custom_template_path: Optional[Path] = None,
281+
encoding: Optional[str] = None,
262282
) -> Sequence[GeneratorError]:
263283
"""
264284
Generate the client library
265285
266286
Returns:
267287
A list containing any errors encountered when generating.
268288
"""
269-
project = _get_project_for_url_or_path(url=url, path=path, custom_template_path=custom_template_path, meta=meta)
289+
project = _get_project_for_url_or_path(
290+
url=url, path=path, custom_template_path=custom_template_path, meta=meta, encoding=encoding
291+
)
270292
if isinstance(project, GeneratorError):
271293
return [project]
272294
return project.build()

openapi_python_client/cli.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ def generate(
116116
url: Optional[str] = typer.Option(None, help="A URL to read the JSON from"),
117117
path: Optional[pathlib.Path] = typer.Option(None, help="A path to the JSON file"),
118118
custom_template_path: Optional[pathlib.Path] = typer.Option(None, **custom_template_path_options), # type: ignore
119+
encoding: Optional[str] = typer.Option(None, help="Set file encoding for client files"), # type: ignore
119120
meta: MetaType = _meta_option,
120121
) -> None:
121122
""" Generate a new OpenAPI Client library """
@@ -127,7 +128,9 @@ def generate(
127128
if url and path:
128129
typer.secho("Provide either --url or --path, not both", fg=typer.colors.RED)
129130
raise typer.Exit(code=1)
130-
errors = create_new_client(url=url, path=path, meta=meta, custom_template_path=custom_template_path)
131+
errors = create_new_client(
132+
url=url, path=path, meta=meta, custom_template_path=custom_template_path, encoding=encoding
133+
)
131134
handle_errors(errors)
132135

133136

tests/test___init__.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def test__get_project_for_url_or_path(mocker):
2323

2424
_get_document.assert_called_once_with(url=url, path=path)
2525
from_dict.assert_called_once_with(data_dict)
26-
_Project.assert_called_once_with(openapi=openapi, custom_template_path=None, meta=MetaType.POETRY)
26+
_Project.assert_called_once_with(openapi=openapi, custom_template_path=None, meta=MetaType.POETRY, encoding=None)
2727
assert project == _Project.return_value
2828

2929

@@ -76,7 +76,7 @@ def test_create_new_client(mocker):
7676
result = create_new_client(url=url, path=path, meta=MetaType.POETRY)
7777

7878
_get_project_for_url_or_path.assert_called_once_with(
79-
url=url, path=path, custom_template_path=None, meta=MetaType.POETRY
79+
url=url, path=path, custom_template_path=None, meta=MetaType.POETRY, encoding=None
8080
)
8181
project.build.assert_called_once()
8282
assert result == project.build.return_value
@@ -95,7 +95,7 @@ def test_create_new_client_project_error(mocker):
9595
result = create_new_client(url=url, path=path, meta=MetaType.POETRY)
9696

9797
_get_project_for_url_or_path.assert_called_once_with(
98-
url=url, path=path, custom_template_path=None, meta=MetaType.POETRY
98+
url=url, path=path, custom_template_path=None, meta=MetaType.POETRY, encoding=None
9999
)
100100
assert result == [error]
101101

@@ -394,7 +394,7 @@ def test__build_metadata_poetry(self, mocker):
394394
)
395395
readme_path.write_text.assert_called_once_with(readme_template.render())
396396
git_ignore_template.render.assert_called_once()
397-
git_ignore_path.write_text.assert_called_once_with(git_ignore_template.render())
397+
git_ignore_path.write_text.assert_called_once_with(git_ignore_template.render(), encoding=None)
398398
project._build_pyproject_toml.assert_called_once_with(use_poetry=True)
399399

400400
def test__build_metadata_setup(self, mocker):
@@ -431,7 +431,7 @@ def test__build_metadata_setup(self, mocker):
431431
)
432432
readme_path.write_text.assert_called_once_with(readme_template.render())
433433
git_ignore_template.render.assert_called_once()
434-
git_ignore_path.write_text.assert_called_once_with(git_ignore_template.render())
434+
git_ignore_path.write_text.assert_called_once_with(git_ignore_template.render(), encoding=None)
435435
project._build_pyproject_toml.assert_called_once_with(use_poetry=False)
436436
project._build_setup_py.assert_called_once()
437437

tests/test_cli.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,16 @@ def test_config_arg(mocker, _create_new_client):
3131

3232
config_path = "config/path"
3333
path = "cool/path"
34+
encoding = "utf-8"
3435

35-
result = runner.invoke(app, [f"--config={config_path}", "generate", f"--path={path}"], catch_exceptions=False)
36+
result = runner.invoke(
37+
app, [f"--config={config_path}", "generate", f"--path={path}", f"--encoding={encoding}"], catch_exceptions=False
38+
)
3639

3740
assert result.exit_code == 0
3841
load_config.assert_called_once_with(path=Path(config_path))
3942
_create_new_client.assert_called_once_with(
40-
url=None, path=Path(path), custom_template_path=None, meta=MetaType.POETRY
43+
url=None, path=Path(path), custom_template_path=None, meta=MetaType.POETRY, encoding="utf-8"
4144
)
4245

4346

@@ -82,7 +85,9 @@ def test_generate_url(self, _create_new_client):
8285
result = runner.invoke(app, ["generate", f"--url={url}"])
8386

8487
assert result.exit_code == 0
85-
_create_new_client.assert_called_once_with(url=url, path=None, custom_template_path=None, meta=MetaType.POETRY)
88+
_create_new_client.assert_called_once_with(
89+
url=url, path=None, custom_template_path=None, meta=MetaType.POETRY, encoding=None
90+
)
8691

8792
def test_generate_path(self, _create_new_client):
8893
path = "cool/path"
@@ -92,7 +97,7 @@ def test_generate_path(self, _create_new_client):
9297

9398
assert result.exit_code == 0
9499
_create_new_client.assert_called_once_with(
95-
url=None, path=Path(path), custom_template_path=None, meta=MetaType.POETRY
100+
url=None, path=Path(path), custom_template_path=None, meta=MetaType.POETRY, encoding=None
96101
)
97102

98103
def test_generate_meta(self, _create_new_client):
@@ -103,7 +108,19 @@ def test_generate_meta(self, _create_new_client):
103108

104109
assert result.exit_code == 0
105110
_create_new_client.assert_called_once_with(
106-
url=None, path=Path(path), custom_template_path=None, meta=MetaType.NONE
111+
url=None, path=Path(path), custom_template_path=None, meta=MetaType.NONE, encoding=None
112+
)
113+
114+
def test_generate_encoding(self, _create_new_client):
115+
path = "cool/path"
116+
encoding = "utf-8"
117+
from openapi_python_client.cli import MetaType, app
118+
119+
result = runner.invoke(app, ["generate", f"--path={path}", f"--encoding={encoding}"])
120+
121+
assert result.exit_code == 0
122+
_create_new_client.assert_called_once_with(
123+
url=None, path=Path(path), custom_template_path=None, meta=MetaType.POETRY, encoding="utf-8"
107124
)
108125

109126
def test_generate_handle_errors(self, _create_new_client):

0 commit comments

Comments
 (0)