]> git.rkrishnan.org Git - tahoe-lafs/zfec.git/blob - zfec/setuptools-0.6c15dev.egg/setuptools/command/build_py.py
setup: bundle the latest zetuptoolz as unpacked source egg and change setup.py to...
[tahoe-lafs/zfec.git] / zfec / setuptools-0.6c15dev.egg / setuptools / command / build_py.py
1 import os.path, sys, fnmatch
2 from distutils.command.build_py import build_py as _build_py
3 from distutils.util import convert_path
4 from glob import glob
5
6 class build_py(_build_py):
7     """Enhanced 'build_py' command that includes data files with packages
8
9     The data files are specified via a 'package_data' argument to 'setup()'.
10     See 'setuptools.dist.Distribution' for more details.
11
12     Also, this version of the 'build_py' command allows you to specify both
13     'py_modules' and 'packages' in the same setup operation.
14     """
15     def finalize_options(self):
16         _build_py.finalize_options(self)
17         self.package_data = self.distribution.package_data
18         self.exclude_package_data = self.distribution.exclude_package_data or {}
19         if 'data_files' in self.__dict__: del self.__dict__['data_files']
20
21     def run(self):
22         """Build modules, packages, and copy data files to build directory"""
23         if not self.py_modules and not self.packages:
24             return
25
26         if self.py_modules:
27             self.build_modules()
28
29         if self.packages:
30             self.build_packages()
31             self.build_package_data()
32
33         # Only compile actual .py files, using our base class' idea of what our
34         # output files are.
35         self.byte_compile(_build_py.get_outputs(self, include_bytecode=0))
36
37     def __getattr__(self,attr):
38         if attr=='data_files':  # lazily compute data files
39             self.data_files = files = self._get_data_files(); return files
40         return _build_py.__getattr__(self,attr)
41
42     def _get_data_files(self):
43         """Generate list of '(package,src_dir,build_dir,filenames)' tuples"""
44         self.analyze_manifest()
45         data = []
46         for package in self.packages or ():
47             # Locate package source directory
48             src_dir = self.get_package_dir(package)
49
50             # Compute package build directory
51             build_dir = os.path.join(*([self.build_lib] + package.split('.')))
52
53             # Length of path to strip from found files
54             plen = len(src_dir)+1
55
56             # Strip directory from globbed filenames
57             filenames = [
58                 file[plen:] for file in self.find_data_files(package, src_dir)
59                 ]
60             data.append( (package, src_dir, build_dir, filenames) )
61         return data
62
63     def find_data_files(self, package, src_dir):
64         """Return filenames for package's data files in 'src_dir'"""
65         globs = (self.package_data.get('', [])
66                  + self.package_data.get(package, []))
67         files = self.manifest_files.get(package, [])[:]
68         for pattern in globs:
69             # Each pattern has to be converted to a platform-specific path
70             files.extend(glob(os.path.join(src_dir, convert_path(pattern))))
71         return self.exclude_data_files(package, src_dir, files)
72
73     def build_package_data(self):
74         """Copy data files into build directory"""
75         lastdir = None
76         for package, src_dir, build_dir, filenames in self.data_files:
77             for filename in filenames:
78                 target = os.path.join(build_dir, filename)
79                 self.mkpath(os.path.dirname(target))
80                 self.copy_file(os.path.join(src_dir, filename), target)
81
82
83     def analyze_manifest(self):
84         self.manifest_files = mf = {}
85         if not self.distribution.include_package_data:
86             return
87         src_dirs = {}
88         for package in self.packages or ():
89             # Locate package source directory
90             src_dirs[assert_relative(self.get_package_dir(package))] = package
91
92         self.run_command('egg_info')
93         ei_cmd = self.get_finalized_command('egg_info')
94         for path in ei_cmd.filelist.files:
95             d,f = os.path.split(assert_relative(path))
96             prev = None
97             oldf = f
98             while d and d!=prev and d not in src_dirs:
99                 prev = d
100                 d, df = os.path.split(d)
101                 f = os.path.join(df, f)
102             if d in src_dirs:
103                 if path.endswith('.py') and f==oldf:
104                     continue    # it's a module, not data
105                 mf.setdefault(src_dirs[d],[]).append(path)
106
107     def get_data_files(self): pass  # kludge 2.4 for lazy computation
108
109     if sys.version<"2.4":    # Python 2.4 already has this code
110         def get_outputs(self, include_bytecode=1):
111             """Return complete list of files copied to the build directory
112
113             This includes both '.py' files and data files, as well as '.pyc'
114             and '.pyo' files if 'include_bytecode' is true.  (This method is
115             needed for the 'install_lib' command to do its job properly, and to
116             generate a correct installation manifest.)
117             """
118             return _build_py.get_outputs(self, include_bytecode) + [
119                 os.path.join(build_dir, filename)
120                 for package, src_dir, build_dir,filenames in self.data_files
121                 for filename in filenames
122                 ]
123
124     def check_package(self, package, package_dir):
125         """Check namespace packages' __init__ for declare_namespace"""
126         try:
127             return self.packages_checked[package]
128         except KeyError:
129             pass
130
131         init_py = _build_py.check_package(self, package, package_dir)
132         self.packages_checked[package] = init_py
133
134         if not init_py or not self.distribution.namespace_packages:
135             return init_py
136
137         for pkg in self.distribution.namespace_packages:
138             if pkg==package or pkg.startswith(package+'.'):
139                 break
140         else:
141             return init_py
142
143         f = open(init_py,'rU')
144         if 'declare_namespace' not in f.read():
145             from distutils.errors import DistutilsError
146             raise DistutilsError(
147               "Namespace package problem: %s is a namespace package, but its\n"
148               "__init__.py does not call declare_namespace()! Please fix it.\n"
149               '(See the setuptools manual under "Namespace Packages" for '
150               "details.)\n" % (package,)
151             )
152         f.close()
153         return init_py
154
155     def initialize_options(self):
156         self.packages_checked={}
157         _build_py.initialize_options(self)
158
159
160
161
162
163
164
165     def exclude_data_files(self, package, src_dir, files):
166         """Filter filenames for package's data files in 'src_dir'"""
167         globs = (self.exclude_package_data.get('', [])
168                  + self.exclude_package_data.get(package, []))
169         bad = []
170         for pattern in globs:
171             bad.extend(
172                 fnmatch.filter(
173                     files, os.path.join(src_dir, convert_path(pattern))
174                 )
175             )
176         bad = dict.fromkeys(bad)
177         seen = {}
178         return [
179             f for f in files if f not in bad
180                 and f not in seen and seen.setdefault(f,1)  # ditch dupes
181         ]
182
183
184 def assert_relative(path):
185     if not os.path.isabs(path):
186         return path
187     from distutils.errors import DistutilsSetupError
188     raise DistutilsSetupError(
189 """Error: setup script specifies an absolute path:
190
191     %s
192
193 setup() arguments must *always* be /-separated paths relative to the
194 setup.py directory, *never* absolute paths.
195 """ % path
196     )
197
198
199
200
201
202
203
204
205