Repository: koxudaxi/datamodel-code-generator

Issue:
Flag `--use-non-positive-negative-number-constrained-types` doesn't work when generating Pydantic v2 classes
**Describe the bug**
When running `datamodel-codegen` against my openapi-example.json input to generate Pydantic v2 classes, the `--use-non-positive-negative-number-constrained-types` flag seems to have no effect.

**To Reproduce**

Example schema:
```json
{
  "openapi": "3.0.0",
  "components": {
    "schemas": {
      "Record": {
        "properties": {
          "uuid": {
            "title": "Uuid",
            "type": "string"
          },
          "sequence": {
            "anyOf": [
              {
                "minimum": 0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": 0,
            "title": "Sequence"
          }
        },
        "required": ["uuid"],
        "title": "Record",
        "type": "object"
      }
    }
  }
}
```

Used commandline:
```
$ uv run datamodel-codegen \
                  --input openapi-example.json \
                  --output out.py \
                  --input-file-type openapi \
                  --output-model-type pydantic_v2.BaseModel \
                  --use-non-positive-negative-number-constrained-types
```

Generates out.py looking like this:

```python
# generated by datamodel-codegen:
#   filename:  openapi-example.json
#   timestamp: 2025-06-17T07:42:12+00:00

from __future__ import annotations

from typing import Optional

from pydantic import BaseModel, Field, conint


class Record(BaseModel):
    uuid: str = Field(..., title='Uuid')
    sequence: Optional[conint(ge=0)] = Field(0, title='Sequence')
```

Also tried with `--field-constraints`:
```
$ uv run datamodel-codegen \
                  --input openapi-example.json \
                  --output out.py \
                  --input-file-type openapi \
                  --output-model-type pydantic_v2.BaseModel \
                  --field-constraints \
                  --use-non-positive-negative-number-constrained-types
```

which generates:

```python
# generated by datamodel-codegen:
#   filename:  openapi-example.json
#   timestamp: 2025-06-17T07:42:26+00:00

from __future__ import annotations

from typing import Optional

from pydantic import BaseModel, Field, RootModel


class Sequence(RootModel[int]):
    root: int = Field(..., ge=0, title='Sequence')


class Record(BaseModel):
    uuid: str = Field(..., title='Uuid')
    sequence: Optional[Sequence] = Field(0, title='Sequence')
```

and also with all the flags that I think I actually want in my real project:

```
$ uv run datamodel-codegen \
                  --input openapi-example.json \
                  --output out.py \
                  --input-file-type openapi \
                  --output-model-type pydantic_v2.BaseModel \
                  --field-constraints \
                  --set-default-enum-member \
                  --use-union-operator \
                  --use-standard-collections \
                  --use-field-description \
                  --use-schema-description \
                  --use-non-positive-negative-number-constrained-types \
                  --use-unique-items-as-set \
                  --use-double-quotes
```

which generates:

```python
# generated by datamodel-codegen:
#   filename:  openapi-example.json
#   timestamp: 2025-06-17T07:45:05+00:00

from __future__ import annotations

from pydantic import BaseModel, Field, RootModel


class Sequence(RootModel[int]):
    root: int = Field(..., ge=0, title="Sequence")


class Record(BaseModel):
    uuid: str = Field(..., title="Uuid")
    sequence: Sequence | None = Field(0, title="Sequence")
```

**Expected behavior**
I expected something like

```python
# generated by datamodel-codegen:
#   filename:  openapi-example.json
#   timestamp: 2025-06-17T07:45:05+00:00

from __future__ import annotations

from pydantic import BaseModel, Field, NonNegativeInt


class Record(BaseModel):
    uuid: str = Field(..., title="Uuid")
    sequence: NonNegativeInt | None = Field(0, title="Sequence")
```

**Version:**
 - OS: macOS 15.5
 - Python version: 3.13.5
 - datamodel-code-generator version: 0.31.0


Discussion:

Patch:
diff --git a/src/datamodel_code_generator/parser/base.py b/src/datamodel_code_generator/parser/base.py
index f39387549..e06c97ac2 100644
--- a/src/datamodel_code_generator/parser/base.py
+++ b/src/datamodel_code_generator/parser/base.py
@@ -389,6 +389,7 @@ def __init__(  # noqa: PLR0913, PLR0915
             python_version=target_python_version,
             use_standard_collections=use_standard_collections,
             use_generic_container_types=use_generic_container_types,
+            use_non_positive_negative_number_constrained_types=use_non_positive_negative_number_constrained_types,
             strict_types=strict_types,
             use_union_operator=use_union_operator,
             use_pendulum=use_pendulum,


Test patch:
diff --git a/tests/parser/test_base.py b/tests/parser/test_base.py
index 33536f8d8..048f9b3ff 100644
--- a/tests/parser/test_base.py
+++ b/tests/parser/test_base.py
@@ -443,3 +443,10 @@ def escape_map() -> dict[str, str]:
 )
 def test_character_escaping(input_str: str, expected: str) -> None:
     assert input_str.translate(escape_characters) == expected
+
+
+@pytest.mark.parametrize("flag", [True, False])
+def test_use_non_positive_negative_number_constrained_types(flag: bool) -> None:
+    instance = C(source="", use_non_positive_negative_number_constrained_types=flag)
+
+    assert instance.data_type_manager.use_non_positive_negative_number_constrained_types == flag