|
| 1 | +#!/usr/bin/env python |
| 2 | + |
| 3 | +from Cython.Distutils import build_ext |
| 4 | +from distutils.errors import DistutilsExecError |
| 5 | +from glob import glob |
| 6 | +import os |
| 7 | +import setuptools |
| 8 | +from setuptools import find_packages, setup |
| 9 | +import shutil |
| 10 | +from subprocess import check_call |
| 11 | + |
| 12 | +# discover the path to this setup.py file |
| 13 | +thisScriptDir = os.path.dirname(os.path.realpath(__file__)) |
| 14 | + |
| 15 | +class ProtocCommand(setuptools.Command): |
| 16 | + user_options = [ |
| 17 | + ('protoc=', 'p', "(default: 'protoc') path to protoc compiler. The default value can be set via the PROTOC environment variable"), |
| 18 | + ('raises=', 'r', '(default: True) if true, raise error on protobuf compilation error'), |
| 19 | + ] |
| 20 | + |
| 21 | + def initialize_options(self): |
| 22 | + self.protoc = os.environ['PROTOC'] if 'PROTOC' in os.environ else 'protoc' |
| 23 | + self.raises = True |
| 24 | + |
| 25 | + def finalize_options(self): |
| 26 | + print(f'searching for protoc executable at: {self.protoc}...') |
| 27 | + self.protoc = shutil.which(self.protoc) |
| 28 | + if self.protoc is None: |
| 29 | + if self.raises: |
| 30 | + raise DistutilsExecError('Could not find protoc executable.') |
| 31 | + else: |
| 32 | + print('Could not find protoc executable. Skipping protobuf compilation.') |
| 33 | + else: |
| 34 | + print(f'Found. Using protoc at: {self.protoc}') |
| 35 | + |
| 36 | + def run(self): |
| 37 | + if self.protoc is None: |
| 38 | + # bail if self.raises is False and protoc isn't found |
| 39 | + return |
| 40 | + |
| 41 | + protoDir = os.path.join(thisScriptDir, 'npbuf', 'protobuf') |
| 42 | + protoOutDir = os.path.join(thisScriptDir, 'npbuf', 'protobuf_py') |
| 43 | + protoSrcs = glob(os.path.join(protoDir, '*.proto')) |
| 44 | + |
| 45 | + # clean up any existing compiled protobufs |
| 46 | + shutil.rmtree(protoOutDir, ignore_errors=True) |
| 47 | + # create a new module for the compiled protobufs, including an `__init__.py` |
| 48 | + os.mkdir(protoOutDir) |
| 49 | + with open(os.path.join(protoOutDir, '__init__.py'), 'w') as f: pass |
| 50 | + |
| 51 | + # compile protobuf files to .py python modules |
| 52 | + protoc_python_cmd = [ |
| 53 | + self.protoc, |
| 54 | + '--proto_path=%s' % protoDir, |
| 55 | + '--python_out=%s' % protoOutDir, |
| 56 | + ] |
| 57 | + protoc_python_cmd.extend(protoSrcs) |
| 58 | + |
| 59 | + check_call(protoc_python_cmd) |
| 60 | + |
| 61 | +class DevelopCommand(setuptools.command.develop.develop): |
| 62 | + def run(self): |
| 63 | + # pass options to the protoc command and run it |
| 64 | + protocCommand = self.distribution.get_command_obj('protoc') |
| 65 | + protocCommand.database = self.database |
| 66 | + self.run_command('protoc') |
| 67 | + |
| 68 | + # run the normal develop command |
| 69 | + super().run(self) |
| 70 | + |
| 71 | +setup( |
| 72 | + author = 'Max Klein', |
| 73 | + cmdclass = {'build_ext': build_ext, |
| 74 | + 'develop': DevelopCommand, |
| 75 | + 'protoc': ProtocCommand |
| 76 | + }, |
| 77 | + description = 'provides Python protobuf types that can be used to serialize/deserialize Numpy arrays', |
| 78 | + license = 'Apache License, Version 2.0', |
| 79 | + name = 'numpy-protobuf', |
| 80 | + packages = find_packages(where='.', exclude=('npbuf.protobuf')) |
| 81 | +) |
0 commit comments