goFrendiAsgard
goFrendiAsgard

Reputation: 4084

Is there any way to make pydev (or whatever Python IDE) understand module imported by using __import__ or exec

Introduction

Pydev is a great eclipse plugin that let us write python code easily.

It can even give autocompletion suggestion when I do this:

from package.module import Random_Class
x = Random_Class()
x.    # the autocompletion will be popped up, 
      # showing every method & attribute inside Random_Class

That is great !!!

The Problem (And My Question)

However, when I don't use explicit import, and use __import__ for example, I can't have the same autocompletion effect.

import_location = ".".join(('package', 'module'))
__import__(import_location, globals(), locals(), ['*'])
My_Class = getattr(sys.modules[import_location], 'Random_Class')
x = My_Class()
x.    # I expect autocompletion, but nothing happened

Question: is there any way (in pydev or any IDE) to make the second one also show autocompletion?

Why do I need to do this?

Well, I make a simple MVC framework, and I want to provide something like load_model, load_controller, and load_view which is still work with autocompletion (or at least possible to work)

So, instead of leave users do this (although I don't forbid them to do so):

from applications.the_application.models.the_model import The_Model
x = The_Model()
x.    # autocompletion works

I want to let users do this:

x = load_model('the_application', 'the_model')()
x.    # autocompletion still works

The "applications" part is actually configurable by another script, and I don't want users to change all of their importing model/controller part everytime they change the configuration. Plus, I think load_model, load_controller, and load_view make MVC pattern shown more obvious.

Unexpected Answer

  1. I know some tricks such as doing this (as what people do with web2py):

    import_location = ".".join(('package', 'module'))
    __import__(import_location, globals(), locals(), ['*'])
    My_Class = getattr(sys.modules[import_location], 'Random_Class')
    x = My_Class()
    if 0:
        from package.module import Random_Class
        x = Random_Class()
    x.    # Now autocompletion is going to work
    

    and I don't expect to do this, since it will only add unnecessary extra work.

  2. I don't expect any don't try to be clever comments. I have enough of them
  3. I don't expect dynamic import is evil comments. I'm not a purist.
  4. I don't expect any just use django, or pylons, or whatever comments. Such as comments even unrelated to my question.

Upvotes: 1

Views: 153

Answers (2)

goFrendiAsgard
goFrendiAsgard

Reputation: 4084

Not really an answer to my own question. However, I can change the approach. So, instead of provide "load_model()", I can use relative import. Something like this:

from ..models.my_model import Model_Class as Great_Model
m = Great_Model()

Upvotes: 1

mhlester
mhlester

Reputation: 23251

I have done this before. This may be slightly different from your intended method, so let me know if it doesn't apply.

I dynamically import different modules that all subclass a master class, using similar code to your example. Because the subclassing module already imports the master, I don't need to import it in the main module.

To get highlighting, the solution was to import the master class into the main module first, even though it wasn't used directly. In my case it was a good fallback if the particular subclass didn't exist, but that's an implementation detail.

This only works if your classes all inherit from one parent.

Upvotes: 2

Related Questions