Skip to content

Commit

Permalink
Write/overwrite __init__.py for namespaces
Browse files Browse the repository at this point in the history
This appears to fix bazelbuild#14, but I haven't tested extensively to see if it
breaks anything else.
  • Loading branch information
drigz committed Nov 19, 2019
1 parent 9467740 commit 4e76eb6
Showing 1 changed file with 40 additions and 0 deletions.
40 changes: 40 additions & 0 deletions packaging/whl.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,17 @@
import re
import zipfile

# Putting this a package's __init__.py causes it to set __path__ so that it is
# possible to import modules and subpackages from other directories on sys.path.
INITPY_CONTENTS = '''
try:
import pkg_resources
pkg_resources.declare_namespace(__name__)
except ImportError:
import pkgutil
__path__ = pkgutil.extend_path(__path__, __name__)
'''


class Wheel(object):

Expand Down Expand Up @@ -109,6 +120,35 @@ def extras(self):
def expand(self, directory):
with zipfile.ZipFile(self.path(), 'r') as whl:
whl.extractall(directory)
names = set(whl.namelist())

# Workaround for https://github.com/bazelbuild/rules_python/issues/14
for initpy in self.get_init_paths(names):
with open(os.path.join(directory, initpy), 'w') as f:
f.write(INITPY_CONTENTS)

def get_init_paths(self, names):
# Overwrite __init__.py in these directories.
# (required as googleapis-common-protos has an empty __init__.py, which
# blocks google.api.core from google-cloud-core)
NAMESPACES = ["google/api"]

# Find package directories without __init__.py, or where the __init__.py
# must be overwritten to create a working namespace. This is based on
# Bazel's PythonUtils.getInitPyFiles().
init_paths = set()
for n in names:
if os.path.splitext(n)[1] not in ['.so', '.py', '.pyc']:
continue
while os.path.sep in n:
n = os.path.dirname(n)
initpy = os.path.join(n, '__init__.py')
initpyc = os.path.join(n, '__init__.pyc')
if (initpy in names or initpyc in names) and n not in NAMESPACES:
continue
init_paths.add(initpy)

return init_paths

# _parse_metadata parses METADATA files according to https://www.python.org/dev/peps/pep-0314/
def _parse_metadata(self, content):
Expand Down

0 comments on commit 4e76eb6

Please sign in to comment.