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