views:

193

answers:

2

In some cases, there are various modules which each implement a common API (in my case, the old pure-python elementtree, cElementTree, lxml.etree, and the built-in xml.etree). I can write the module using ElementTree to try each of these options, and take the first one that exists according to my own preference order -- but I can't find any information on specifying that only one of these must be installed in setup.py. I want to write something that looks like this:

setup(
    ...,
    install_requires="""
        elementtree | cElementTree | lxml
    """,
    ...
)

Is this, or something like it, possible?

A: 

I don't think so, but, if you're using a reasonably recent Python, elementtree being part of the standard Python libraries, why do you worry it might be absent? (I do understand this would be a problem for other cases of several possible implementations of an API, I just wonder if you really need it for your specific use case).

Alex Martelli
This problem is actually occurring in an open-source third party module we're using, so I was looking for a solution to contribute as a patch, and wanted to avoid the appearance of publicly shaming the developers of the module. Our other code depends on lxml, and runs in Py26, so we have at least two other implementations available -- just not the one named `elementtree`.
dcrosta
A: 

You might want to try doing something like this in setup.py:

install_requires = ["elementree"]

try:
    import cElementTree
    install_requires = []
except ImportError:
    try:
        import lxml
        install_requires = []
    except ImportError:
        # etc for remaining equivalent modules

setup(
    install_requires = install_requires,
    # rest of setup parameters
)

This will basically install elementree package as dependency if none of the equivalent are installed.

Heikki Toivonen
Unfortunately, this won't work -- the code is deployed via RPM, with each third-party module (see my comment to Alex Martelli's post) built and installed in a separate RPM. By the time `pkg_resources` is checking the dependencies at startup, we are well past when `setup.py` is run (and in fact it is not even present on the system where the error is occurring).
dcrosta
This does not make sense to me. If you are deploying packages as RPMs, why would you ever run setup.py?
Heikki Toivonen
`setup.py` is run during the RPM build, and, among other things, creates the `.egg-info/requires.txt` which names "elementtree". I figure the right place to change this is in `setup.py` for the component with the dependency, as well as in the modules that try to import `elementtree`.
dcrosta