]>
Commit | Line | Data |
---|---|---|
c368d904 RD |
1 | """my_install_data.py |
2 | ||
3 | Provides a more sophisticated facility to install data files | |
4 | than distutils' install_data does. | |
5 | You can specify your files as a template like in MANIFEST.in | |
6 | and you have more control over the copy process. | |
7 | ||
8 | """ | |
9 | ||
10 | # created 2000/08/01, Rene Liebscher <R.Liebscher@gmx.de> | |
11 | ||
12 | ########################################################################### | |
13 | # import some modules we need | |
14 | ||
15 | import os,sys,string | |
16 | from types import StringType,TupleType,ListType | |
17 | from distutils.util import change_root | |
18 | from distutils.filelist import FileList | |
19 | from distutils.command.install_data import install_data | |
20 | ||
21 | ########################################################################### | |
22 | # a container class for our more sophisticated install mechanism | |
23 | ||
24 | class Data_Files: | |
25 | """ container for list of data files. | |
26 | supports alternate base_dirs e.g. 'install_lib','install_header',... | |
27 | supports a directory where to copy files | |
28 | supports templates as in MANIFEST.in | |
29 | supports preserving of paths in filenames | |
30 | eg. foo/xyz is copied to base_dir/foo/xyz | |
31 | supports stripping of leading dirs of source paths | |
32 | eg. foo/bar1/xyz, foo/bar2/abc can be copied to bar1/xyz, bar2/abc | |
33 | """ | |
34 | ||
35 | def __init__(self,base_dir=None,files=None,copy_to=None,template=None,preserve_path=0,strip_dirs=0): | |
36 | self.base_dir = base_dir | |
37 | self.files = files | |
38 | self.copy_to = copy_to | |
39 | self.template = template | |
40 | self.preserve_path = preserve_path | |
41 | self.strip_dirs = strip_dirs | |
42 | self.finalized = 0 | |
43 | ||
44 | def warn (self, msg): | |
45 | sys.stderr.write ("warning: %s: %s\n" % | |
46 | ("install_data", msg)) | |
47 | ||
48 | def debug_print (self, msg): | |
49 | """Print 'msg' to stdout if the global DEBUG (taken from the | |
50 | DISTUTILS_DEBUG environment variable) flag is true. | |
51 | """ | |
52 | from distutils.core import DEBUG | |
53 | if DEBUG: | |
54 | print msg | |
55 | ||
56 | ||
57 | def finalize(self): | |
58 | """ complete the files list by processing the given template """ | |
59 | if self.finalized: | |
60 | return | |
61 | if self.files == None: | |
62 | self.files = [] | |
63 | if self.template != None: | |
64 | if type(self.template) == StringType: | |
65 | self.template = string.split(self.template,";") | |
66 | filelist = FileList(self.warn,self.debug_print) | |
67 | for line in self.template: | |
68 | filelist.process_template_line(string.strip(line)) | |
69 | filelist.sort() | |
70 | filelist.remove_duplicates() | |
71 | self.files.extend(filelist.files) | |
72 | self.finalized = 1 | |
73 | ||
74 | # end class Data_Files | |
75 | ||
76 | ########################################################################### | |
77 | # a more sophisticated install routine than distutils install_data | |
78 | ||
79 | class my_install_data (install_data): | |
80 | ||
81 | def check_data(self,d): | |
82 | """ check if data are in new format, if not create a suitable object. | |
83 | returns finalized data object | |
84 | """ | |
85 | if not isinstance(d, Data_Files): | |
86 | self.warn(("old-style data files list found " | |
87 | "-- please convert to Data_Files instance")) | |
88 | if type(d) is TupleType: | |
89 | if len(d) != 2 or not (type(d[1]) is ListType): | |
90 | raise DistutilsSetupError, \ | |
91 | ("each element of 'data_files' option must be an " | |
92 | "Data File instance, a string or 2-tuple (string,[strings])") | |
93 | d = Data_Files(copy_to=d[0],files=d[1]) | |
94 | else: | |
95 | if not (type(d) is StringType): | |
96 | raise DistutilsSetupError, \ | |
97 | ("each element of 'data_files' option must be an " | |
98 | "Data File instance, a string or 2-tuple (string,[strings])") | |
99 | d = Data_Files(files=[d]) | |
100 | d.finalize() | |
101 | return d | |
102 | ||
103 | def run(self): | |
104 | self.outfiles = [] | |
105 | install_cmd = self.get_finalized_command('install') | |
106 | ||
107 | for d in self.data_files: | |
108 | d = self.check_data(d) | |
109 | ||
110 | install_dir = self.install_dir | |
111 | # alternative base dir given => overwrite install_dir | |
112 | if d.base_dir != None: | |
113 | install_dir = getattr(install_cmd,d.base_dir) | |
114 | ||
115 | # copy to an other directory | |
116 | if d.copy_to != None: | |
117 | if not os.path.isabs(d.copy_to): | |
118 | # relatiev path to install_dir | |
119 | dir = os.path.join(install_dir, d.copy_to) | |
120 | elif install_cmd.root: | |
121 | # absolute path and alternative root set | |
122 | dir = change_root(self.root,d.copy_to) | |
123 | else: | |
124 | # absolute path | |
125 | dir = d.copy_to | |
126 | else: | |
127 | # simply copy to install_dir | |
128 | dir = install_dir | |
129 | # warn if necceassary | |
130 | self.warn("setup script did not provide a directory to copy files to " | |
131 | " -- installing right in '%s'" % install_dir) | |
132 | ||
133 | dir=os.path.normpath(dir) | |
134 | # create path | |
135 | self.mkpath(dir) | |
136 | ||
137 | # copy all files | |
138 | for src in d.files: | |
139 | if d.strip_dirs > 0: | |
140 | dst = string.join(string.split(os.path.normcase(src),os.sep)[d.strip_dirs:],os.sep) | |
141 | else: | |
142 | dst = src | |
143 | if d.preserve_path: | |
144 | # preserve path in filename | |
145 | self.mkpath(os.path.dirname(os.path.join(dir,dst))) | |
146 | out = self.copy_file(src, os.path.join(dir,dst)) | |
147 | else: | |
148 | out = self.copy_file(src, dir) | |
149 | if type(out) is TupleType: | |
150 | out = out[0] | |
151 | self.outfiles.append(out) | |
152 | ||
153 | return self.outfiles | |
154 | ||
155 | def get_inputs (self): | |
156 | inputs = [] | |
157 | for d in self.data_files: | |
158 | d = self.check_data(d) | |
159 | inputs.append(d.files) | |
160 | return inputs | |
161 | ||
162 | def get_outputs (self): | |
163 | return self.outfiles | |
164 | ||
165 | ||
166 | ########################################################################### | |
167 |