When a module is large, reindenting the whole file (or files) may not be the best idea. You can make a private file to work around this:

+

When a module is large, reindenting the whole file (or files) may not be the best idea.

+

You can use a directory to achieve this:

<pre>

<pre>

−

# File: bundled/copy.py => Rename to _copy.py

+

# Directory: bundled/copy => Create this new directory

−

# File: bundled/copy.py => Fill this with something like the following

+

# File: bundled/copy.py => Move this to bundled/copy/_copy.py

+

+

# File: bundled/copy/__init__.py => Create this with the following code:

try:

try:

# Sometimes you can get away with import * here

# Sometimes you can get away with import * here

Line 91:

Line 94:

</pre>

</pre>

−

In some cases using a directory may be more appropriate:

+

{{admon/warning|Using a file does not work|You might be tempted to just make a single private file instead of a directory like this

<pre>

<pre>

−

# Directory: bundled/copy => Create this new directory

+

# File: bundled/copy.py => Rename to _copy.py

−

# File: bundled/copy.py => Move this to bundled/copy/_copy.py

+

# File: bundled/copy.py => Fill this with something like the following

−

+

−

# File: bundled/copy/__init__.py => Create this with the following code:

+

try:

try:

−

# Sometimes you can get away with import * here

+

# Copy exists in site-packages like this:

−

# Other times you have to list all the things you want to import explicitly

+

# /usr/lib/python2.6/site-packages/copy.py

−

# This example is being explicit

+

from copy import foo, bar, baz

−

from system.library.copy import foo, bar, baz

+

except ImportError:

except ImportError:

from _copy import foo, bar, baz

from _copy import foo, bar, baz

</pre>

</pre>

+

+

Unfortunately, this does not work because python-2.x does relative imports in preference to absolute imports. That means <code>bundled/copy.py</code> will end up importing itself when you do <code>from copy import foo, bar, baz</code>; not <code>/usr/lib/python2.6/site-packages/copy.py</code>.

+

}}

Latest revision as of 19:24, 5 July 2010

Here are some ways that you can unbundle python modules. Remember that upstreams usually feel they have a reason to bundle libraries so we need to offer them solutions that satisfy their concerns while also allowing us to unbundle for maintainance and security reasons.

When upstream considers the module an implementation detail and not something that software outside of their module should be importing we have more flexibility in how to fix things.

This example can be used when upstream just wants to make sure that a copy of a library is available (bundling is a "just in case this library is not installed"). In the rpm specfile we'll specify the Requires that pulls in the library and therefore we'll use the system library and not the bundled code.

Sometimes upstream will claim that they are also making sure that the library has a compatible API or is of a recent enough version to have a bugfix. When this occurs we should make sure that our packages have the bugfix or required version and do something like this:

The bundled copy will be used by people who just download upstream's code. In the Fedora package, since we've removed the bundled/_copy it will fail to load the bundle and load the system lib instead.

Delete all bundled code?Question for security team: Since the code is private, should we delete the bundled copies in our spec files in all these examples? The last one is the only one where it's strictly necessary in order for us not to use the code in our package.

A slight variant on the above can be used if upstream wants to do something like unittest the bundled code. By always defining foo (but as a private class) unittests can access the bundled code when necessary but normal code will use the system library:

When a module is large, reindenting the whole file (or files) may not be the best idea.
You can use a directory to achieve this:

# Directory: bundled/copy => Create this new directory
# File: bundled/copy.py => Move this to bundled/copy/_copy.py
# File: bundled/copy/__init__.py => Create this with the following code:
try:
# Sometimes you can get away with import * here
# Other times you have to list all the things you want to import explicitly
# This example is being explicit
from system.library.copy import foo, bar, baz
except ImportError:
from _copy import foo, bar, baz

Using a file does not workYou might be tempted to just make a single private file instead of a directory like this

Unfortunately, this does not work because python-2.x does relative imports in preference to absolute imports. That means bundled/copy.py will end up importing itself when you do from copy import foo, bar, baz; not /usr/lib/python2.6/site-packages/copy.py.