17db96d56Sopenharmony_ci"""distutils.command.build_py 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_ciImplements the Distutils 'build_py' command.""" 47db96d56Sopenharmony_ci 57db96d56Sopenharmony_ciimport os 67db96d56Sopenharmony_ciimport importlib.util 77db96d56Sopenharmony_ciimport sys 87db96d56Sopenharmony_ciimport glob 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_cifrom distutils.core import Command 117db96d56Sopenharmony_cifrom distutils.errors import * 127db96d56Sopenharmony_cifrom distutils.util import convert_path, Mixin2to3 137db96d56Sopenharmony_cifrom distutils import log 147db96d56Sopenharmony_ci 157db96d56Sopenharmony_ciclass build_py (Command): 167db96d56Sopenharmony_ci 177db96d56Sopenharmony_ci description = "\"build\" pure Python modules (copy to build directory)" 187db96d56Sopenharmony_ci 197db96d56Sopenharmony_ci user_options = [ 207db96d56Sopenharmony_ci ('build-lib=', 'd', "directory to \"build\" (copy) to"), 217db96d56Sopenharmony_ci ('compile', 'c', "compile .py to .pyc"), 227db96d56Sopenharmony_ci ('no-compile', None, "don't compile .py files [default]"), 237db96d56Sopenharmony_ci ('optimize=', 'O', 247db96d56Sopenharmony_ci "also compile with optimization: -O1 for \"python -O\", " 257db96d56Sopenharmony_ci "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"), 267db96d56Sopenharmony_ci ('force', 'f', "forcibly build everything (ignore file timestamps)"), 277db96d56Sopenharmony_ci ] 287db96d56Sopenharmony_ci 297db96d56Sopenharmony_ci boolean_options = ['compile', 'force'] 307db96d56Sopenharmony_ci negative_opt = {'no-compile' : 'compile'} 317db96d56Sopenharmony_ci 327db96d56Sopenharmony_ci def initialize_options(self): 337db96d56Sopenharmony_ci self.build_lib = None 347db96d56Sopenharmony_ci self.py_modules = None 357db96d56Sopenharmony_ci self.package = None 367db96d56Sopenharmony_ci self.package_data = None 377db96d56Sopenharmony_ci self.package_dir = None 387db96d56Sopenharmony_ci self.compile = 0 397db96d56Sopenharmony_ci self.optimize = 0 407db96d56Sopenharmony_ci self.force = None 417db96d56Sopenharmony_ci 427db96d56Sopenharmony_ci def finalize_options(self): 437db96d56Sopenharmony_ci self.set_undefined_options('build', 447db96d56Sopenharmony_ci ('build_lib', 'build_lib'), 457db96d56Sopenharmony_ci ('force', 'force')) 467db96d56Sopenharmony_ci 477db96d56Sopenharmony_ci # Get the distribution options that are aliases for build_py 487db96d56Sopenharmony_ci # options -- list of packages and list of modules. 497db96d56Sopenharmony_ci self.packages = self.distribution.packages 507db96d56Sopenharmony_ci self.py_modules = self.distribution.py_modules 517db96d56Sopenharmony_ci self.package_data = self.distribution.package_data 527db96d56Sopenharmony_ci self.package_dir = {} 537db96d56Sopenharmony_ci if self.distribution.package_dir: 547db96d56Sopenharmony_ci for name, path in self.distribution.package_dir.items(): 557db96d56Sopenharmony_ci self.package_dir[name] = convert_path(path) 567db96d56Sopenharmony_ci self.data_files = self.get_data_files() 577db96d56Sopenharmony_ci 587db96d56Sopenharmony_ci # Ick, copied straight from install_lib.py (fancy_getopt needs a 597db96d56Sopenharmony_ci # type system! Hell, *everything* needs a type system!!!) 607db96d56Sopenharmony_ci if not isinstance(self.optimize, int): 617db96d56Sopenharmony_ci try: 627db96d56Sopenharmony_ci self.optimize = int(self.optimize) 637db96d56Sopenharmony_ci assert 0 <= self.optimize <= 2 647db96d56Sopenharmony_ci except (ValueError, AssertionError): 657db96d56Sopenharmony_ci raise DistutilsOptionError("optimize must be 0, 1, or 2") 667db96d56Sopenharmony_ci 677db96d56Sopenharmony_ci def run(self): 687db96d56Sopenharmony_ci # XXX copy_file by default preserves atime and mtime. IMHO this is 697db96d56Sopenharmony_ci # the right thing to do, but perhaps it should be an option -- in 707db96d56Sopenharmony_ci # particular, a site administrator might want installed files to 717db96d56Sopenharmony_ci # reflect the time of installation rather than the last 727db96d56Sopenharmony_ci # modification time before the installed release. 737db96d56Sopenharmony_ci 747db96d56Sopenharmony_ci # XXX copy_file by default preserves mode, which appears to be the 757db96d56Sopenharmony_ci # wrong thing to do: if a file is read-only in the working 767db96d56Sopenharmony_ci # directory, we want it to be installed read/write so that the next 777db96d56Sopenharmony_ci # installation of the same module distribution can overwrite it 787db96d56Sopenharmony_ci # without problems. (This might be a Unix-specific issue.) Thus 797db96d56Sopenharmony_ci # we turn off 'preserve_mode' when copying to the build directory, 807db96d56Sopenharmony_ci # since the build directory is supposed to be exactly what the 817db96d56Sopenharmony_ci # installation will look like (ie. we preserve mode when 827db96d56Sopenharmony_ci # installing). 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_ci # Two options control which modules will be installed: 'packages' 857db96d56Sopenharmony_ci # and 'py_modules'. The former lets us work with whole packages, not 867db96d56Sopenharmony_ci # specifying individual modules at all; the latter is for 877db96d56Sopenharmony_ci # specifying modules one-at-a-time. 887db96d56Sopenharmony_ci 897db96d56Sopenharmony_ci if self.py_modules: 907db96d56Sopenharmony_ci self.build_modules() 917db96d56Sopenharmony_ci if self.packages: 927db96d56Sopenharmony_ci self.build_packages() 937db96d56Sopenharmony_ci self.build_package_data() 947db96d56Sopenharmony_ci 957db96d56Sopenharmony_ci self.byte_compile(self.get_outputs(include_bytecode=0)) 967db96d56Sopenharmony_ci 977db96d56Sopenharmony_ci def get_data_files(self): 987db96d56Sopenharmony_ci """Generate list of '(package,src_dir,build_dir,filenames)' tuples""" 997db96d56Sopenharmony_ci data = [] 1007db96d56Sopenharmony_ci if not self.packages: 1017db96d56Sopenharmony_ci return data 1027db96d56Sopenharmony_ci for package in self.packages: 1037db96d56Sopenharmony_ci # Locate package source directory 1047db96d56Sopenharmony_ci src_dir = self.get_package_dir(package) 1057db96d56Sopenharmony_ci 1067db96d56Sopenharmony_ci # Compute package build directory 1077db96d56Sopenharmony_ci build_dir = os.path.join(*([self.build_lib] + package.split('.'))) 1087db96d56Sopenharmony_ci 1097db96d56Sopenharmony_ci # Length of path to strip from found files 1107db96d56Sopenharmony_ci plen = 0 1117db96d56Sopenharmony_ci if src_dir: 1127db96d56Sopenharmony_ci plen = len(src_dir)+1 1137db96d56Sopenharmony_ci 1147db96d56Sopenharmony_ci # Strip directory from globbed filenames 1157db96d56Sopenharmony_ci filenames = [ 1167db96d56Sopenharmony_ci file[plen:] for file in self.find_data_files(package, src_dir) 1177db96d56Sopenharmony_ci ] 1187db96d56Sopenharmony_ci data.append((package, src_dir, build_dir, filenames)) 1197db96d56Sopenharmony_ci return data 1207db96d56Sopenharmony_ci 1217db96d56Sopenharmony_ci def find_data_files(self, package, src_dir): 1227db96d56Sopenharmony_ci """Return filenames for package's data files in 'src_dir'""" 1237db96d56Sopenharmony_ci globs = (self.package_data.get('', []) 1247db96d56Sopenharmony_ci + self.package_data.get(package, [])) 1257db96d56Sopenharmony_ci files = [] 1267db96d56Sopenharmony_ci for pattern in globs: 1277db96d56Sopenharmony_ci # Each pattern has to be converted to a platform-specific path 1287db96d56Sopenharmony_ci filelist = glob.glob(os.path.join(glob.escape(src_dir), convert_path(pattern))) 1297db96d56Sopenharmony_ci # Files that match more than one pattern are only added once 1307db96d56Sopenharmony_ci files.extend([fn for fn in filelist if fn not in files 1317db96d56Sopenharmony_ci and os.path.isfile(fn)]) 1327db96d56Sopenharmony_ci return files 1337db96d56Sopenharmony_ci 1347db96d56Sopenharmony_ci def build_package_data(self): 1357db96d56Sopenharmony_ci """Copy data files into build directory""" 1367db96d56Sopenharmony_ci lastdir = None 1377db96d56Sopenharmony_ci for package, src_dir, build_dir, filenames in self.data_files: 1387db96d56Sopenharmony_ci for filename in filenames: 1397db96d56Sopenharmony_ci target = os.path.join(build_dir, filename) 1407db96d56Sopenharmony_ci self.mkpath(os.path.dirname(target)) 1417db96d56Sopenharmony_ci self.copy_file(os.path.join(src_dir, filename), target, 1427db96d56Sopenharmony_ci preserve_mode=False) 1437db96d56Sopenharmony_ci 1447db96d56Sopenharmony_ci def get_package_dir(self, package): 1457db96d56Sopenharmony_ci """Return the directory, relative to the top of the source 1467db96d56Sopenharmony_ci distribution, where package 'package' should be found 1477db96d56Sopenharmony_ci (at least according to the 'package_dir' option, if any).""" 1487db96d56Sopenharmony_ci path = package.split('.') 1497db96d56Sopenharmony_ci 1507db96d56Sopenharmony_ci if not self.package_dir: 1517db96d56Sopenharmony_ci if path: 1527db96d56Sopenharmony_ci return os.path.join(*path) 1537db96d56Sopenharmony_ci else: 1547db96d56Sopenharmony_ci return '' 1557db96d56Sopenharmony_ci else: 1567db96d56Sopenharmony_ci tail = [] 1577db96d56Sopenharmony_ci while path: 1587db96d56Sopenharmony_ci try: 1597db96d56Sopenharmony_ci pdir = self.package_dir['.'.join(path)] 1607db96d56Sopenharmony_ci except KeyError: 1617db96d56Sopenharmony_ci tail.insert(0, path[-1]) 1627db96d56Sopenharmony_ci del path[-1] 1637db96d56Sopenharmony_ci else: 1647db96d56Sopenharmony_ci tail.insert(0, pdir) 1657db96d56Sopenharmony_ci return os.path.join(*tail) 1667db96d56Sopenharmony_ci else: 1677db96d56Sopenharmony_ci # Oops, got all the way through 'path' without finding a 1687db96d56Sopenharmony_ci # match in package_dir. If package_dir defines a directory 1697db96d56Sopenharmony_ci # for the root (nameless) package, then fallback on it; 1707db96d56Sopenharmony_ci # otherwise, we might as well have not consulted 1717db96d56Sopenharmony_ci # package_dir at all, as we just use the directory implied 1727db96d56Sopenharmony_ci # by 'tail' (which should be the same as the original value 1737db96d56Sopenharmony_ci # of 'path' at this point). 1747db96d56Sopenharmony_ci pdir = self.package_dir.get('') 1757db96d56Sopenharmony_ci if pdir is not None: 1767db96d56Sopenharmony_ci tail.insert(0, pdir) 1777db96d56Sopenharmony_ci 1787db96d56Sopenharmony_ci if tail: 1797db96d56Sopenharmony_ci return os.path.join(*tail) 1807db96d56Sopenharmony_ci else: 1817db96d56Sopenharmony_ci return '' 1827db96d56Sopenharmony_ci 1837db96d56Sopenharmony_ci def check_package(self, package, package_dir): 1847db96d56Sopenharmony_ci # Empty dir name means current directory, which we can probably 1857db96d56Sopenharmony_ci # assume exists. Also, os.path.exists and isdir don't know about 1867db96d56Sopenharmony_ci # my "empty string means current dir" convention, so we have to 1877db96d56Sopenharmony_ci # circumvent them. 1887db96d56Sopenharmony_ci if package_dir != "": 1897db96d56Sopenharmony_ci if not os.path.exists(package_dir): 1907db96d56Sopenharmony_ci raise DistutilsFileError( 1917db96d56Sopenharmony_ci "package directory '%s' does not exist" % package_dir) 1927db96d56Sopenharmony_ci if not os.path.isdir(package_dir): 1937db96d56Sopenharmony_ci raise DistutilsFileError( 1947db96d56Sopenharmony_ci "supposed package directory '%s' exists, " 1957db96d56Sopenharmony_ci "but is not a directory" % package_dir) 1967db96d56Sopenharmony_ci 1977db96d56Sopenharmony_ci # Require __init__.py for all but the "root package" 1987db96d56Sopenharmony_ci if package: 1997db96d56Sopenharmony_ci init_py = os.path.join(package_dir, "__init__.py") 2007db96d56Sopenharmony_ci if os.path.isfile(init_py): 2017db96d56Sopenharmony_ci return init_py 2027db96d56Sopenharmony_ci else: 2037db96d56Sopenharmony_ci log.warn(("package init file '%s' not found " + 2047db96d56Sopenharmony_ci "(or not a regular file)"), init_py) 2057db96d56Sopenharmony_ci 2067db96d56Sopenharmony_ci # Either not in a package at all (__init__.py not expected), or 2077db96d56Sopenharmony_ci # __init__.py doesn't exist -- so don't return the filename. 2087db96d56Sopenharmony_ci return None 2097db96d56Sopenharmony_ci 2107db96d56Sopenharmony_ci def check_module(self, module, module_file): 2117db96d56Sopenharmony_ci if not os.path.isfile(module_file): 2127db96d56Sopenharmony_ci log.warn("file %s (for module %s) not found", module_file, module) 2137db96d56Sopenharmony_ci return False 2147db96d56Sopenharmony_ci else: 2157db96d56Sopenharmony_ci return True 2167db96d56Sopenharmony_ci 2177db96d56Sopenharmony_ci def find_package_modules(self, package, package_dir): 2187db96d56Sopenharmony_ci self.check_package(package, package_dir) 2197db96d56Sopenharmony_ci module_files = glob.glob(os.path.join(glob.escape(package_dir), "*.py")) 2207db96d56Sopenharmony_ci modules = [] 2217db96d56Sopenharmony_ci setup_script = os.path.abspath(self.distribution.script_name) 2227db96d56Sopenharmony_ci 2237db96d56Sopenharmony_ci for f in module_files: 2247db96d56Sopenharmony_ci abs_f = os.path.abspath(f) 2257db96d56Sopenharmony_ci if abs_f != setup_script: 2267db96d56Sopenharmony_ci module = os.path.splitext(os.path.basename(f))[0] 2277db96d56Sopenharmony_ci modules.append((package, module, f)) 2287db96d56Sopenharmony_ci else: 2297db96d56Sopenharmony_ci self.debug_print("excluding %s" % setup_script) 2307db96d56Sopenharmony_ci return modules 2317db96d56Sopenharmony_ci 2327db96d56Sopenharmony_ci def find_modules(self): 2337db96d56Sopenharmony_ci """Finds individually-specified Python modules, ie. those listed by 2347db96d56Sopenharmony_ci module name in 'self.py_modules'. Returns a list of tuples (package, 2357db96d56Sopenharmony_ci module_base, filename): 'package' is a tuple of the path through 2367db96d56Sopenharmony_ci package-space to the module; 'module_base' is the bare (no 2377db96d56Sopenharmony_ci packages, no dots) module name, and 'filename' is the path to the 2387db96d56Sopenharmony_ci ".py" file (relative to the distribution root) that implements the 2397db96d56Sopenharmony_ci module. 2407db96d56Sopenharmony_ci """ 2417db96d56Sopenharmony_ci # Map package names to tuples of useful info about the package: 2427db96d56Sopenharmony_ci # (package_dir, checked) 2437db96d56Sopenharmony_ci # package_dir - the directory where we'll find source files for 2447db96d56Sopenharmony_ci # this package 2457db96d56Sopenharmony_ci # checked - true if we have checked that the package directory 2467db96d56Sopenharmony_ci # is valid (exists, contains __init__.py, ... ?) 2477db96d56Sopenharmony_ci packages = {} 2487db96d56Sopenharmony_ci 2497db96d56Sopenharmony_ci # List of (package, module, filename) tuples to return 2507db96d56Sopenharmony_ci modules = [] 2517db96d56Sopenharmony_ci 2527db96d56Sopenharmony_ci # We treat modules-in-packages almost the same as toplevel modules, 2537db96d56Sopenharmony_ci # just the "package" for a toplevel is empty (either an empty 2547db96d56Sopenharmony_ci # string or empty list, depending on context). Differences: 2557db96d56Sopenharmony_ci # - don't check for __init__.py in directory for empty package 2567db96d56Sopenharmony_ci for module in self.py_modules: 2577db96d56Sopenharmony_ci path = module.split('.') 2587db96d56Sopenharmony_ci package = '.'.join(path[0:-1]) 2597db96d56Sopenharmony_ci module_base = path[-1] 2607db96d56Sopenharmony_ci 2617db96d56Sopenharmony_ci try: 2627db96d56Sopenharmony_ci (package_dir, checked) = packages[package] 2637db96d56Sopenharmony_ci except KeyError: 2647db96d56Sopenharmony_ci package_dir = self.get_package_dir(package) 2657db96d56Sopenharmony_ci checked = 0 2667db96d56Sopenharmony_ci 2677db96d56Sopenharmony_ci if not checked: 2687db96d56Sopenharmony_ci init_py = self.check_package(package, package_dir) 2697db96d56Sopenharmony_ci packages[package] = (package_dir, 1) 2707db96d56Sopenharmony_ci if init_py: 2717db96d56Sopenharmony_ci modules.append((package, "__init__", init_py)) 2727db96d56Sopenharmony_ci 2737db96d56Sopenharmony_ci # XXX perhaps we should also check for just .pyc files 2747db96d56Sopenharmony_ci # (so greedy closed-source bastards can distribute Python 2757db96d56Sopenharmony_ci # modules too) 2767db96d56Sopenharmony_ci module_file = os.path.join(package_dir, module_base + ".py") 2777db96d56Sopenharmony_ci if not self.check_module(module, module_file): 2787db96d56Sopenharmony_ci continue 2797db96d56Sopenharmony_ci 2807db96d56Sopenharmony_ci modules.append((package, module_base, module_file)) 2817db96d56Sopenharmony_ci 2827db96d56Sopenharmony_ci return modules 2837db96d56Sopenharmony_ci 2847db96d56Sopenharmony_ci def find_all_modules(self): 2857db96d56Sopenharmony_ci """Compute the list of all modules that will be built, whether 2867db96d56Sopenharmony_ci they are specified one-module-at-a-time ('self.py_modules') or 2877db96d56Sopenharmony_ci by whole packages ('self.packages'). Return a list of tuples 2887db96d56Sopenharmony_ci (package, module, module_file), just like 'find_modules()' and 2897db96d56Sopenharmony_ci 'find_package_modules()' do.""" 2907db96d56Sopenharmony_ci modules = [] 2917db96d56Sopenharmony_ci if self.py_modules: 2927db96d56Sopenharmony_ci modules.extend(self.find_modules()) 2937db96d56Sopenharmony_ci if self.packages: 2947db96d56Sopenharmony_ci for package in self.packages: 2957db96d56Sopenharmony_ci package_dir = self.get_package_dir(package) 2967db96d56Sopenharmony_ci m = self.find_package_modules(package, package_dir) 2977db96d56Sopenharmony_ci modules.extend(m) 2987db96d56Sopenharmony_ci return modules 2997db96d56Sopenharmony_ci 3007db96d56Sopenharmony_ci def get_source_files(self): 3017db96d56Sopenharmony_ci return [module[-1] for module in self.find_all_modules()] 3027db96d56Sopenharmony_ci 3037db96d56Sopenharmony_ci def get_module_outfile(self, build_dir, package, module): 3047db96d56Sopenharmony_ci outfile_path = [build_dir] + list(package) + [module + ".py"] 3057db96d56Sopenharmony_ci return os.path.join(*outfile_path) 3067db96d56Sopenharmony_ci 3077db96d56Sopenharmony_ci def get_outputs(self, include_bytecode=1): 3087db96d56Sopenharmony_ci modules = self.find_all_modules() 3097db96d56Sopenharmony_ci outputs = [] 3107db96d56Sopenharmony_ci for (package, module, module_file) in modules: 3117db96d56Sopenharmony_ci package = package.split('.') 3127db96d56Sopenharmony_ci filename = self.get_module_outfile(self.build_lib, package, module) 3137db96d56Sopenharmony_ci outputs.append(filename) 3147db96d56Sopenharmony_ci if include_bytecode: 3157db96d56Sopenharmony_ci if self.compile: 3167db96d56Sopenharmony_ci outputs.append(importlib.util.cache_from_source( 3177db96d56Sopenharmony_ci filename, optimization='')) 3187db96d56Sopenharmony_ci if self.optimize > 0: 3197db96d56Sopenharmony_ci outputs.append(importlib.util.cache_from_source( 3207db96d56Sopenharmony_ci filename, optimization=self.optimize)) 3217db96d56Sopenharmony_ci 3227db96d56Sopenharmony_ci outputs += [ 3237db96d56Sopenharmony_ci os.path.join(build_dir, filename) 3247db96d56Sopenharmony_ci for package, src_dir, build_dir, filenames in self.data_files 3257db96d56Sopenharmony_ci for filename in filenames 3267db96d56Sopenharmony_ci ] 3277db96d56Sopenharmony_ci 3287db96d56Sopenharmony_ci return outputs 3297db96d56Sopenharmony_ci 3307db96d56Sopenharmony_ci def build_module(self, module, module_file, package): 3317db96d56Sopenharmony_ci if isinstance(package, str): 3327db96d56Sopenharmony_ci package = package.split('.') 3337db96d56Sopenharmony_ci elif not isinstance(package, (list, tuple)): 3347db96d56Sopenharmony_ci raise TypeError( 3357db96d56Sopenharmony_ci "'package' must be a string (dot-separated), list, or tuple") 3367db96d56Sopenharmony_ci 3377db96d56Sopenharmony_ci # Now put the module source file into the "build" area -- this is 3387db96d56Sopenharmony_ci # easy, we just copy it somewhere under self.build_lib (the build 3397db96d56Sopenharmony_ci # directory for Python source). 3407db96d56Sopenharmony_ci outfile = self.get_module_outfile(self.build_lib, package, module) 3417db96d56Sopenharmony_ci dir = os.path.dirname(outfile) 3427db96d56Sopenharmony_ci self.mkpath(dir) 3437db96d56Sopenharmony_ci return self.copy_file(module_file, outfile, preserve_mode=0) 3447db96d56Sopenharmony_ci 3457db96d56Sopenharmony_ci def build_modules(self): 3467db96d56Sopenharmony_ci modules = self.find_modules() 3477db96d56Sopenharmony_ci for (package, module, module_file) in modules: 3487db96d56Sopenharmony_ci # Now "build" the module -- ie. copy the source file to 3497db96d56Sopenharmony_ci # self.build_lib (the build directory for Python source). 3507db96d56Sopenharmony_ci # (Actually, it gets copied to the directory for this package 3517db96d56Sopenharmony_ci # under self.build_lib.) 3527db96d56Sopenharmony_ci self.build_module(module, module_file, package) 3537db96d56Sopenharmony_ci 3547db96d56Sopenharmony_ci def build_packages(self): 3557db96d56Sopenharmony_ci for package in self.packages: 3567db96d56Sopenharmony_ci # Get list of (package, module, module_file) tuples based on 3577db96d56Sopenharmony_ci # scanning the package directory. 'package' is only included 3587db96d56Sopenharmony_ci # in the tuple so that 'find_modules()' and 3597db96d56Sopenharmony_ci # 'find_package_tuples()' have a consistent interface; it's 3607db96d56Sopenharmony_ci # ignored here (apart from a sanity check). Also, 'module' is 3617db96d56Sopenharmony_ci # the *unqualified* module name (ie. no dots, no package -- we 3627db96d56Sopenharmony_ci # already know its package!), and 'module_file' is the path to 3637db96d56Sopenharmony_ci # the .py file, relative to the current directory 3647db96d56Sopenharmony_ci # (ie. including 'package_dir'). 3657db96d56Sopenharmony_ci package_dir = self.get_package_dir(package) 3667db96d56Sopenharmony_ci modules = self.find_package_modules(package, package_dir) 3677db96d56Sopenharmony_ci 3687db96d56Sopenharmony_ci # Now loop over the modules we found, "building" each one (just 3697db96d56Sopenharmony_ci # copy it to self.build_lib). 3707db96d56Sopenharmony_ci for (package_, module, module_file) in modules: 3717db96d56Sopenharmony_ci assert package == package_ 3727db96d56Sopenharmony_ci self.build_module(module, module_file, package) 3737db96d56Sopenharmony_ci 3747db96d56Sopenharmony_ci def byte_compile(self, files): 3757db96d56Sopenharmony_ci if sys.dont_write_bytecode: 3767db96d56Sopenharmony_ci self.warn('byte-compiling is disabled, skipping.') 3777db96d56Sopenharmony_ci return 3787db96d56Sopenharmony_ci 3797db96d56Sopenharmony_ci from distutils.util import byte_compile 3807db96d56Sopenharmony_ci prefix = self.build_lib 3817db96d56Sopenharmony_ci if prefix[-1] != os.sep: 3827db96d56Sopenharmony_ci prefix = prefix + os.sep 3837db96d56Sopenharmony_ci 3847db96d56Sopenharmony_ci # XXX this code is essentially the same as the 'byte_compile() 3857db96d56Sopenharmony_ci # method of the "install_lib" command, except for the determination 3867db96d56Sopenharmony_ci # of the 'prefix' string. Hmmm. 3877db96d56Sopenharmony_ci if self.compile: 3887db96d56Sopenharmony_ci byte_compile(files, optimize=0, 3897db96d56Sopenharmony_ci force=self.force, prefix=prefix, dry_run=self.dry_run) 3907db96d56Sopenharmony_ci if self.optimize > 0: 3917db96d56Sopenharmony_ci byte_compile(files, optimize=self.optimize, 3927db96d56Sopenharmony_ci force=self.force, prefix=prefix, dry_run=self.dry_run) 3937db96d56Sopenharmony_ci 3947db96d56Sopenharmony_ciclass build_py_2to3(build_py, Mixin2to3): 3957db96d56Sopenharmony_ci def run(self): 3967db96d56Sopenharmony_ci self.updated_files = [] 3977db96d56Sopenharmony_ci 3987db96d56Sopenharmony_ci # Base class code 3997db96d56Sopenharmony_ci if self.py_modules: 4007db96d56Sopenharmony_ci self.build_modules() 4017db96d56Sopenharmony_ci if self.packages: 4027db96d56Sopenharmony_ci self.build_packages() 4037db96d56Sopenharmony_ci self.build_package_data() 4047db96d56Sopenharmony_ci 4057db96d56Sopenharmony_ci # 2to3 4067db96d56Sopenharmony_ci self.run_2to3(self.updated_files) 4077db96d56Sopenharmony_ci 4087db96d56Sopenharmony_ci # Remaining base class code 4097db96d56Sopenharmony_ci self.byte_compile(self.get_outputs(include_bytecode=0)) 4107db96d56Sopenharmony_ci 4117db96d56Sopenharmony_ci def build_module(self, module, module_file, package): 4127db96d56Sopenharmony_ci res = build_py.build_module(self, module, module_file, package) 4137db96d56Sopenharmony_ci if res[1]: 4147db96d56Sopenharmony_ci # file was copied 4157db96d56Sopenharmony_ci self.updated_files.append(res[0]) 4167db96d56Sopenharmony_ci return res 417