django-components icon indicating copy to clipboard operation
django-components copied to clipboard

"django_components.component" does not explicitly export attribute "register"

Open thacoon opened this issue 1 year ago • 6 comments

I have a component like this

from typing import Dict, Any

from django_components import component

from server.example.models import Example


@component.register('example')
class ExampleComponent(component.Component):
    template_name = 'example/template.html'

    def get_context_data(self, instance: Example) -> Dict[str, Any]:
        return {
            'instance': instance,
        }

When running mypy I get the following error: error: Module "django_components.component" does not explicitly export attribute "register" [attr-defined]

thacoon avatar Apr 29 '24 14:04 thacoon

@thacoon How would we fix this, and are you open to writing a PR?

EmilStenstrom avatar Apr 29 '24 15:04 EmilStenstrom

Looking at this thread, I guess a temporary workaround could be to either:

  • Use
    rom django_components.component_registry import registry
    
  • Set in mypy.ini
    mplicit_reexport = True
    

What would be a proper fix? @thacoon can you share your mypy config?

JuroOravec avatar Apr 29 '24 16:04 JuroOravec

@JuroOravec my latest configuration is:

[mypy]
# Mypy configuration:
# https://mypy.readthedocs.io/en/latest/config_file.html
enable_error_code =
    truthy-bool,
    truthy-iterable,
    redundant-expr,
    unused-awaitable,
    ignore-without-code,
    possibly-undefined,
    redundant-self,

explicit_package_bases = true
ignore_missing_imports = true
strict = true
warn_unreachable = true

plugins =
    mypy_django_plugin.main

[mypy-server.apps.*.migrations.*]
# Django migrations should not produce any errors:
ignore_errors = true

[mypy.plugins.django-stubs]
# Docs: https://github.com/typeddjango/django-stubs
django_settings_module = config.settings
strict_settings = false

thacoon avatar May 01 '24 19:05 thacoon

I think the problem this mypy error is trying to point us at, is that we rely on the component module importing register as an API, but it's all implicit. So if we would refactor the module, and accidentally remove that import, we wouldn't notice that the API broke.

A simple way to explicitly define the public API is specifying all, and list all the symbols we export. Isn't that the simplest solution here?

EmilStenstrom avatar May 01 '24 20:05 EmilStenstrom

@EmilStenstrom So we want to define __all__ inside ~src/__init__.py~ src/component.py, is that correct?

JuroOravec avatar May 02 '24 05:05 JuroOravec

@thacoon I wasn't able to get the same error in my project, but it might be because there I'm on django_components 0.66 and mypy 1.7.0. What versions are you on?

Could you possibly test the solution below to check if it solves the issue? In your python packages folder, navigate to django_components/components.py, and on line 22 or 23, change

from django_components.component_registry import AlreadyRegistered, ComponentRegistry, NotRegistered, register  # NOQA

to

from django_components.component_registry import (
    AlreadyRegistered as AlreadyRegistered,
    ComponentRegistry as ComponentRegistry,
    NotRegistered as NotRegistered,
    register as register,
)

And then run mypy.

Aliasing at import should make mypy happy

JuroOravec avatar May 02 '24 09:05 JuroOravec

@thacoon I wasn't able to get the same error in my project, but it might be because there I'm on django_components 0.66 and mypy 1.7.0. What versions are you on?

Could you possibly test the solution below to check if it solves the issue? In your python packages folder, navigate to django_components/components.py, and on line 22 or 23, change

from django_components.component_registry import AlreadyRegistered, ComponentRegistry, NotRegistered, register  # NOQA

to

from django_components.component_registry import (
    AlreadyRegistered as AlreadyRegistered,
    ComponentRegistry as ComponentRegistry,
    NotRegistered as NotRegistered,
    register as register,
)

And then run mypy.

Aliasing at import should make mypy happy

I can confirm that this works with:

  • mypy==1.7.1
  • django_components==0.74

mikucz avatar May 12 '24 18:05 mikucz

@mikucz Excellent! Mind writing up a PR as well? Should be a good first contribution, don't you think? :)

EmilStenstrom avatar May 12 '24 18:05 EmilStenstrom

@mikucz Excellent! Mind writing up a PR as well? Should be a good first contribution, don't you think? :)

@EmilStenstrom PR as requested: https://github.com/EmilStenstrom/django-components/pull/499 :)

mikucz avatar May 19 '24 07:05 mikucz

@mikucz Thanks again for the contribution! This has now been release as part of https://github.com/EmilStenstrom/django-components/releases/tag/0.75

JuroOravec avatar May 19 '24 08:05 JuroOravec