Skip to content

Commit 2e6d41d

Browse files
committed
Support local HTTP ref paths
1 parent 318aa46 commit 2e6d41d

16 files changed

Lines changed: 208 additions & 18 deletions

docs/cli-reference/general-options.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
| [`--generate-pyproject-config`](#generate-pyproject-config) | Generate pyproject.toml configuration from CLI arguments. |
1414
| [`--http-headers`](#http-headers) | Fetch schema from URL with custom HTTP headers. |
1515
| [`--http-ignore-tls`](#http-ignore-tls) | Disable TLS certificate verification for HTTPS requests. |
16+
| [`--http-local-ref-path`](#http-local-ref-path) | Resolve HTTP references from local schema files. |
1617
| [`--http-query-parameters`](#http-query-parameters) | Add query parameters to HTTP requests for remote schemas. |
1718
| [`--http-timeout`](#http-timeout) | Set timeout for HTTP requests to remote hosts. |
1819
| [`--ignore-pyproject`](#ignore-pyproject) | Ignore pyproject.toml configuration file. |
@@ -1631,6 +1632,65 @@ environments with self-signed certificates. Not recommended for production.
16311632

16321633
---
16331634

1635+
## `--http-local-ref-path` {#http-local-ref-path}
1636+
1637+
Resolve HTTP references from local schema files.
1638+
1639+
The `--http-local-ref-path` flag maps HTTP(S) `$ref` URLs to files under
1640+
a local schema store instead of fetching them from the network. The host and
1641+
URL path are used as the relative path under the schema store.
1642+
1643+
!!! tip "Usage"
1644+
1645+
```bash
1646+
datamodel-codegen --input schema.json --url https://api.example.com/schema.json --http-local-ref-path schemas # (1)!
1647+
```
1648+
1649+
1. :material-arrow-left: `--http-local-ref-path` - the option documented here
1650+
1651+
??? example "Examples"
1652+
1653+
**Input Schema:**
1654+
1655+
```json
1656+
{
1657+
"$schema": "http://json-schema.org/draft-07/schema#",
1658+
"title": "Pet",
1659+
"type": "object",
1660+
"properties": {
1661+
"id": {
1662+
"type": "integer"
1663+
},
1664+
"name": {
1665+
"type": "string"
1666+
},
1667+
"tag": {
1668+
"type": "string"
1669+
}
1670+
}
1671+
}
1672+
```
1673+
1674+
**Output:**
1675+
1676+
```python
1677+
# generated by datamodel-codegen:
1678+
# filename: https://api.example.com/schema.json
1679+
# timestamp: 2019-07-26T00:00:00+00:00
1680+
1681+
from __future__ import annotations
1682+
1683+
from pydantic import BaseModel
1684+
1685+
1686+
class Pet(BaseModel):
1687+
id: int | None = None
1688+
name: str | None = None
1689+
tag: str | None = None
1690+
```
1691+
1692+
---
1693+
16341694
## `--http-query-parameters` {#http-query-parameters}
16351695

16361696
Add query parameters to HTTP requests for remote schemas.

docs/cli-reference/index.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ This documentation is auto-generated from test cases.
1515
| 🎨 [Template Customization](template-customization.md) | 21 | Output formatting and custom rendering |
1616
| 📘 [OpenAPI-only Options](openapi-only-options.md) | 7 | OpenAPI-specific features |
1717
| 📋 [GraphQL-only Options](graphql-only-options.md) | 1 | |
18-
| ⚙️ [General Options](general-options.md) | 16 | Utilities and meta options |
18+
| ⚙️ [General Options](general-options.md) | 17 | Utilities and meta options |
1919
| 📝 [Utility Options](utility-options.md) | 6 | Help, version, debug options |
2020

2121
## All Options
@@ -105,6 +105,7 @@ This documentation is auto-generated from test cases.
105105
- [`--help`](utility-options.md#help)
106106
- [`--http-headers`](general-options.md#http-headers)
107107
- [`--http-ignore-tls`](general-options.md#http-ignore-tls)
108+
- [`--http-local-ref-path`](general-options.md#http-local-ref-path)
108109
- [`--http-query-parameters`](general-options.md#http-query-parameters)
109110
- [`--http-timeout`](general-options.md#http-timeout)
110111

docs/cli-reference/model-customization.md

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5272,6 +5272,10 @@ Use default values from schema in generated models.
52725272
The `--use-default` flag allows required fields with default values to be generated
52735273
with their defaults, making them optional to provide when instantiating the model.
52745274

5275+
The field type still follows the schema's nullability. For example, a required
5276+
string field with a default is generated as `str = 'value'`, not
5277+
`str | None = 'value'`, unless the schema allows null.
5278+
52755279
**Related:** [`--strict-nullable`](model-customization.md#strict-nullable)
52765280

52775281
!!! tip "Usage"
@@ -5282,21 +5286,6 @@ with their defaults, making them optional to provide when instantiating the mode
52825286

52835287
1. :material-arrow-left: `--use-default` - the option documented here
52845288

5285-
!!! warning "Fields with defaults become nullable"
5286-
When using `--use-default`, fields with default values are generated as nullable
5287-
types (e.g., `str | None` instead of `str`), even if the schema does not allow
5288-
null values.
5289-
5290-
If you want fields to strictly follow the schema's type definition (non-nullable),
5291-
use `--strict-nullable` together with `--use-default`.
5292-
5293-
5294-
!!! note "Future behavior change"
5295-
In a future major version, the default behavior of `--use-default` may change to
5296-
generate non-nullable types that match the schema definition (equivalent to using
5297-
`--strict-nullable`). If you rely on the current nullable behavior, consider
5298-
explicitly handling this in your code.
5299-
53005289
??? example "Examples"
53015290

53025291
**Input Schema:**

docs/cli-reference/quick-reference.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ datamodel-codegen [OPTIONS]
191191
| [`--generate-pyproject-config`](general-options.md#generate-pyproject-config) | Generate pyproject.toml configuration from CLI arguments. |
192192
| [`--http-headers`](general-options.md#http-headers) | Fetch schema from URL with custom HTTP headers. |
193193
| [`--http-ignore-tls`](general-options.md#http-ignore-tls) | Disable TLS certificate verification for HTTPS requests. |
194+
| [`--http-local-ref-path`](general-options.md#http-local-ref-path) | Resolve HTTP references from local schema files. |
194195
| [`--http-query-parameters`](general-options.md#http-query-parameters) | Add query parameters to HTTP requests for remote schemas. |
195196
| [`--http-timeout`](general-options.md#http-timeout) | Set timeout for HTTP requests to remote hosts. |
196197
| [`--ignore-pyproject`](general-options.md#ignore-pyproject) | Ignore pyproject.toml configuration file. |
@@ -275,6 +276,7 @@ All options sorted alphabetically:
275276
- [`--help`](utility-options.md#help) - Show help message and exit
276277
- [`--http-headers`](general-options.md#http-headers) - Fetch schema from URL with custom HTTP headers.
277278
- [`--http-ignore-tls`](general-options.md#http-ignore-tls) - Disable TLS certificate verification for HTTPS requests.
279+
- [`--http-local-ref-path`](general-options.md#http-local-ref-path) - Resolve HTTP references from local schema files.
278280
- [`--http-query-parameters`](general-options.md#http-query-parameters) - Add query parameters to HTTP requests for remote schemas.
279281
- [`--http-timeout`](general-options.md#http-timeout) - Set timeout for HTTP requests to remote hosts.
280282
- [`--ignore-enum-constraints`](typing-customization.md#ignore-enum-constraints) - Ignore enum constraints and use base string type instead of ...

src/datamodel_code_generator/__main__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ def validate_file(cls, value: Any) -> TextIOBase | None: # noqa: N805
177177
"output",
178178
"custom_template_dir",
179179
"custom_file_header_path",
180+
"http_local_ref_path",
180181
mode="before",
181182
)
182183
def validate_path(cls, value: Any) -> Path | None: # noqa: N805
@@ -493,6 +494,7 @@ def validate_class_name_affix_scope(cls, v: str | ClassNameAffixScope | None) ->
493494
allof_class_hierarchy: AllOfClassHierarchy = AllOfClassHierarchy.IfNoConflict
494495
allow_remote_refs: Optional[bool] = None # noqa: UP045
495496
http_headers: Optional[Sequence[tuple[str, str]]] = None # noqa: UP045
497+
http_local_ref_path: Optional[Path] = None # noqa: UP045
496498
http_ignore_tls: bool = False
497499
http_timeout: Optional[float] = None # noqa: UP045
498500
use_annotated: bool = False
@@ -944,6 +946,7 @@ def run_generate_from_config( # noqa: PLR0913, PLR0917
944946
allof_class_hierarchy=config.allof_class_hierarchy,
945947
allow_remote_refs=config.allow_remote_refs,
946948
http_headers=config.http_headers,
949+
http_local_ref_path=config.http_local_ref_path,
947950
http_ignore_tls=config.http_ignore_tls,
948951
http_timeout=config.http_timeout,
949952
use_annotated=config.use_annotated,

src/datamodel_code_generator/_types/generate_config_dict.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ class GenerateConfigDict(TypedDict, closed=True):
118118
allof_class_hierarchy: NotRequired[AllOfClassHierarchy]
119119
allow_remote_refs: NotRequired[bool | None]
120120
http_headers: NotRequired[Sequence[tuple[str, str]] | None]
121+
http_local_ref_path: NotRequired[Path | None]
121122
http_ignore_tls: NotRequired[bool]
122123
http_timeout: NotRequired[float | None]
123124
use_annotated: NotRequired[bool]

src/datamodel_code_generator/_types/parser_config_dicts.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ class ParserConfigDict(TypedDict):
113113
allof_class_hierarchy: NotRequired[AllOfClassHierarchy]
114114
allow_remote_refs: NotRequired[bool | None]
115115
http_headers: NotRequired[Sequence[tuple[str, str]] | None]
116+
http_local_ref_path: NotRequired[Path | None]
116117
http_ignore_tls: NotRequired[bool]
117118
http_timeout: NotRequired[float | None]
118119
use_annotated: NotRequired[bool]

src/datamodel_code_generator/arguments.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,13 @@ def start_section(self, heading: str | None) -> None:
193193
default=None,
194194
help="Timeout in seconds for HTTP requests to remote hosts (default: 30)",
195195
)
196+
base_options.add_argument(
197+
"--http-local-ref-path",
198+
help=(
199+
"Resolve HTTP(S) JSON Schema $ref URLs from a local directory instead of fetching them. "
200+
"URLs are mapped under the directory by host and path; extensionless refs also try '.json'."
201+
),
202+
)
196203
base_options.add_argument(
197204
"--input",
198205
help="Input file/directory (default: stdin)",

src/datamodel_code_generator/cli_options.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ class CLIOptionMeta:
268268
"--allow-remote-refs": CLIOptionMeta(name="--allow-remote-refs", category=OptionCategory.GENERAL),
269269
"--no-allow-remote-refs": CLIOptionMeta(name="--no-allow-remote-refs", category=OptionCategory.GENERAL),
270270
"--http-headers": CLIOptionMeta(name="--http-headers", category=OptionCategory.GENERAL),
271+
"--http-local-ref-path": CLIOptionMeta(name="--http-local-ref-path", category=OptionCategory.GENERAL),
271272
"--http-ignore-tls": CLIOptionMeta(name="--http-ignore-tls", category=OptionCategory.GENERAL),
272273
"--http-query-parameters": CLIOptionMeta(name="--http-query-parameters", category=OptionCategory.GENERAL),
273274
"--http-timeout": CLIOptionMeta(name="--http-timeout", category=OptionCategory.GENERAL),

src/datamodel_code_generator/config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ class GenerateConfig(BaseModel):
143143
allof_class_hierarchy: AllOfClassHierarchy = AllOfClassHierarchy.IfNoConflict
144144
allow_remote_refs: bool | None = None
145145
http_headers: Sequence[tuple[str, str]] | None = None
146+
http_local_ref_path: Path | None = None
146147
http_ignore_tls: bool = False
147148
http_timeout: float | None = None
148149
use_annotated: bool = False
@@ -276,6 +277,7 @@ class ParserConfig(BaseModel):
276277
allof_class_hierarchy: AllOfClassHierarchy = AllOfClassHierarchy.IfNoConflict
277278
allow_remote_refs: bool | None = None
278279
http_headers: Sequence[tuple[str, str]] | None = None
280+
http_local_ref_path: Path | None = None
279281
http_ignore_tls: bool = False
280282
http_timeout: float | None = None
281283
use_annotated: bool = False

0 commit comments

Comments
 (0)