views:

235

answers:

1

I'm writing a piece of reusable code to import where I need it, but it needs some info about what is importing it. I have a workaround that does what I want, but it's a bit ugly. Is there a better way?

Here is a simplified version of what I'm doing.

What I want: Import a method and use it, but look at f in mod2. It needs some info from the importing module.

mod1:

from mod2 import f
f(...)

mod2:

from things_i_want import parent_module, importing_module
def f(*args, **kwargs):
    from importing_module.parent_module import models
    # ... do some stuff with it, including populating v with a string

    v = 'some_string'
    m = getattr(importing_module, v, None)
    if callable(m)
        return m(*args, **kwargs)

My ugly workaround:

mod1:

from mod2 import f as _f
def f(*a, **k):return _f(__name__, globals(), *a, **k)
f(...)

mod2:

def f(module_name, globs, *args, **kwargs):
    # find parent modules path
    parent_module_path = module_name.split('.')[0:-1]
    # find models modules path
    models_path = parent_module_path + ['models',]
    # import it
    models = __import__('.'.join(models_path), {}, {}, [''])
    # ... do some stuff with it, including populating v with a string

    v = 'some_string'
    if v in globs:
        return globs[v](*args, **kwargs)
+4  A: 

That's a bad idea, because modules are cached.

So if another module, say, mod3.py, also imports mod2, it will get the same mod2 object of the first time. The module is not reimported.

Maybe you imported some other module that imported mod2 before importing mod2 yourself, then you're not the one importing mod2 anymore. Modules are imported only once.

So instead of trying to get who imported the module, you should use another, reusable approach. Perhaps using classes and passing the instance around?

nosklo
So my ugly workaround might not be so ugly?See comment above for context.
Jake
It is ugly because it tries to hide its intents. It's better to be explicit than implicit. Why don't you pass a class to f() that contains the delete/insert/update/select methods inside it? Also, Django uses strings 'project.app.myfun' everywhere to refer to functions, so there is some function somewhere in django that takes a string and returns the actual function object it is refering. Why not use that?
nosklo
Good point. There is a function (get_app)which takes a string like "project.app" and returns it, there may be one that goes deeper. Or I could use __import__?I'd rather not wrap them in a class because I want them to remain the the view file so that other URLs can point to them, and so that I'm changing Django as little as possible.
Jake