Giter VIP home page Giter VIP logo

Comments (6)

Fingel avatar Fingel commented on September 25, 2024 1

Yes, this is on Master. When I get home I’ll try and get you a PR with a failing test case. Probably what I should have done first before blasting you with a wall of text.

from django-components.

Fingel avatar Fingel commented on September 25, 2024

OK, I think I've found the root cause. The class hash function here:

return hash(str(cls.__module__) + str(cls.__name__))

will return 2 different hashes if a class is imported using a different path.

Take for example, a Todo component with a .py file under components/todo/todo.py. When using the regular @component.register("todo") wrapper, the return value of cls.__module__ is todo.

However, if you import the module in another file, such as urls.py like this:

from components.todo.todo import TodoComponent

urlpatterns = [...]

the return value of cls.__module__ will be components.todo.todo.

This is an issue because the documentation at

# In a file called [project root]/components/urls.py
instructs you to place your components urls.py in the top level components folder, and import the example competent like so:

from calendar import Calendar

However this import will not work if the urls.py module is in a directory above the calendar folder. You need to write it like this:

from components.calendar.calendar import Calendar

or use a relative import. Either way, the hash function will not match because the module will not simply be calendar.

The only way to get this to work is if where you are importing the module (such as in a urls.py) is in the same module as where the component is defined. And indeed, in the sample/test project that the component views tests use:
https://github.com/EmilStenstrom/django-components/blob/91b4accfebf74f3f7a8cf2ecab03789a1979d578/sampleproject/components/urls.py

the urls.py file is in the same folder as greeting.py where the component is actually defined. So in this case, the hash function will match - but this does not match what the documentation says to do.

So I think there are two options:

  1. Update the documentation to say that the urls.py file needs to be in the same directory as the module that defines the component, or
  2. Make the hash function a bit more robust so that it stands up to imports from different paths.

EDIT:

I did some looking into this and I believe the root of this stems from the auto-detect and import that happens on init here:

def import_file(path):

No matter what I try, I cannot get the identity of the modules imported via autodetect to match the identity of classes imported later, such as in a urls.py. The full module path does not match. This makes it hard to make the class_hash method work.

As an example of this, I can make my project work by getting the component directly from the registry, thus circumventing the second attempt to register:

from django_components.component_registry import registry
urlpatterns = [path("components/todo", registry.get("todo").as_view(), name="todo")]

But this seems a little hacky.

Another option would be to make the class_hash method a little less resrictive:

    def class_hash(cls):
        return hash(cls.__name__)

This will still prevent someone from the (probably most common case) of trying to register a second component under the same component name, unless the class name they use also matches, but at some point you gotta just stop it 🤷‍♂️

from django-components.

EmilStenstrom avatar EmilStenstrom commented on September 25, 2024

Hi @Fingel! Before going further into troubleshooting this: Are you sure you're using the latest version of the code? I JUST released 0.34 to pypi. Which version are you using? Does things work when you run the latest release?

from django-components.

EmilStenstrom avatar EmilStenstrom commented on September 25, 2024

@dylanjcastillo Is on it.

It was me who suggested this (faulty) change in the PR review, going with Dylan's original suggestions would have avoided this! :)

from django-components.

dylanjcastillo avatar dylanjcastillo commented on September 25, 2024

@Fingel, I got the PR for this now. Please give it a try, and let us know if it works!

@EmilStenstrom, no worries. I should've included a specific test for this, and we have that now!

from django-components.

Fingel avatar Fingel commented on September 25, 2024

Yes! It works now. Nice work. The python import system is so funky.

from django-components.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.