summaryrefslogtreecommitdiffstats
path: root/Lib/distutils/command/build_py.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/distutils/command/build_py.py')
-rw-r--r--Lib/distutils/command/build_py.py113
1 files changed, 113 insertions, 0 deletions
diff --git a/Lib/distutils/command/build_py.py b/Lib/distutils/command/build_py.py
new file mode 100644
index 0000000..ae133f9
--- /dev/null
+++ b/Lib/distutils/command/build_py.py
@@ -0,0 +1,113 @@
+"""distutils.command.build_py
+
+Implements the Distutils 'build_py' command."""
+
+# created 1999/03/08, Greg Ward
+
+__rcsid__ = "$Id$"
+
+import string, os
+from distutils.core import Command
+from distutils.errors import *
+from distutils.util import mkpath, newer, make_file, copy_file
+
+
+class BuildPy (Command):
+
+ options = [('dir=', 'd', "directory for platform-shared files"),
+ ('compile', 'c', "compile .py to .pyc"),
+ ('optimize', 'o', "compile .py to .pyo (optimized)"),
+ ]
+
+
+ def set_default_options (self):
+ self.dir = None
+ self.compile = 1
+ self.optimize = 1
+
+ def set_final_options (self):
+ self.set_undefined_options ('build',
+ ('libdir', 'dir'),
+ ('compile_py', 'compile'),
+ ('optimize_py', 'optimize'))
+
+
+ def run (self):
+
+ # XXX copy_file by default preserves all stat info -- mode, atime,
+ # and mtime. IMHO this is the right thing to do, but perhaps it
+ # should be an option -- in particular, a site administrator might
+ # want installed files to reflect the time of installation rather
+ # than the last modification time before the installed release.
+
+ # XXX copy_file does *not* preserve MacOS-specific file metadata.
+ # If this is a problem for building/installing Python modules, then
+ # we'll have to fix copy_file. (And what about installing scripts,
+ # when the time comes for that -- does MacOS use its special
+ # metadata to know that a file is meant to be interpreted by
+ # Python?)
+
+ self.set_final_options ()
+
+ (modules, package) = \
+ self.distribution.get_options ('py_modules', 'package')
+ package = package or ''
+
+ infiles = []
+ outfiles = []
+ missing = []
+
+ # Loop over the list of "pure Python" modules, deriving
+ # input and output filenames and checking for missing
+ # input files.
+
+ # XXX we should allow for wildcards, so eg. the Distutils setup.py
+ # file would just have to say
+ # py_modules = ['distutils.*', 'distutils.command.*']
+ # without having to list each one explicitly.
+ for m in modules:
+ fn = apply (os.path.join, tuple (string.split (m, '.'))) + '.py'
+ if not os.path.exists (fn):
+ missing.append (fn)
+ else:
+ infiles.append (fn)
+ outfiles.append (os.path.join (self.dir, package, fn))
+
+ # Blow up if any input files were not found.
+ if missing:
+ raise DistutilsFileError, \
+ "missing files: " + string.join (missing, ' ')
+
+ # Loop over the list of input files, copying them to their
+ # temporary (build) destination.
+ created = {}
+ for i in range (len (infiles)):
+ outdir = os.path.split (outfiles[i])[0]
+ if not created.get(outdir):
+ mkpath (outdir, verbose=self.distribution.verbose)
+ created[outdir] = 1
+
+ copy_file (infiles[i], outfiles[i],
+ update=1, verbose=self.distribution.verbose)
+
+ # (Optionally) compile .py to .pyc
+ # XXX hey! we can't control whether we optimize or not; that's up
+ # to the invocation of the current Python interpreter (at least
+ # according to the py_compile docs). That sucks.
+
+ if self.compile:
+ from py_compile import compile
+
+ for f in outfiles:
+ # XXX can't assume this filename mapping!
+ out_fn = string.replace (f, '.py', '.pyc')
+
+ make_file (f, out_fn, compile, (f,),
+ verbose=self.distribution.verbose,
+ update_message="compiling %s" % f)
+
+ # XXX ignore self.optimize for now, since we don't really know if
+ # we're compiling optimally or not, and couldn't pick what to do
+ # even if we did know. ;-(
+
+# end class BuildPy