rplevy/clojure-python

py-import against libraries with dots

Raynes opened this issue · 6 comments

I was playing around with clojure-python earlier and I'm not sure if this is a bug or just me lacking the ability to understand how this works, but I can't manage to import things with dots. My example is pygments. I have a directory structure like this:

- resources
   - pygments
      - lexers
        - __init__.py
        - .. and so on ...

I was able to do (py-import pygments), but I can't figure out how to import lexers. I tried (py-import pygments.lexers), but it failed with a vague exception and no message. It looks like you're creating a def from the lib name, so that wouldn't work anyway. Am I missing something?

Note this:

user> (py/py-import pygments lexers)
#'user/lexers
user> lexers
nil
user> (py/py-import pygments.lexers)
; Evaluation aborted.
user> lexers
nil
user> (py/py-import pygments lexers)
#'user/lexers
user> lexers
#<PyModuleDerived <module 'pygments.lexers' from '__pyclasspath__/pygments/lexers/__init__.py'>>

So the .exec call that does the actual import in py-import appears to be working. It's the rest of the code that fails.

Thanks, Anthony. I started working on this library a while ago, and left it in kind of a primitive state, making it work for a few limited use cases I had. Just the other day I picked it up and started looking into what might be needed to make it more generally usable. Thanks for helping, this is useful info, and I will look into it soon, probably today.

It looks like you're creating a def from the lib name, so that wouldn't work anyway. Am I missing something?

So are you suggesting that "pygments.lexers" should be accepted as another valid syntax for "pygments lexers"? This would be easy to add, and I think would be intuitive. By default the name it is def'd to would be, to use this example, lexers, in the namespace that is being imported into. However it would also be useful to have an :as usage. What do you think?

Well, no.

Notice that the first call to py-import doesn't work (I'm guessing that it probably shouldn't work?). The second call actually does half-work, in that the import call that you throw at the interpreter works. It is something else that fails there. If I call (py-import pygments.lexers) (which fails) first, then (py-import pygments lexers) actually does work. If I don't do the first call, which actually imports the thing, the second call doesn't work. I'm not sure the second call should work. It might be a 'just so happens' kind of thing.

Does this make sense? I really know nothing about Python, so it is very likely I'm either explaining this terribly or being stupid.

Ah I see what you mean, yup, I will fix that.

It needs to expand to this:

(.exec *interp* "import pygments.lexer") 
(-> *interp*
      .getLocals
      (.__getitem__ "pygments")
      (.__getattr__ "lexers")
      .__dict__)

I'm surprised this hasn't come up even in the limited use cases I have applied it to.

Also, I'm not sure how generally useful it is to automatically define something from python-land to a symbol of the same name, but that's another to-do item. I reserve the right to radically change the API since it's still on major version 0.

I think the rationale for that began with the idea of defining a function that calls the python-style function, which I still like, but I will change that to make it so that the user can choose what the function gets called.

Fixed in 4c552cb