build_py.py revision 3ce77fd05ed00168f618b63401d770ccc4f04b09
113ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward"""distutils.command.build_py 213ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward 313ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg WardImplements the Distutils 'build_py' command.""" 413ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward 513ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward# created 1999/03/08, Greg Ward 613ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward 73ce77fd05ed00168f618b63401d770ccc4f04b09Greg Ward__revision__ = "$Id$" 813ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward 99b45443c1bdf99b0f27b12baf06fea475b60e145Greg Wardimport sys, string, os 1017dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Wardfrom types import * 1117dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Wardfrom glob import glob 1217dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 1313ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Wardfrom distutils.core import Command 1413ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Wardfrom distutils.errors import * 1513ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward 1613ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward 171993f9ad0e2cf53c8dc441cbbb44eb2e3a190538Greg Wardclass build_py (Command): 1813ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward 1937bc81505379facad85a7c6ff273de0201f28656Greg Ward description = "\"build\" pure Python modules (copy to build directory)" 2037bc81505379facad85a7c6ff273de0201f28656Greg Ward 21bbeceeaf9a5edf878154b17a6a94403a26822d51Greg Ward user_options = [ 22e6916516828a88ab71fab7a749f8c9cf6b52775aGreg Ward ('build-lib=', 'd', "directory to \"build\" (copy) to"), 23bbeceeaf9a5edf878154b17a6a94403a26822d51Greg Ward ] 2413ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward 2513ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward 26e01149cbe83778a5cf872a6b429ff33179b7cdcbGreg Ward def initialize_options (self): 27e6916516828a88ab71fab7a749f8c9cf6b52775aGreg Ward self.build_lib = None 2871eb8644d7e27fd379a2cf78c509155bdb179332Greg Ward self.modules = None 2971eb8644d7e27fd379a2cf78c509155bdb179332Greg Ward self.package = None 3017dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward self.package_dir = None 3113ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward 32e01149cbe83778a5cf872a6b429ff33179b7cdcbGreg Ward def finalize_options (self): 3313ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward self.set_undefined_options ('build', 34e6916516828a88ab71fab7a749f8c9cf6b52775aGreg Ward ('build_lib', 'build_lib')) 3517dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 3617dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # Get the distribution options that are aliases for build_py 3717dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # options -- list of packages and list of modules. 3817dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward self.packages = self.distribution.packages 3917dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward self.modules = self.distribution.py_modules 4017dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward self.package_dir = self.distribution.package_dir 4113ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward 4213ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward 4313ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward def run (self): 4413ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward 459b45443c1bdf99b0f27b12baf06fea475b60e145Greg Ward # XXX copy_file by default preserves atime and mtime. IMHO this is 469b45443c1bdf99b0f27b12baf06fea475b60e145Greg Ward # the right thing to do, but perhaps it should be an option -- in 479b45443c1bdf99b0f27b12baf06fea475b60e145Greg Ward # particular, a site administrator might want installed files to 489b45443c1bdf99b0f27b12baf06fea475b60e145Greg Ward # reflect the time of installation rather than the last 499b45443c1bdf99b0f27b12baf06fea475b60e145Greg Ward # modification time before the installed release. 509b45443c1bdf99b0f27b12baf06fea475b60e145Greg Ward 519b45443c1bdf99b0f27b12baf06fea475b60e145Greg Ward # XXX copy_file by default preserves mode, which appears to be the 529b45443c1bdf99b0f27b12baf06fea475b60e145Greg Ward # wrong thing to do: if a file is read-only in the working 539b45443c1bdf99b0f27b12baf06fea475b60e145Greg Ward # directory, we want it to be installed read/write so that the next 549b45443c1bdf99b0f27b12baf06fea475b60e145Greg Ward # installation of the same module distribution can overwrite it 559b45443c1bdf99b0f27b12baf06fea475b60e145Greg Ward # without problems. (This might be a Unix-specific issue.) Thus 569b45443c1bdf99b0f27b12baf06fea475b60e145Greg Ward # we turn off 'preserve_mode' when copying to the build directory, 579b45443c1bdf99b0f27b12baf06fea475b60e145Greg Ward # since the build directory is supposed to be exactly what the 589b45443c1bdf99b0f27b12baf06fea475b60e145Greg Ward # installation will look like (ie. we preserve mode when 599b45443c1bdf99b0f27b12baf06fea475b60e145Greg Ward # installing). 6013ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward 6113ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward # XXX copy_file does *not* preserve MacOS-specific file metadata. 6213ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward # If this is a problem for building/installing Python modules, then 6313ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward # we'll have to fix copy_file. (And what about installing scripts, 6413ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward # when the time comes for that -- does MacOS use its special 6513ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward # metadata to know that a file is meant to be interpreted by 6613ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward # Python?) 6713ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward 6813ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward infiles = [] 6913ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward outfiles = [] 7013ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward missing = [] 7113ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward 7217dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # Two options control which modules will be installed: 'packages' 7317dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # and 'modules'. The former lets us work with whole packages, not 7417dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # specifying individual modules at all; the latter is for 7517dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # specifying modules one-at-a-time. Currently they are mutually 7617dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # exclusive: you can define one or the other (or neither), but not 7717dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # both. It remains to be seen how limiting this is. 7813ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward 7917dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # Dispose of the two "unusual" cases first: no pure Python modules 8017dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # at all (no problem, just return silently), and over-specified 8117dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # 'packages' and 'modules' options. 8217dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 8317dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward if not self.modules and not self.packages: 845d60fcf02a7050a07067a12c7a98c8b6b1e68372Greg Ward return 8517dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward if self.modules and self.packages: 8617dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward raise DistutilsOptionError, \ 8717dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward "build_py: supplying both 'packages' and 'modules' " + \ 889b45443c1bdf99b0f27b12baf06fea475b60e145Greg Ward "options is not allowed" 8917dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 9017dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # Now we're down to two cases: 'modules' only and 'packages' only. 9117dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward if self.modules: 9217dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward self.build_modules () 9317dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward else: 9417dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward self.build_packages () 9517dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 9617dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # run () 975d60fcf02a7050a07067a12c7a98c8b6b1e68372Greg Ward 9817dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 9917dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward def get_package_dir (self, package): 10017dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward """Return the directory, relative to the top of the source 10117dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward distribution, where package 'package' should be found 10217dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward (at least according to the 'package_dir' option, if any).""" 10317dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 10417dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward if type (package) is StringType: 10517dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward path = string.split (package, '.') 10617dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward elif type (package) in (TupleType, ListType): 107631e6a0c070810b064c48ff6cf777ebb0276f038Greg Ward path = list (package) 10817dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward else: 10917dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward raise TypeError, "'package' must be a string, list, or tuple" 11017dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 11117dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward if not self.package_dir: 112631e6a0c070810b064c48ff6cf777ebb0276f038Greg Ward if path: 113631e6a0c070810b064c48ff6cf777ebb0276f038Greg Ward return apply (os.path.join, path) 114631e6a0c070810b064c48ff6cf777ebb0276f038Greg Ward else: 115631e6a0c070810b064c48ff6cf777ebb0276f038Greg Ward return '' 11617dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward else: 11717dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward tail = [] 11817dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward while path: 11917dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward try: 12017dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward pdir = self.package_dir[string.join (path, '.')] 12117dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward except KeyError: 12217dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward tail.insert (0, path[-1]) 12317dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward del path[-1] 12417dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward else: 12517dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward tail.insert (0, pdir) 12617dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward return apply (os.path.join, tail) 12713ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward else: 12817dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # arg! everything failed, we might as well have not even 12917dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # looked in package_dir -- oh well 130631e6a0c070810b064c48ff6cf777ebb0276f038Greg Ward if tail: 131631e6a0c070810b064c48ff6cf777ebb0276f038Greg Ward return apply (os.path.join, tail) 132631e6a0c070810b064c48ff6cf777ebb0276f038Greg Ward else: 133631e6a0c070810b064c48ff6cf777ebb0276f038Greg Ward return '' 13417dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 13517dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # get_package_dir () 13617dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 13717dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 13817dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward def check_package (self, package, package_dir): 13917dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 14017dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # Empty dir name means current directory, which we can probably 14117dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # assume exists. Also, os.path.exists and isdir don't know about 14217dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # my "empty string means current dir" convention, so we have to 14317dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # circumvent them. 14417dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward if package_dir != "": 14517dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward if not os.path.exists (package_dir): 14617dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward raise DistutilsFileError, \ 14717dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward "package directory '%s' does not exist" % package_dir 14817dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward if not os.path.isdir (package_dir): 14917dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward raise DistutilsFileErorr, \ 15017dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward ("supposed package directory '%s' exists, " + 15117dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward "but is not a directory") % package_dir 15217dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 15317dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # Require __init__.py for all but the "root package" 154631e6a0c070810b064c48ff6cf777ebb0276f038Greg Ward if package: 15517dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward init_py = os.path.join (package_dir, "__init__.py") 15617dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward if not os.path.isfile (init_py): 15717dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward self.warn (("package init file '%s' not found " + 15817dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward "(or not a regular file)") % init_py) 15917dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # check_package () 16017dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 16117dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 16217dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward def check_module (self, module, module_file): 16317dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward if not os.path.isfile (module_file): 164113e70efa2b932a3ad2662875114133a1edb600cGreg Ward self.warn ("file %s (for module %s) not found" % 165113e70efa2b932a3ad2662875114133a1edb600cGreg Ward (module_file, module)) 16617dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward return 0 16717dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward else: 16817dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward return 1 16917dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 17017dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # check_module () 17117dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 17217dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 1732a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward def find_package_modules (self, package, package_dir): 17417dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward module_files = glob (os.path.join (package_dir, "*.py")) 17517dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward module_pairs = [] 1769b45443c1bdf99b0f27b12baf06fea475b60e145Greg Ward setup_script = os.path.abspath (sys.argv[0]) 1779b45443c1bdf99b0f27b12baf06fea475b60e145Greg Ward 17817dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward for f in module_files: 1799b45443c1bdf99b0f27b12baf06fea475b60e145Greg Ward abs_f = os.path.abspath (f) 1809b45443c1bdf99b0f27b12baf06fea475b60e145Greg Ward if abs_f != setup_script: 1819b45443c1bdf99b0f27b12baf06fea475b60e145Greg Ward module = os.path.splitext (os.path.basename (f))[0] 1829b45443c1bdf99b0f27b12baf06fea475b60e145Greg Ward module_pairs.append ((module, f)) 18317dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward return module_pairs 18417dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 18517dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 1862a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward def find_modules (self): 18717dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # Map package names to tuples of useful info about the package: 18817dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # (package_dir, checked) 18917dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # package_dir - the directory where we'll find source files for 19017dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # this package 19117dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # checked - true if we have checked that the package directory 19217dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # is valid (exists, contains __init__.py, ... ?) 19317dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward packages = {} 19417dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 1952a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward # List of (module, package, filename) tuples to return 1962a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward modules = [] 1972a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward 19817dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # We treat modules-in-packages almost the same as toplevel modules, 19917dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # just the "package" for a toplevel is empty (either an empty 20017dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # string or empty list, depending on context). Differences: 20117dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # - don't check for __init__.py in directory for empty package 20217dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 20317dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward for module in self.modules: 20417dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward path = string.split (module, '.') 20517dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward package = tuple (path[0:-1]) 2062a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward module_base = path[-1] 20717dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 20817dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward try: 20917dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward (package_dir, checked) = packages[package] 21017dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward except KeyError: 21117dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward package_dir = self.get_package_dir (package) 21217dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward checked = 0 21317dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 21417dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward if not checked: 21517dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward self.check_package (package, package_dir) 21617dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward packages[package] = (package_dir, 1) 21717dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 21817dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # XXX perhaps we should also check for just .pyc files 21917dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # (so greedy closed-source bastards can distribute Python 22017dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # modules too) 2212a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward module_file = os.path.join (package_dir, module_base + ".py") 22217dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward if not self.check_module (module, module_file): 22317dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward continue 22417dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 2252a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward modules.append ((module, package, module_file)) 2262a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward 2272a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward return modules 2282a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward 2292a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward # find_modules () 2302a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward 2312a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward 2322a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward def get_source_files (self): 2332a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward 2342a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward if self.modules: 2352a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward modules = self.find_modules () 2362a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward else: 2372a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward modules = [] 2382a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward for package in self.packages: 2392a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward package_dir = self.get_package_dir (package) 2402a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward m = self.find_package_modules (package, package_dir) 2412a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward modules.extend (m) 2422a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward 2432a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward # Both find_modules() and find_package_modules() return a list of 2442a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward # tuples where the last element of each tuple is the filename -- 2452a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward # what a happy coincidence! 2462a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward filenames = [] 2472a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward for module in modules: 2482a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward filenames.append (module[-1]) 2492a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward 2502a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward return filenames 2512a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward 2522a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward 2532a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward def build_module (self, module, module_file, package): 2542a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward 2552a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward if type (package) is StringType: 2562a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward package = string.split (package, '.') 257631e6a0c070810b064c48ff6cf777ebb0276f038Greg Ward elif type (package) not in (ListType, TupleType): 258631e6a0c070810b064c48ff6cf777ebb0276f038Greg Ward raise TypeError, \ 259631e6a0c070810b064c48ff6cf777ebb0276f038Greg Ward "'package' must be a string (dot-separated), list, or tuple" 2602a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward 2612a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward # Now put the module source file into the "build" area -- this is 262e6916516828a88ab71fab7a749f8c9cf6b52775aGreg Ward # easy, we just copy it somewhere under self.build_lib (the build 2632a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward # directory for Python source). 264631e6a0c070810b064c48ff6cf777ebb0276f038Greg Ward outfile_path = list (package) 2652a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward outfile_path.append (module + ".py") 266e6916516828a88ab71fab7a749f8c9cf6b52775aGreg Ward outfile_path.insert (0, self.build_lib) 2672a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward outfile = apply (os.path.join, outfile_path) 2682a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward 2692a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward dir = os.path.dirname (outfile) 2702a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward self.mkpath (dir) 2719b45443c1bdf99b0f27b12baf06fea475b60e145Greg Ward self.copy_file (module_file, outfile, preserve_mode=0) 2722a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward 2732a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward 2742a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward def build_modules (self): 2752a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward 2762a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward modules = self.find_modules() 2772a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward for (module, package, module_file) in modules: 2782a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward 27917dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # Now "build" the module -- ie. copy the source file to 280e6916516828a88ab71fab7a749f8c9cf6b52775aGreg Ward # self.build_lib (the build directory for Python source). 2812a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward # (Actually, it gets copied to the directory for this package 282e6916516828a88ab71fab7a749f8c9cf6b52775aGreg Ward # under self.build_lib.) 28317dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward self.build_module (module, module_file, package) 28417dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 28517dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # build_modules () 28617dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 28717dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 28817dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward def build_packages (self): 28917dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 29017dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward for package in self.packages: 29117dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward package_dir = self.get_package_dir (package) 29217dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward self.check_package (package, package_dir) 29317dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 29417dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # Get list of (module, module_file) tuples based on scanning 29517dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # the package directory. Here, 'module' is the *unqualified* 29617dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # module name (ie. no dots, no package -- we already know its 29717dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # package!), and module_file is the path to the .py file, 29817dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # relative to the current directory (ie. including 29917dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # 'package_dir'). 3002a612067e60a98f05d39b39f4a7a5a7a8065bfc9Greg Ward modules = self.find_package_modules (package, package_dir) 30117dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 30217dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # Now loop over the modules we found, "building" each one (just 303e6916516828a88ab71fab7a749f8c9cf6b52775aGreg Ward # copy it to self.build_lib). 30417dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward for (module, module_file) in modules: 30517dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward self.build_module (module, module_file, package) 30617dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward 30717dc6e7ed8cd62068b5f244a9f1023917d3caf4aGreg Ward # build_packages () 30813ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward 30913ae1c8ff81befcfd0b0ece98ef471cd504642d8Greg Ward# end class BuildPy 310