#!/usr/bin/env python3 # # Copyright 2017 - The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from distutils import cmd from distutils import log import subprocess import os import shutil import setuptools from setuptools.command import test import sys install_requires = [ # Require an older version of setuptools that does not enforce PEP 440. # This must be added first. 'setuptools<66.0.0', # Future needs to have a newer version that contains urllib. 'future>=0.16.0', 'mobly==1.12.0', # Latest version of mock (4.0.0b) causes a number of compatibility issues with ACTS unit tests # b/148695846, b/148814743 'mock==3.0.5', 'Monsoon', 'paramiko[ed25519]', 'pylibftdi', 'pyserial', 'pyyaml>=5.1', 'requests', 'retry', 'scapy', 'scp', 'usbinfo', 'zeroconf' ] versioned_deps = { 'backoff': 'backoff', 'numpy': 'numpy', 'scipy': 'scipy', 'protobuf': 'protobuf==4.21.5', 'grpcio': 'grpcio', } # numpy and scipy version matrix per: # https://docs.scipy.org/doc/scipy/dev/toolchain.html if sys.version_info < (3, 11): versioned_deps['numpy'] = 'numpy<2.0.0b1' if sys.version_info < (3, 9): versioned_deps['scipy'] = 'scipy<1.11' if sys.version_info < (3, 8): versioned_deps['numpy'] = 'numpy<1.22' versioned_deps['scipy'] = 'scipy<1.8' if sys.version_info < (3, 7): versioned_deps['backoff'] = 'backoff<2.0' versioned_deps['numpy'] = 'numpy<1.20' versioned_deps['scipy'] = 'scipy<1.6' versioned_deps['protobuf'] = 'protobuf==3.20.1' versioned_deps['grpcio'] = 'grpcio==1.48.2' versioned_deps['typing_extensions'] = 'typing_extensions==4.1.1' versioned_deps['cryptography'] = 'cryptography<41.0' if (sys.version_info.major, sys.version_info.minor) == (3, 6): versioned_deps['dataclasses'] = 'dataclasses==0.8' if sys.version_info < (3, 6): versioned_deps['numpy'] = 'numpy<1.19' versioned_deps['scipy'] = 'scipy<1.5' versioned_deps['typing_extensions'] = 'typing_extensions<4.0.0' install_requires += list(versioned_deps.values()) if sys.version_info < (3, ): install_requires.append('enum34') install_requires.append('statistics') # "futures" is needed for py2 compatibility and it only works in 2.7 install_requires.append('futures') install_requires.append('py2-ipaddress') install_requires.append('subprocess32') DEV_PACKAGES = ['shiv'] framework_dir = os.path.dirname(os.path.realpath(__file__)) class PyTest(test.test): """Class used to execute unit tests using PyTest. This allows us to execute unit tests without having to install the package. """ def finalize_options(self): test.test.finalize_options(self) self.test_args = ['-x', "tests"] self.test_suite = True def run_tests(self): test_path = os.path.join(framework_dir, '../tests/meta/ActsUnitTest.py') result = subprocess.Popen('python3 %s' % test_path, stdout=sys.stdout, stderr=sys.stderr, shell=True) result.communicate() sys.exit(result.returncode) class ActsUninstall(cmd.Command): """Acts uninstaller. Uninstalls acts from the current version of python. This will attempt to import acts from any of the python egg locations. If it finds an import it will use the modules file location to delete it. This is repeated until acts can no longer be imported and thus is uninstalled. """ description = 'Uninstall acts from the local machine.' user_options = [] def initialize_options(self): pass def finalize_options(self): pass def uninstall_acts_module(self, acts_module): """Uninstalls acts from a module. Args: acts_module: The acts module to uninstall. """ for acts_install_dir in acts_module.__path__: self.announce('Deleting acts from: %s' % acts_install_dir, log.INFO) shutil.rmtree(acts_install_dir) def run(self): """Entry point for the uninstaller.""" # Remove the working directory from the python path. This ensures that # Source code is not accidentally targeted. if framework_dir in sys.path: sys.path.remove(framework_dir) if os.getcwd() in sys.path: sys.path.remove(os.getcwd()) try: import acts as acts_module except ImportError: self.announce('Acts is not installed, nothing to uninstall.', level=log.ERROR) return while acts_module: self.uninstall_acts_module(acts_module) try: del sys.modules['acts'] import acts as acts_module except ImportError: acts_module = None self.announce('Finished uninstalling acts.') def main(): scripts = [ os.path.join('acts', 'bin', 'act.py'), os.path.join('acts', 'bin', 'monsoon.py') ] # cd to framework directory so the correct package namespace is found os.chdir(framework_dir) setuptools.setup(name='acts', version='0.9', description='Android Comms Test Suite', license='Apache2.0', packages=setuptools.find_packages(), include_package_data=True, tests_require=['pytest'], install_requires=install_requires, extras_require={ 'dev': DEV_PACKAGES, 'digital_loggers_pdu': ['dlipower'], }, scripts=scripts, cmdclass={ 'test': PyTest, 'uninstall': ActsUninstall }, url="http://www.android.com/") if {'-u', '--uninstall', 'uninstall'}.intersection(sys.argv): installed_scripts = [ '/usr/local/bin/act.py', '/usr/local/bin/monsoon.py' ] for act_file in installed_scripts: if os.path.islink(act_file): os.unlink(act_file) elif os.path.exists(act_file): os.remove(act_file) if __name__ == '__main__': main()