1#!/usr/bin/env python3 2# 3# Copyright 2017 - The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17import os 18import shutil 19import subprocess 20import sys 21from distutils import cmd 22from distutils import log 23 24import setuptools 25from setuptools.command.develop import develop 26from setuptools.command.install import install 27 28FRAMEWORK_DIR = 'acts_framework' 29LOCAL_FRAMEWORK_DIR = '../acts/framework' 30 31acts_tests_dir = os.path.abspath(os.path.dirname(__file__)) 32 33install_requires = [ 34 # Require an older version of setuptools that does not enforce PEP 440. 35 # This must be added first. 36 'setuptools<66.0.0', 37 'soundfile' 38] 39 40if sys.version_info < (3, 6): 41 # Python <= 3.5 uses bokeh up to 1.4.x 42 install_requires.append('bokeh<1.5') 43elif sys.version_info < (3, 7): 44 # Python 3.6 uses bokeh up to 2.3.x 45 install_requires.append('bokeh<2.4') 46elif sys.version_info < (3, 8): 47 # Python 3.7+ uses bokeh up to 2.4.x 48 install_requires.append('bokeh<2.5') 49else: 50 # Python 3.8+ is support by latest bokeh 51 install_requires.append('bokeh') 52 53def _setup_acts_framework(option, *args): 54 """Locates and runs setup.py for the ACTS framework. 55 56 Args: 57 option: the option to use with setup.py, e.g. install, develop 58 args: additional args for the command 59 """ 60 acts_framework_dir = os.path.join(acts_tests_dir, FRAMEWORK_DIR) 61 if not os.path.isdir(acts_framework_dir): 62 log.info('Directory "%s" not found. Attempting to locate ACTS ' 63 'framework through local repository.' % acts_framework_dir) 64 acts_framework_dir = os.path.join(acts_tests_dir, LOCAL_FRAMEWORK_DIR) 65 if not os.path.isdir(acts_framework_dir): 66 log.error('Cannot install ACTS framework. Framework dir "%s" not ' 67 'found.' % acts_framework_dir) 68 exit(1) 69 acts_setup_bin = os.path.join(acts_framework_dir, 'setup.py') 70 if not os.path.isfile(acts_setup_bin): 71 log.error('Cannot install ACTS framework. Setup script not found.') 72 exit(1) 73 command = [sys.executable, acts_setup_bin, option, *args] 74 subprocess.check_call(command, cwd=acts_framework_dir) 75 76 77class ActsContribInstall(install): 78 """Custom installation of the acts_contrib package. 79 80 Also installs the required ACTS framework via its own setup.py script. 81 82 The installation requires the ACTS framework to exist under the 83 "acts_framework" directory, at the same level of this setup script. 84 Otherwise, it will attempt to locate the ACTS framework from the local 85 repository. 86 """ 87 def do_egg_install(self): 88 # Ref. https://stackoverflow.com/a/20196065 89 _setup_acts_framework('install') 90 install.do_egg_install(self) 91 92 93class ActsContribDevelop(develop): 94 """Custom installation of the acts_contrib package (in develop mode). 95 96 See ActsContribInstall for more details. 97 """ 98 99 def run(self): 100 super().run() 101 if self.uninstall: 102 _setup_acts_framework('develop', '-u') 103 else: 104 _setup_acts_framework('develop') 105 106 107class ActsContribUninstall(cmd.Command): 108 """acts_contrib uninstaller. 109 110 Uninstalls acts_contrib from the current version of python. This will 111 attempt to import acts_contrib from any of the python egg locations. If it 112 finds an import it will use the modules file location to delete it. This is 113 repeated until acts_contrib can no longer be imported and thus is 114 uninstalled. 115 """ 116 117 description = 'Uninstall acts_contrib from the local machine.' 118 user_options = [] 119 120 def initialize_options(self): 121 pass 122 123 def finalize_options(self): 124 pass 125 126 def uninstall_acts_contrib_module(self, acts_contrib_module): 127 """Uninstalls acts_contrib from a module. 128 129 Args: 130 acts_contrib_module: The acts_contrib module to uninstall. 131 """ 132 for acts_contrib_install_dir in acts_contrib_module.__path__: 133 self.announce( 134 'Deleting acts_contrib from: %s' % acts_contrib_install_dir, 135 log.INFO) 136 shutil.rmtree(acts_contrib_install_dir) 137 138 def run(self): 139 """Entry point for the uninstaller.""" 140 # Remove the working directory from the python path. This ensures that 141 # Source code is not accidentally targeted. 142 our_dir = os.path.abspath(os.path.dirname(__file__)) 143 if our_dir in sys.path: 144 sys.path.remove(our_dir) 145 146 if os.getcwd() in sys.path: 147 sys.path.remove(os.getcwd()) 148 149 try: 150 import acts_contrib as acts_contrib_module 151 except ImportError: 152 self.announce( 153 'acts_contrib is not installed, nothing to uninstall.', 154 level=log.ERROR) 155 return 156 157 while acts_contrib_module: 158 self.uninstall_acts_contrib_module(acts_contrib_module) 159 try: 160 del sys.modules['acts_contrib'] 161 import acts_contrib as acts_contrib_module 162 except ImportError: 163 acts_contrib_module = None 164 165 self.announce('Finished uninstalling acts_contrib.') 166 167 # Uninstall the ACTS framework 168 _setup_acts_framework('uninstall') 169 170 171def main(): 172 os.chdir(acts_tests_dir) 173 packages = setuptools.find_packages(include=('acts_contrib*', )) 174 setuptools.setup(name='acts_contrib', 175 version='0.9', 176 description='Android Comms Test Suite', 177 license='Apache2.0', 178 packages=packages, 179 include_package_data=True, 180 install_requires=install_requires, 181 cmdclass={ 182 'install': ActsContribInstall, 183 'develop': ActsContribDevelop, 184 'uninstall': ActsContribUninstall 185 }, 186 url="http://www.android.com/") 187 188 189if __name__ == '__main__': 190 main() 191