views:

28

answers:

1

I have a python package called zypp. It is generated via swig and the rpm package (called python-zypp) puts it in:

rpm -ql python-zypp
/usr/lib64/python2.6/site-packages/_zypp.so
/usr/lib64/python2.6/site-packages/zypp.py

Now, I have a different project which provides an additional sets of APIs. Pure python. Plus some scripts.

The layout is:

bin/script1
python
python/zypp
python/zypp/plugins.py
python/zypp/__init__.py

plugins.py contains a Plugin class. I intended to put this in an rpm, and put it into

/usr/lib64/python2.6/site-packages/zypp/plugins.py

script1 uses this Plugin class. But as I test it running from git, I would like it to find the module from git too if it is not installed. So it has something like:

sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '../python'))
from zypp.plugins import Plugin

However, it seems that if python-zypp is installed on /usr/lib64/python2.6/site-packages/zypp.py, then script1 won't find the plugins submodule anymore. If I uninstall python-zypp, it does.

So my question is if it is possible to extend a module by adding submodules, being the submodules being located in a different load path. Or will they always clash?

An analogy would be, I have a module foo. And I provide foo.extras in a different load path (which may use foo indeed). The script won't find foo.extras if foo is found first in the system load path. If I only use the custom load path, the script may not find foo module if foo.extras uses it.

I have more experience with ruby, but in ruby I could have installed:

/usr/lib64/ruby/gems/1.8/gems/foo-1.0/lib/foo/*

And I could have in my script:

bin/script
lib/foo/extras/*

I could do in script:

$: << File.join(File.dirname(__FILE__), "../lib"

and then my script could

require foo
require foo/extras

No mater if foo/extras is installed on the system or in the custom load path. They don't clash.

The other way around, I found out that with PYTHONPATH the local zypp.plugins is found first. But then the installed zypp module is not found:

import zypp # works, but seems to import the local one
from zypp.plugins import Plugin # works, PYTHONPATH finds it first

repoinfo = zypp.RepoInfo() # does not work
+1  A: 

If I understand your question correctly, you want to use the development version of that module instead of the installed module. Therefore, you can use

  1. PYTHONPATH

    From the Module Search Path documentation:

    When a module named spam is imported, the interpreter searches for a file named spam.py in the current directory, and then in the list of directories specified by the environment variable PYTHONPATH. This has the same syntax as the shell variable PATH, that is, a list of directory names. When PYTHONPATH is not set, or when the file is not found there, the search continues in an installation-dependent default path; on Unix, this is usually .:/usr/local/lib/python.

    So, if the GIT tree of the module directory was "/home/username/some/path", you would change the PYTHONPATH to "/home/username/some/path". Or if the PYTHONPATH variable is already in use, you would append ":/home/username/some/path" to it (note the colon separator). In order to make this permanent, add the line "PYTHONPATH=value" to the file "/etc/environment".

  2. sys.path.insert

    If you have a start script for your program, you could override the module search path using sys.path.insert(0, "somepath"). This is similar to the sys.path.append call you described but inserts the path into the beginning of the list.

AndiDog
That is only one part of the problem. If you read carefully you will see that the installed version of the module and the development version are not the same. The later one is just shares the top package name (submodule).
duncan
@duncan: Why is "zypp.py" installed directly in `/usr/lib64/python2.6/site-packages`? This should not be the case if your package contains more than one submodule. The layout should be `/usr/lib64/python2.6/site-packages/zypp/X` where X is "__init__.py" and probably other files (like the plugin).
AndiDog
Because zypp.py has the main library classes, is generated by swig. While zypp.plugins is a module adding some utility classes. Can a module be a package at the same time?
duncan
@duncan: As a module is a single file, you can't have file-based submodules in it (as if it was a package). Furthermore, you can only override the module search path but IMO it's not possible to load the package from directory "A" and a submodule from "B". I would recommend you build both the zypp module *and* the submodule in your development directory. As you have .so files, you need to copy them to the module directory after building. In that case, you must override the search path with the dev module path, effectively making the `/usr/lib64/...` path unused.
AndiDog