Skip to content

Commit 99638b1

Browse files
rtaycherdbanty
andauthored
feat: add use_path_prefixes_for_title_model_names config option for simpler model names [#559, #560]. Thanks @rtaycher!
Co-authored-by: Dylan Anthony <[email protected]>
1 parent dd81e19 commit 99638b1

File tree

4 files changed

+58
-3
lines changed

4 files changed

+58
-3
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,5 +157,13 @@ post_hooks:
157157
- "black ."
158158
```
159159

160+
### use_path_prefixes_for_title_model_names
161+
162+
By default, `openapi-python-client` generates class names which include the full path to the schema, including any parent-types. This can result in very long class names like `MyRouteSomeClassAnotherClassResponse`—which is very unique and unlikely to cause conflicts with future API additions, but also super verbose.
163+
164+
If you are carefully curating your `title` properties already to ensure no duplicate class names, you can turn off this prefixing feature by setting `use_path_prefixes_for_title_model_names` to `false` in your config file. This will use the `title` property of any object that has it set _without_ prefixing.
165+
166+
If this option results in conflicts, you will need to manually override class names instead via the `class_overrides` option.
167+
160168
[changelog.md]: CHANGELOG.md
161169
[poetry]: https://python-poetry.org/

openapi_python_client/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class Config(BaseModel):
2727
project_name_override: Optional[str]
2828
package_name_override: Optional[str]
2929
package_version_override: Optional[str]
30+
use_path_prefixes_for_title_model_names: bool = True
3031
post_hooks: List[str] = [
3132
"autoflake -i -r --remove-all-unused-imports --remove-unused-variables --ignore-init-module-imports .",
3233
"isort .",

openapi_python_client/parser/properties/model_property.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -391,9 +391,14 @@ def build_model_property(
391391
roots: Set of strings that identify schema objects on which the new ModelProperty will depend
392392
process_properties: Determines whether the new ModelProperty will be initialized with property data
393393
"""
394-
class_string = data.title or name
395-
if parent_name:
396-
class_string = f"{utils.pascal_case(parent_name)}{utils.pascal_case(class_string)}"
394+
if not config.use_path_prefixes_for_title_model_names and data.title:
395+
class_string = data.title
396+
else:
397+
title = data.title or name
398+
if parent_name:
399+
class_string = f"{utils.pascal_case(parent_name)}{utils.pascal_case(title)}"
400+
else:
401+
class_string = title
397402
class_info = Class.from_string(string=class_string, config=config)
398403
model_roots = {*roots, class_info.name}
399404
required_properties: Optional[List[Property]] = None

tests/test_parser/test_properties/test_model_property.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from typing import Optional
12
from unittest.mock import MagicMock
23

34
import pytest
@@ -201,6 +202,46 @@ def test_model_name_conflict(self):
201202
assert new_schemas == schemas
202203
assert err == PropertyError(detail='Attempted to generate duplicate models with name "OtherModel"', data=data)
203204

205+
@pytest.mark.parametrize(
206+
"name, title, parent_name, use_title_prefixing, expected",
207+
ids=(
208+
"basic name only",
209+
"title override",
210+
"name with parent",
211+
"name with parent and title prefixing disabled",
212+
"title with parent",
213+
"title with parent and title prefixing disabled",
214+
),
215+
argvalues=(
216+
("prop", None, None, True, "Prop"),
217+
("prop", "MyModel", None, True, "MyModel"),
218+
("prop", None, "parent", True, "ParentProp"),
219+
("prop", None, "parent", False, "ParentProp"),
220+
("prop", "MyModel", "parent", True, "ParentMyModel"),
221+
("prop", "MyModel", "parent", False, "MyModel"),
222+
),
223+
)
224+
def test_model_naming(
225+
self, name: str, title: Optional[str], parent_name: Optional[str], use_title_prefixing: bool, expected: str
226+
):
227+
from openapi_python_client.parser.properties import Schemas, build_model_property
228+
229+
data = oai.Schema(
230+
title=title,
231+
properties={},
232+
)
233+
result = build_model_property(
234+
data=data,
235+
name=name,
236+
schemas=Schemas(),
237+
required=True,
238+
parent_name=parent_name,
239+
config=Config(use_path_prefixes_for_title_model_names=use_title_prefixing),
240+
roots={"root"},
241+
process_properties=True,
242+
)[0]
243+
assert result.class_info.name == expected
244+
204245
def test_model_bad_properties(self):
205246
from openapi_python_client.parser.properties import Schemas, build_model_property
206247

0 commit comments

Comments
 (0)