Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: AttributeError: type object 'datetime.datetime' has no attribute 'datetime' #370

Open
1 of 4 tasks
Tracked by #374
noamsto opened this issue Jan 27, 2025 · 5 comments
Open
1 of 4 tasks
Tracked by #374
Labels
bug Something isn't working

Comments

@noamsto
Copy link
Contributor

noamsto commented Jan 27, 2025

Description

Since this PR #341 we had to lock advanced_alchemy to version 28.0.0
We get the following error even when running litestar cli.

Logs

❯ litestar

 Usage: litestar [OPTIONS] COMMAND [ARGS]...

 Litestar CLI.

╭─ Options ────────────────────────────────────────────────────────────────────╮
│ --app          TEXT       Module path to a Litestar application (TEXT)       │
│ --app-dir      DIRECTORY  Look for APP in the specified directory, by adding │
│                           this to the PYTHONPATH. Defaults to the current    │
│                           working directory.                                 │
│                           (DIRECTORY)                                        │
│ --help     -h             Show this message and exit.                        │
╰──────────────────────────────────────────────────────────────────────────────╯
Traceback (most recent call last):
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/bin/litestar", line 8, in <module>
    sys.exit(run_cli())
             ^^^^^^^^^
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/litestar/__main__.py", line 6, in run_cli
    litestar_group()
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/rich_click/rich_command.py", line 367, in __call__
    return super().__call__(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/click/core.py", line 1161, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/rich_click/rich_command.py", line 151, in main
    with self.make_context(prog_name, args, **extra) as ctx:
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/litestar/cli/_utils.py", line 223, in make_context
    ctx = super().make_context(info_name, args, parent, **extra)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/rich_click/rich_command.py", line 260, in make_context
    return super().make_context(info_name, args, parent, **extra)  # type: ignore[return-value]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/click/core.py", line 949, in make_context
    self.parse_args(ctx, args)
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/click/core.py", line 1650, in parse_args
    echo(ctx.get_help(), color=ctx.color)
         ^^^^^^^^^^^^^^
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/click/core.py", line 711, in get_help
    return self.command.get_help(self)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/click/core.py", line 1334, in get_help
    self.format_help(ctx, formatter)
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/rich_click/rich_command.py", line 359, in format_help
    self.format_options(ctx, formatter)
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/rich_click/rich_command.py", line 296, in format_options
    self.format_commands(ctx, formatter)  # type: ignore[arg-type]
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/rich_click/rich_command.py", line 289, in format_commands
    get_rich_commands(self, ctx, formatter)
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/rich_click/rich_help_rendering.py", line 616, in get_rich_commands
    for command in obj.list_commands(ctx):
                   ^^^^^^^^^^^^^^^^^^^^^^
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/litestar/cli/_utils.py", line 228, in list_commands
    self._prepare(ctx)
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/litestar/cli/_utils.py", line 206, in _prepare
    env = ctx.obj = LitestarEnv.from_env(ctx.params.get("app_path"), ctx.params.get("app_dir"))
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/litestar/cli/_utils.py", line 114, in from_env
    loaded_app = _autodiscover_app(cwd)
                 ^^^^^^^^^^^^^^^^^^^^^^
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/litestar/cli/_utils.py", line 316, in _autodiscover_app
    module = importlib.import_module(import_path)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/765zc1gcbd6c3zsx0hjm8dwv4c20kph1-python3-3.12.8/lib/python3.12/importlib/__init__.py", line 90, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 999, in exec_module
  File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/app/__init__.py", line 109, in <module>
    app = Litestar(
          ^^^^^^^^^
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/litestar/app.py", line 491, in __init__
    self.register(route_handler)
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/litestar/app.py", line 692, in register
    route_handler.on_registration(self)
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/litestar/handlers/http_handlers/base.py", line 587, in on_registration
    super().on_registration(app)
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/litestar/handlers/base.py", line 544, in on_registration
    self.resolve_return_dto()
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/litestar/handlers/base.py", line 504, in resolve_return_dto
    return_dto.create_for_field_definition(
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/litestar/dto/base_dto.py", line 201, in create_for_field_definition
    backend_context[key] = backend_cls(  # type: ignore[literal-required]
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/litestar/dto/_codegen_backend.py", line 73, in __init__
    super().__init__(
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/litestar/dto/_backend.py", line 109, in __init__
    self.parsed_field_definitions = self.parse_model(
                                    ^^^^^^^^^^^^^^^^^
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/litestar/dto/_backend.py", line 141, in parse_model
    for field_definition in self.dto_factory.generate_field_definitions(model_type):
                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/advanced_alchemy/extensions/litestar/dto.py", line 299, in generate_field_definitions
    model_type_hints = cls.get_model_type_hints(model_type, namespace=namespace)
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/noams/Data/git/factify-dal-dev/factify-dal/.devenv/state/venv/lib/python3.12/site-packages/litestar/dto/base_dto.py", line 309, in get_model_type_hints
    for k, v in get_type_hints(model_type, localns=namespace, include_extras=True).items()  # pyright: ignore
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/70487hpbikbhjrlylcwg4xflkn52hjdd-devenv-profile/lib/python3.12/site-packages/typing_extensions.py", line 1230, in get_type_hints
    hint = typing.get_type_hints(
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/765zc1gcbd6c3zsx0hjm8dwv4c20kph1-python3-3.12.8/lib/python3.12/typing.py", line 2273, in get_type_hints
    value = _eval_type(value, base_globals, base_locals, base.__type_params__)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/765zc1gcbd6c3zsx0hjm8dwv4c20kph1-python3-3.12.8/lib/python3.12/typing.py", line 415, in _eval_type
    return t._evaluate(globalns, localns, type_params, recursive_guard=recursive_guard)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/765zc1gcbd6c3zsx0hjm8dwv4c20kph1-python3-3.12.8/lib/python3.12/typing.py", line 947, in _evaluate
    eval(self.__forward_code__, globalns, localns),
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<string>", line 1, in <module>
AttributeError: type object 'datetime.datetime' has no attribute 'datetime'

Package Version

Image

Platform

  • Linux
  • Mac
  • Windows
  • Other (Please specify in the description above)
@noamsto noamsto added the bug Something isn't working label Jan 27, 2025
@kevgliss
Copy link

Also, facing this issue. As a new user to the library, this one was pretty brutal as it wasn't clear if I was simply getting the typing wrong.

@Alc-Alc
Copy link
Collaborator

Alc-Alc commented Jan 29, 2025

@noamsto and @kevgliss I want to preface by mentioning I am not a typing pro. Some of you may know why this happens, but just so everyone stumbling upon this is on the same page, this happens because deep down the class datetime that you annotate your model with is getting mixed up with the module datetime.

As far as I am aware, there is not really an easy (or no?, happy to be corrected) fix here that will satisfy users who do from datetime import datetime and import datetime (and later do datetime.datetime). The library can only support either of this, not both.

With the current implementation, you can either

  • Move to the "long form" import (import datetime and then use datetime.datetime) or
  • Alias the import from datetime import datetime as dt and then do some_thing: Mapped[dt] (haven't tried this, would like to hear if it works)

@provinzkraut can probably give a better explanation 🙂

@provinzkraut
Copy link
Member

As far as I am aware, there is not really an easy (or no?, happy to be corrected) fix here that will satisfy users who do from datetime import datetime and import datetime (and later do datetime.datetime). The library can only support either of this, not both.

That's correct. There is, however, a way to, at least somewhat, nicely solve this: We need to never used stringised annotations in AA. That means all type hints that need resolving would be on the user, who has control over this (e.g. in Litestar with the signature_types or by simply not using stringised annotations themselves where they'll be inspected).

That is, unfortunately, the only way to fundamentally solve this issue (that is until Python 3.14 comes out and ruins it again for everyone but that's a whole other story 🙂).

@provinzkraut provinzkraut mentioned this issue Jan 30, 2025
5 tasks
@noamsto
Copy link
Contributor Author

noamsto commented Feb 4, 2025

@Alc-Alc
Thanks,
I changed my datetime imports and it's working.
It is indeed an unexpected and annoying issue..

@noamsto noamsto closed this as completed Feb 4, 2025
@noamsto
Copy link
Contributor Author

noamsto commented Feb 4, 2025

@Alc-Alc
Sorry I closed this issue by mistake. I see it's in the Roadmap so you might want to keep it open

@Alc-Alc Alc-Alc reopened this Feb 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants