webminal.org
webminal.org

Reputation: 47196

Is it possible to replace python import command?

I have a strange requirement. I can't install (or compile) python-fabric module on machine (at workplace). I was wondering Is it possible to copy the entire source code of fabric as single file and paste into a my file (something like "sqlite amalgamation") ? Does that work ?

-> Get the source of fabric module. -> Copy all files content of this module in to file (singlefile.py) -> Now import this singlefile.py on my myfile.py

Any thoughts? (Lets assume, the dependencies like paramiko,pycrypto already available on workplace).

Upvotes: 0

Views: 511

Answers (1)

abarnert
abarnert

Reputation: 365697

If the library has any C extensions, there is definitely no way to do this.

If not, it's technically possible, but practically not.

What you almost certainly want to do is use a virtualenv, or, if you can't do that, a user site-packages instead of a system site-packages, or some other way to get around the "can't install" problem, and just install it.


But if you're interested in the technical bits…

If Fabric were, say, a single .py file, that would be easy. But looking at the source, it's got a lot of files. And they're organized in a hierarchy, not just a flat directory. And there's a non-trivial setup.py, which usually means the way it ends up installed isn't the same way it is in the source tree.

So, to make this work, what you'd need to do is:

  • Do a "development" install into the source tree.
  • Take each file that gets installed, and wrap its source up in a giant string (first backslash-escaping any triple-quotes); followed by a function that compiles that string, execs it in a new globals dict, builds a types.ModuleType object out of that dict, and inserts it into the sys.modules dict; followed by a call to that function.
  • Concatenate the wrapped files in order of a reverse topological sort by which file imports which.
  • Embed the result at the top of your file.

The only really tricky, as opposed to tedious, bits here are:

  • Modules are first-class objects, with a type with a normal constructor and everything.
  • import spam always looks for sys.modules['spam'] before turning to the module loader, so if you pre-populate that, import will just accept it

In theory, that ought to work. Or something close to it; I may have missed a detail. In practice, I sincerely doubt you want to do that.

Upvotes: 1

Related Questions