1#!/usr/bin/env python3.4 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 17from distutils import cmd 18from distutils import log 19import os 20import shutil 21import setuptools 22from setuptools.command import test 23import sys 24 25install_requires = [ 26 # Future needs to have a newer version that contains urllib. 27 'future>=0.16.0', 28 # mock-1.0.1 is the last version compatible with setuptools <17.1, 29 # which is what comes with Ubuntu 14.04 LTS. 30 'mock<=1.0.1', 31 'numpy', 32 'pyserial', 33 'shellescape', 34 'protobuf', 35 'roman', 36 'scapy-python3', 37 'pylibftdi', 38 'xlsxwriter' 39] 40 41if sys.version_info < (3, ): 42 install_requires.append('enum34') 43 install_requires.append('statistics') 44 # "futures" is needed for py2 compatibility and it only works in 2.7 45 install_requires.append('futures') 46 install_requires.append('py2-ipaddress') 47 install_requires.append('subprocess32') 48 49 50class PyTest(test.test): 51 """Class used to execute unit tests using PyTest. This allows us to execute 52 unit tests without having to install the package. 53 """ 54 55 def finalize_options(self): 56 test.test.finalize_options(self) 57 self.test_args = ['-x', "tests"] 58 self.test_suite = True 59 60 def run_tests(self): 61 import pytest 62 errno = pytest.main(self.test_args) 63 sys.exit(errno) 64 65 66class ActsInstallDependencies(cmd.Command): 67 """Installs only required packages 68 69 Installs all required packages for acts to work. Rather than using the 70 normal install system which creates links with the python egg, pip is 71 used to install the packages. 72 """ 73 74 description = 'Install dependencies needed for acts to run on this machine.' 75 user_options = [] 76 77 def initialize_options(self): 78 pass 79 80 def finalize_options(self): 81 pass 82 83 def run(self): 84 import pip 85 pip.main(['install', '--upgrade', 'pip']) 86 required_packages = self.distribution.install_requires 87 88 for package in required_packages: 89 self.announce('Installing %s...' % package, log.INFO) 90 pip.main(['install', '-v', '--no-cache-dir', package]) 91 92 self.announce('Dependencies installed.') 93 94 95class ActsUninstall(cmd.Command): 96 """Acts uninstaller. 97 98 Uninstalls acts from the current version of python. This will attempt to 99 import acts from any of the python egg locations. If it finds an import 100 it will use the modules file location to delete it. This is repeated until 101 acts can no longer be imported and thus is uninstalled. 102 """ 103 104 description = 'Uninstall acts from the local machine.' 105 user_options = [] 106 107 def initialize_options(self): 108 pass 109 110 def finalize_options(self): 111 pass 112 113 def uninstall_acts_module(self, acts_module): 114 """Uninstalls acts from a module. 115 116 Args: 117 acts_module: The acts module to uninstall. 118 """ 119 for acts_install_dir in acts_module.__path__: 120 self.announce('Deleting acts from: %s' % acts_install_dir, 121 log.INFO) 122 shutil.rmtree(acts_install_dir) 123 124 def run(self): 125 """Entry point for the uninstaller.""" 126 # Remove the working directory from the python path. This ensures that 127 # Source code is not accidentally targeted. 128 our_dir = os.path.abspath(os.path.dirname(__file__)) 129 if our_dir in sys.path: 130 sys.path.remove(our_dir) 131 132 if os.getcwd() in sys.path: 133 sys.path.remove(os.getcwd()) 134 135 try: 136 import acts as acts_module 137 except ImportError: 138 self.announce( 139 'Acts is not installed, nothing to uninstall.', 140 level=log.ERROR) 141 return 142 143 while acts_module: 144 self.uninstall_acts_module(acts_module) 145 try: 146 del sys.modules['acts'] 147 import acts as acts_module 148 except ImportError: 149 acts_module = None 150 151 self.announce('Finished uninstalling acts.') 152 153 154def main(): 155 setuptools.setup( 156 name='acts', 157 version='0.9', 158 description='Android Comms Test Suite', 159 license='Apache2.0', 160 packages=setuptools.find_packages(), 161 include_package_data=False, 162 tests_require=['pytest'], 163 install_requires=install_requires, 164 scripts=['acts/bin/act.py', 'acts/bin/monsoon.py'], 165 cmdclass={ 166 'test': PyTest, 167 'install_deps': ActsInstallDependencies, 168 'uninstall': ActsUninstall 169 }, 170 url="http://www.android.com/") 171 172 if {'-u', '--uninstall', 'uninstall'}.intersection(sys.argv): 173 act_path = '/usr/local/bin/act.py' 174 if os.path.islink(act_path): 175 os.unlink(act_path) 176 elif os.path.exists(act_path): 177 os.remove(act_path) 178 179 180if __name__ == '__main__': 181 main() 182