Skip to content

Commit 13ae1c8

Browse files
committed
First checkin of real Distutils command modules.
1 parent 03f8c3c commit 13ae1c8

6 files changed

Lines changed: 448 additions & 0 deletions

File tree

Lib/distutils/command/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# this is solely for debugging convenience
2+
3+
__all__ = ['build',
4+
'build_py',
5+
'make_blib',
6+
]

Lib/distutils/command/build.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
"""distutils.command.build
2+
3+
Implements the Distutils 'build' command."""
4+
5+
# created 1999/03/08, Greg Ward
6+
7+
__rcsid__ = "$Id$"
8+
9+
import os
10+
from distutils.core import Command
11+
12+
13+
class Build (Command):
14+
15+
options = [('basedir=', 'b', "base directory for build library"),
16+
('libdir=', 'l', "directory for platform-shared files"),
17+
('platdir=', 'p', "directory for platform-specific files"),
18+
19+
# Flags for 'build_py'
20+
('compile-py', None, "compile .py to .pyc"),
21+
('optimize-py', None, "compile .py to .pyo (optimized)"),
22+
]
23+
24+
def set_default_options (self):
25+
self.basedir = 'build'
26+
# these are decided only after 'basedir' has its final value
27+
# (unless overridden by the user or client)
28+
self.libdir = None
29+
self.platdir = None
30+
31+
self.compile_py = 1
32+
self.optimize_py = 1
33+
34+
def set_final_options (self):
35+
# 'libdir' and 'platdir' just default to 'lib' and 'plat' under
36+
# the base build directory
37+
if self.libdir is None:
38+
self.libdir = os.path.join (self.basedir, 'lib')
39+
if self.platdir is None:
40+
self.platdir = os.path.join (self.basedir, 'plat')
41+
42+
43+
def run (self):
44+
45+
self.set_final_options ()
46+
47+
# For now, "build" means "build_py" then "build_ext". (Eventually
48+
# it should also build documentation.)
49+
50+
# Invoke the 'build_py' command
51+
self.run_peer ('build_py')
52+
53+
# And now 'build_ext'
54+
#self.run_peer ('build_ext')
55+
56+
# end class Build

Lib/distutils/command/build_py.py

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
"""distutils.command.build_py
2+
3+
Implements the Distutils 'build_py' command."""
4+
5+
# created 1999/03/08, Greg Ward
6+
7+
__rcsid__ = "$Id$"
8+
9+
import string, os
10+
from distutils.core import Command
11+
from distutils.errors import *
12+
from distutils.util import mkpath, newer, make_file, copy_file
13+
14+
15+
class BuildPy (Command):
16+
17+
options = [('dir=', 'd', "directory for platform-shared files"),
18+
('compile', 'c', "compile .py to .pyc"),
19+
('optimize', 'o', "compile .py to .pyo (optimized)"),
20+
]
21+
22+
23+
def set_default_options (self):
24+
self.dir = None
25+
self.compile = 1
26+
self.optimize = 1
27+
28+
def set_final_options (self):
29+
self.set_undefined_options ('build',
30+
('libdir', 'dir'),
31+
('compile_py', 'compile'),
32+
('optimize_py', 'optimize'))
33+
34+
35+
def run (self):
36+
37+
# XXX copy_file by default preserves all stat info -- mode, atime,
38+
# and mtime. IMHO this is the right thing to do, but perhaps it
39+
# should be an option -- in particular, a site administrator might
40+
# want installed files to reflect the time of installation rather
41+
# than the last modification time before the installed release.
42+
43+
# XXX copy_file does *not* preserve MacOS-specific file metadata.
44+
# If this is a problem for building/installing Python modules, then
45+
# we'll have to fix copy_file. (And what about installing scripts,
46+
# when the time comes for that -- does MacOS use its special
47+
# metadata to know that a file is meant to be interpreted by
48+
# Python?)
49+
50+
self.set_final_options ()
51+
52+
(modules, package) = \
53+
self.distribution.get_options ('py_modules', 'package')
54+
package = package or ''
55+
56+
infiles = []
57+
outfiles = []
58+
missing = []
59+
60+
# Loop over the list of "pure Python" modules, deriving
61+
# input and output filenames and checking for missing
62+
# input files.
63+
64+
# XXX we should allow for wildcards, so eg. the Distutils setup.py
65+
# file would just have to say
66+
# py_modules = ['distutils.*', 'distutils.command.*']
67+
# without having to list each one explicitly.
68+
for m in modules:
69+
fn = apply (os.path.join, tuple (string.split (m, '.'))) + '.py'
70+
if not os.path.exists (fn):
71+
missing.append (fn)
72+
else:
73+
infiles.append (fn)
74+
outfiles.append (os.path.join (self.dir, package, fn))
75+
76+
# Blow up if any input files were not found.
77+
if missing:
78+
raise DistutilsFileError, \
79+
"missing files: " + string.join (missing, ' ')
80+
81+
# Loop over the list of input files, copying them to their
82+
# temporary (build) destination.
83+
created = {}
84+
for i in range (len (infiles)):
85+
outdir = os.path.split (outfiles[i])[0]
86+
if not created.get(outdir):
87+
mkpath (outdir, verbose=self.distribution.verbose)
88+
created[outdir] = 1
89+
90+
copy_file (infiles[i], outfiles[i],
91+
update=1, verbose=self.distribution.verbose)
92+
93+
# (Optionally) compile .py to .pyc
94+
# XXX hey! we can't control whether we optimize or not; that's up
95+
# to the invocation of the current Python interpreter (at least
96+
# according to the py_compile docs). That sucks.
97+
98+
if self.compile:
99+
from py_compile import compile
100+
101+
for f in outfiles:
102+
# XXX can't assume this filename mapping!
103+
out_fn = string.replace (f, '.py', '.pyc')
104+
105+
make_file (f, out_fn, compile, (f,),
106+
verbose=self.distribution.verbose,
107+
update_message="compiling %s" % f)
108+
109+
# XXX ignore self.optimize for now, since we don't really know if
110+
# we're compiling optimally or not, and couldn't pick what to do
111+
# even if we did know. ;-(
112+
113+
# end class BuildPy

