datamodel-code-generator icon indicating copy to clipboard operation
datamodel-code-generator copied to clipboard

Enum defaults haves have broken import path prefix when using `dataclasses.dataclass`

Open negz opened this issue 1 year ago • 0 comments

Describe the bug

When I use --output-model-type=dataclasses.dataclass, datamodel-codegen generates enums with invalid defaults. The defaults are invalid because they refer to enums defined in the same package by their full import path.

To Reproduce

Example schema:

openapi.json

The above file was produced by running:

curl http://localhost:8001/openapi/v3/apis/s3.aws.upbound.io/v1beta2>openapi.json

Used commandline:

datamodel-codegen \
  --url http://localhost:8001/openapi/v3/apis/s3.aws.upbound.io/v1beta2 \
  --target-python-version=3.12 \
  --output generated \
  --output-model-type=dataclasses.dataclass \
  --use-field-description

Expected behavior I expect valid code to be generated, but it seems that the default values of enum fields are including the full import prefix, even though the types are defined in the same package.

class Resolution(Enum):
    Required = 'Required'
    Optional = 'Optional'


class Resolve(Enum):
    Always = 'Always'
    IfNotPresent = 'IfNotPresent'


@dataclass
class Policy:
    resolution: Optional[Resolution] = io.upbound.aws.s3.v1beta2.Resolution.Required
    """
    Resolution specifies whether resolution of this reference is required.
    The default is 'Required', which means the reconcile will fail if the
    reference cannot be resolved. 'Optional' means this reference will be
    a no-op if it cannot be resolved.
    """
    resolve: Optional[Resolve] = None
    """
    Resolve specifies when this reference should be resolved. The default
    is 'IfNotPresent', which will attempt to resolve the reference only when
    the corresponding field is not present. Use 'Always' to resolve the
    reference on every reconcile.
    """

Here both the Resolution and Policy classes are part of the the io.upbound.aws.s3.v1beta2 package, defined in the same file. Note that the default for the resolution field is io.upbound.aws.s3.v1beta2.Resolution.Required. If I edit it to remove the io.upbound.aws.s3.v1beta2. prefix, the code works. If I try to run the code as generated I get this error:

$ ./.fn/bin/python composition.py
Traceback (most recent call last):
  File "/home/negz/experiment/python-composition/composition.py", line 7, in <module>
    from generated.io.upbound.aws.s3 import v1beta2
  File "/home/negz/experiment/python-composition/generated/io/upbound/aws/s3/v1beta2.py", line 76, in <module>
    class Policy:
  File "/home/negz/experiment/python-composition/generated/io/upbound/aws/s3/v1beta2.py", line 77, in Policy
    resolution: Optional[Resolution] = io.upbound.aws.s3.v1beta2.Resolution.Required
                                       ^^
NameError: name 'io' is not defined. Did you mean: 'id'? Or did you forget to import 'io'?

Version:

  • OS: Linux mael 6.10.10 #1-NixOS SMP Thu Sep 12 09:13:13 UTC 2024 aarch64 GNU/Linux
  • Python version: Python 3.12.5
  • datamodel-code-generator version: [e.g. 22] 0.26.0

Additional context Add any other context about the problem here.

This issue only occurs for me with --output-model-type=dataclasses.dataclass. I have a slight preference for data classes to avoid the dependency on Pydantic.

negz avatar Sep 27 '24 00:09 negz