-
Notifications
You must be signed in to change notification settings - Fork 43
Python Support Copying application packages to a bundle
Given a user-supplied function to an operation, the Python API finds the function's module by using the __module__
attribute. After determining the function's module, the following examples outline the steps used to determine what to copy into the Streams application bundle.
Regular packages contain __init__.py
. The top-level package can contain only one path.
In this example, a.b.my_module
is the function's module. It's top-level package is a
.
Given the following structure:
/tmp/ <== In `sys.path`
a/ <== package `a`
__init__.py
b/ <== subpackage `b`
__init__.py
my_module.py <== contains user-supplied function "my_func"
a) Start a new python3 command-line session in /home/<user>
b) Importing a.b.my_module
fails since /tmp
is not in sys.path
>>> import a.b.my_module
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named 'a'
c) Append to sys.path
and try again
>>> import sys
>>> sys.path.append('/tmp')
>>> import a.b.my_module
>>> a.b.my_module
<module 'a.b.my_module' from '/tmp/a/b/my_module.py'>
d) Using the module's __name__
attribute, we know that the module belongs to a package because it contains a period.
>>> a.b.my_module.__name__
'a.b.my_module'
e) We need to determine the top-level directory of the package. We look at the __name__
string before the first period, which is a
. This is the name of the package whose directory we need to copy.
>>> a.b.my_module.__name__.split('.')[0]
'a'
f) We need the path of the package so we can copy it to <applicationDirectory>/opt/python/packages
in the bundle. We extract the information from the module's __path__
attribute.
>>> sys.modules['a'].__path__
['/tmp/a']
g) Result: Copy entire directory /tmp/a
to <applicationDirectory>/opt/python/packages
. This results in <applicationDirectory>/opt/python/packages/a
.
Namespace packages do not contain __init__.py
. Also, the top-level package can have multiple paths. For example,
Given the following structure:
test_common_namespace/
package1/ <== In `sys.path`
common_namespace/
module1.py
package2/ <== In `sys.path`
common_namespace/
module2.py
a) Start a Python command-line session in the same directory as test_common_namespace
. Add package1
and package2
to sys.path
.
>>> import sys
>>> sys.path.extend(['test_common_namespace/package1', 'test_common_namespace/package2'])
b) We can import both module1.py and module2.py under a common namespace.
>>> import common_namespace.module1
>>> import common_namespace.module2
c) Examine the names of the modules. The name of the top-level package for both is "common_namespace".
>>> common_namespace.module1.__name__
'common_namespace.module1'
>>> common_namespace.module2.__name__
'common_namespace.module2'
d) Even though the top-level package name is the same, we can see that they are two different locations by looking at the __path__
.
>>> sys.modules['common_namespace'].__path__
_NamespacePath(['test_common_namespace/package1/common_namespace', 'test_common_namespace/package2/common_namespace'])
e) Result: Copy both test_common_namespace/package1/common_namespace
and test_common_namespace/package2/common_namespace
to <applicationDirectory>/opt/python/packages
. This results in:
<applicationDirectory>/opt/python/packages/common_namespace/modulep1.py
<applicationDirectory>/opt/python/packages/common_namespace/modulep2.py