Lib/distutils/command/install.py

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
"""distutils.command.install
2+
3+
Implements the Distutils 'install' command."""
4+
5+
# created 1999/03/13, Greg Ward
6+
7+
__rcsid__ = "$Id$"
8+
9+
import sys, os, string
10+
from distutils import sysconfig
11+
from distutils.core import Command
12+
13+
14+
class Install (Command):
15+
16+
options = [('prefix=', None, "installation prefix"),
17+
('execprefix=', None,
18+
"prefix for platform-specific files"),
19+
20+
# Build directories: where to install from
21+
('build-base=', None,
22+
"base build directory"),
23+
('build-lib=', None,
24+
"build directory for non-platform-specific library files"),
25+
('build-platlib=', None,
26+
"build directory for platform-specific library files"),
27+
28+
# Installation directories: where to put modules and packages
29+
('install-lib=', None,
30+
"base Python library directory"),
31+
('install-platlib=', None,
32+
"platform-specific Python library directory"),
33+
('install-site-lib=', None,
34+
"directory for site-specific packages and modules"),
35+
('install-site-platlib=', None,
36+
"platform-specific site directory"),
37+
('install-scheme=', None,
38+
"install to 'system' or 'site' library directory?"),
39+
40+
# Where to install documentation (eventually!)
41+
('doc-format=', None, "format of documentation to generate"),
42+
('install-man=', None, "directory for Unix man pages"),
43+
('install-html=', None, "directory for HTML documentation"),
44+
('install-info=', None, "directory for GNU info files"),
45+
46+
]
47+
48+
def set_default_options (self):
49+
50+
self.build_base = None
51+
self.build_lib = None
52+
self.build_platlib = None
53+
54+
# Don't define 'prefix' or 'exec_prefix' so we can know when the
55+
# command is run whether the user supplied values
56+
self.prefix = None
57+
self.exec_prefix = None
58+
59+
# These two, we can supply real values for! (because they're
60+
# not directories, and don't have a confusing multitude of
61+
# possible derivations)
62+
#self.install_scheme = 'site'
63+
self.doc_format = None
64+
65+
# The actual installation directories are determined only at
66+
# run-time, so the user can supply just prefix (and exec_prefix?)
67+
# as a base for everything else
68+
self.install_lib = None
69+
self.install_platlib = None
70+
self.install_site_lib = None
71+
self.install_site_platlib = None
72+
73+
self.install_man = None
74+
self.install_html = None
75+
self.install_info = None
76+
77+
78+
def set_final_options (self):
79+
80+
# Figure out the build directories, ie. where to install from
81+
self.set_peer_option ('build', 'basedir', self.build_base)
82+
self.set_undefined_options ('build',
83+
('basedir', 'build_base'),
84+
('libdir', 'build_lib'),
85+
('platdir', 'build_platlib'))
86+
87+
# Figure out actual installation directories; the basic principle
88+
# is: if the user supplied nothing, then use the directories that
89+
# Python was built and installed with (ie. the compiled-in prefix
90+
# and exec_prefix, and the actual installation directories gleaned
91+
# by sysconfig). If the user supplied a prefix (and possibly
92+
# exec_prefix), then we generate our own installation directories,
93+
# following any pattern gleaned from sysconfig's findings. If no
94+
# such pattern can be gleaned, then we'll just make do and try to
95+
# ape the behaviour of Python's configure script.
96+
97+
if self.prefix is None: # user didn't override
98+
self.prefix = sys.prefix
99+
if self.exec_prefix is None:
100+
self.exec_prefix = sys.exec_prefix
101+
102+
if self.install_lib is None:
103+
self.install_lib = \
104+
self.replace_sys_prefix ('LIBDEST', ('lib','python1.5'))
105+
if self.install_platlib is None:
106+
# XXX this should probably be DESTSHARED -- but why is there no
107+
# equivalent to DESTSHARED for the "site-packages" dir"?
108+
self.install_platlib = \
109+
self.replace_sys_prefix ('BINLIBDEST', ('lib','python1.5'), 1)
110+
111+
if self.install_site_lib is None:
112+
self.install_site_lib = \
113+
os.path.join (self.install_lib, 'site-packages')
114+
if self.install_site_platlib is None:
115+
# XXX ugh! this puts platform-specific files in with shared files,
116+
# with no nice way to override it! (this might be a Python
117+
# problem, though, not a Distutils problem...)
118+
self.install_site_platlib = \
119+
os.path.join (self.install_lib, 'site-packages')
120+
121+
#if self.install_scheme == 'site':
122+
# install_lib = self.install_site_lib
123+
# install_platlib = self.install_site_platlib
124+
#elif self.install_scheme == 'system':
125+
# install_lib = self.install_lib
126+
# install_platlib = self.install_platlib
127+
#else:
128+
# # XXX new exception for this kind of misbehaviour?
129+
# raise DistutilsArgError, \
130+
# "invalid install scheme '%s'" % self.install_scheme
131+
132+
133+
# Punt on doc directories for now -- after all, we're punting on
134+
# documentation completely!
135+
136+
# set_final_options ()
137+
138+
139+
def replace_sys_prefix (self, config_attr, fallback_postfix, use_exec=0):
140+
"""Attempts to glean a simple pattern from an installation
141+
directory available as a 'sysconfig' attribute: if the
142+
directory name starts with the "system prefix" (the one
143+
hard-coded in the Makefile and compiled into Python),
144+
then replace it with the current installation prefix and
145+
return the "relocated" installation directory."""
146+
147+
if use_exec:
148+
sys_prefix = sys.exec_prefix
149+
my_prefix = self.exec_prefix
150+
else:
151+
sys_prefix = sys.prefix
152+
my_prefix = self.prefix
153+
154+
val = getattr (sysconfig, config_attr)
155+
if string.find (val, sys_prefix) == 0:
156+
# If the sysconfig directory starts with the system prefix,
157+
# then we can "relocate" it to the user-supplied prefix --
158+
# assuming, of course, it is different from the system prefix.
159+
160+
if sys_prefix == my_prefix:
161+
return val
162+
else:
163+
return my_prefix + val[len(sys_prefix):]
164+
165+
else:
166+
# Otherwise, just tack the "fallback postfix" onto the
167+
# user-specified prefix.
168+
169+
return apply (os.join, (my_prefix,) + fallback_postfix)
170+
171+
# replace_sys_prefix ()
172+
173+
174+
def run (self):
175+
176+
self.set_final_options ()
177+
178+
# Install modules in two steps: "platform-shared" files (ie. pure
179+
# python modules) and platform-specific files (compiled C
180+
# extensions).
181+
182+
self.run_peer ('install_py')
183+
184+
# don't have an 'install_ext' command just yet!
185+
#self.run_peer ('install_ext'))
186+
187+
# run ()
188+
189+
# class Install

0 commit comments

Comments
 (0)