1 # -*- python -*- -*- encoding: Latin-1 -*-
3 __copyright__
= "Copyright (c) 2003 Terje Røsten <terjeros@phys.ntnu.no>"
5 # Extention of distutils for straw.
15 from distutils
.core
import Command
16 from distutils
.command
.build
import build
17 from distutils
.command
.install
import install
18 from distutils
.command
.install_lib
import install_lib
19 from distutils
.command
.install_data
import install_data
20 from distutils
.dep_util
import newer
21 from distutils
.util
import subst_vars
22 from distutils
.dist
import Distribution
23 from distutils
.core
import setup
25 class straw_build(build
):
26 def has_po_files(self
):
27 return self
.distribution
.has_po_files()
29 def has_desktop_file(self
):
30 return self
.distribution
.has_desktop_file()
33 sub_commands
.extend(build
.sub_commands
)
34 sub_commands
.append(('build_mo', has_po_files
))
35 sub_commands
.append(('build_desktop', has_desktop_file
))
37 class build_mo(Command
):
38 description
= 'build binary message catalog'
39 user_options
= [('build-base=', 'b', 'directory to build to')]
40 def initialize_options(self
):
41 self
.build_base
= None
44 def finalize_options(self
):
45 self
.set_undefined_options('build',
46 ('build_base', 'build_base'),
50 self
.announce('Building binary message catalog')
51 if self
.distribution
.has_po_files():
52 for mo
, po
in self
.distribution
.translations
:
53 dest
= os
.path
.normpath(self
.build_base
+ '/' + mo
)
54 self
.mkpath(os
.path
.dirname(dest
))
55 if not self
.force
and not newer(po
, dest
):
56 self
.warn("not building %s (up-to-date)" % dest
)
61 class build_desktop(Command
):
62 description
= 'builds the straw.desktop file'
63 user_options
= [('build-base=', 'b', 'directory to build to')]
64 def initialize_options(self
):
65 self
.build_base
= None
66 self
.intl_merge
= None
68 def finalize_options(self
):
69 if self
.intl_merge
is None:
70 self
.intl_merge
= commands
.getoutput('which intltool-merge')
71 if not os
.path
.exists(self
.intl_merge
):
72 sys
.exit('intltool-merge does not exist in your PATH. ' + \
73 'Make sure it exists in your PATH..')
74 self
.set_undefined_options('build',
75 ('build_base', 'build_base'))
78 self
.announce("Building straw.desktop file....")
79 if self
.distribution
.has_desktop_file():
80 for desktop
in self
.distribution
.desktop_file
:
81 dest
= os
.path
.normpath(os
.path
.join(self
.build_base
, 'share/applications'))
83 fname
= '.'.join(desktop
.split('.')[:2]) # straw.desktop.in -> straw.desktop
84 cmd
= '%s -d -u po %s %s/%s' % (self
.intl_merge
, desktop
,
86 err
, val
= commands
.getstatusoutput(cmd
)
88 sys
.exit('Unable to translate straw.desktop. %s' % err
)
90 class straw_install(install
):
93 ('sysconfdir=', None, 'specify SYSCONFDIR [default=PREFIX/etc]'),
94 ('disable-modules-check', None,
95 'do not check that necessary modules is installed'),
96 ('enable-modules-check', None,
97 'check that necessary modules is installed [default]'),
98 ('disable-schemas-install', None,
99 'do not install schema files. Setting the variable '
100 'GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL will prevent this too.'),
101 ('enable-schemas-install', None,
102 'install schema files. [default]'),
103 ('with-gconftool=', None,
104 'specify path to the gconftool executable. Can also be set by'
105 'the variable GCONFTOOL. [default=gconftool-2]' ),
106 ('with-gconf-source=', None,
107 'Config database for installing schema files. Can also be set by '
108 'the variable GCONF_SCHEMA_CONFIG_SOURCE. Setting to `auto\' is '
109 'short for `$(gconftool-2 --get-default-source)\'. '),
110 ('with-gconf-schema-file-dir=', None,
111 'Directory for installing schema files. Can also be set by the '
112 'variable GCONF_SCHEMA_FILE_DIR. [default=SYSCONFDIR/gconf/schemas]'),
113 ('with-desktop-file-dir=', None,
114 'specify directory for the straw.desktop file [default=PREFIX/share/applications')]
115 user_options
.extend(install
.user_options
)
116 user_options
.extend(_user_options
)
118 boolean_options
.extend(install
.boolean_options
)
119 boolean_options
.extend([
120 'disable-schemas-install', 'disable-modules-check' ])
124 negative_opt
.update(install
.negative_opt
)
125 except AttributeError:
127 negative_opt
.update({'enable-schemas-install' : 'disable-schemas-install',
128 'enable-modules-check' : 'disable-modules-check'})
130 def initialize_options(self
):
131 install
.initialize_options(self
)
132 #self.prefix = '/usr/local'
133 # if self.sysconfdir is not a absolute path it will
134 # be prefixed by self.prefix
135 self
.sysconfdir
= 'etc'
136 self
.disable_modules_check
= 0
137 self
.disable_schemas_install
= os
.environ
.get(
138 'GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL', 0)
139 self
.with_gconftool
= os
.environ
.get(
140 'GCONFTOOL', commands
.getoutput('which gconftool-2'))
141 self
.with_gconf_source
= os
.environ
.get(
142 'GCONF_SCHEMA_CONFIG_SOURCE', 'auto')
143 self
.with_gconf_schema_file_dir
= os
.environ
.get(
144 'GCONF_SCHEMA_FILE_DIR', None)
145 self
.with_desktop_file_dir
= 'share/applications'
147 def finalize_options(self
):
148 if self
.prefix
== 'auto':
149 cmd
= 'pkg-config --variable=prefix libgnome2.0'
150 err
, val
= commands
.getstatusoutput(cmd
)
154 sys
.exit('Cannot find prefix: %s. pkgconfig not installed?'
157 self
.sysconfdir
= os
.path
.join(self
.prefix
, self
.sysconfdir
)
159 self
.sysconfdir
= os
.path
.normpath(self
.root
+ '/' + self
.sysconfdir
)
161 self
.announce(self
.sysconfdir
)
162 if self
.root
and self
.with_gconf_schema_file_dir
:
163 self
.with_gconf_schema_file_dir
= os
.path
.normpath(
164 self
.root
+ '/' + self
.with_gconf_schema_file_dir
)
166 if not self
.disable_schemas_install
:
168 if not os
.path
.exists(self
.with_gconftool
):
169 sys
.exit('gconftool-2 executable not found in your path ' + \
170 '- should be installed with GConf')
172 if self
.with_gconf_source
== 'auto':
173 cmd
= '%s --get-default-source' % self
.with_gconftool
174 self
.with_gconf_source
= commands
.getoutput(cmd
)
176 if self
.with_gconf_source
!= 'auto' and self
.root
:
177 self
.with_gconf_source
= self
.with_gconf_source
.replace(
178 'xml::','xml::%s' % self
.root
)
179 elif not self
.with_gconf_source
:
180 fmt
= 'xml::%s/gconf/gconf.xml.defaults'
181 self
.with_gconf_source
= fmt
% self
.sysconfdir
183 # Run this after we (possibly) have changed prefix.
184 install
.finalize_options(self
)
186 def has_modules_check(self
):
187 return self
.distribution
.has_modules_check()
189 def has_config_files(self
):
190 return self
.distribution
.has_config_files()
192 def has_po_files(self
):
193 return self
.distribution
.has_po_files()
195 def has_desktop_file(self
):
196 return self
.distribution
.has_desktop_file()
198 def has_constants(self
):
199 return self
.distribution
.has_constants()
202 # Check modules before we start to install files
203 sub_commands
.append(('install_modules_check', has_modules_check
))
204 sub_commands
.extend(install
.sub_commands
)
205 sub_commands
.append(('install_mo', has_po_files
))
206 sub_commands
.append(('install_gconf', has_config_files
))
207 sub_commands
.append(('install_desktop', has_desktop_file
))
208 sub_commands
.append(('install_constants', has_constants
))
210 class install_mo(install_data
):
211 description
= 'install generated binary message catalog'
212 def initialize_options(self
):
213 self
.translations
= self
.distribution
.translations
214 self
.has_po_files
= self
.distribution
.has_po_files
215 self
.install_dir
= None
216 self
.build_dir
= None
217 self
.skip_build
= None
220 def finalize_options(self
):
221 self
.set_undefined_options('build_mo', ('build_base', 'build_dir'))
222 self
.set_undefined_options('install',
223 ('install_data', 'install_dir'),
224 ('skip_build', 'skip_build'))
226 if not self
.skip_build
:
227 self
.run_command('build_mo')
228 if self
.has_po_files():
229 for mo
, po
in self
.translations
:
230 src
= os
.path
.normpath(self
.build_dir
+ '/' + mo
)
231 if not os
.path
.isabs(mo
):
232 dest
= os
.path
.normpath(self
.install_dir
+ '/' + mo
)
234 dest
= self
.root
+ mo
237 self
.mkpath(os
.path
.dirname(dest
))
238 (out
, _
) = self
.copy_file(src
, dest
)
239 self
.outfiles
.append(out
)
241 def get_outputs (self
): return self
.outfiles
242 def get_inputs (self
): return [ po
for mo
, po
in self
.translations
]
244 class install_gconf(install_data
):
246 Same as install_data but using <sysconfdir> instead of
247 <prefix>. If <sysconfdir> is not absolute, <prefix> is prefixed
248 <sysconfdir>. If the tuple has length 3 and the option in the last
249 element is known, the value of the option is used as dest
250 directory. On the other hand if option is None, the value of the
251 option is set to value of the first element in the tuple.
253 description
= 'install generated gconf files'
256 'specify SYSCONFDIR [default=PREFIX/etc]')]
258 def initialize_options(self
):
259 self
.disable_schemas_install
= None
260 self
.sysconfdir
= None
261 self
.with_gconftool
= None
262 self
.with_gconf_source
= None
263 self
.with_gconf_schema_file_dir
= None
264 self
.config_files
= self
.distribution
.config_files
265 install_data
.initialize_options(self
)
267 def finalize_options(self
):
268 install_data
.finalize_options(self
)
269 self
.set_undefined_options(
271 ('disable_schemas_install', 'disable_schemas_install'),
272 ('with_gconftool', 'with_gconftool'),
273 ('with_gconf_source', 'with_gconf_source'),
274 ('sysconfdir','sysconfdir'),
275 ('with_gconf_schema_file_dir', 'with_gconf_schema_file_dir'))
278 def install_schema(self
):
279 schemas_dir
, schemas_file
= self
.config_files
[0]
280 schemas_idir
= os
.path
.normpath(self
.sysconfdir
+'/'+schemas_dir
)
281 self
.mkpath(schemas_idir
)
282 os
.environ
['GCONF_CONFIG_SOURCE'] = self
.with_gconf_source
283 for filepath
in schemas_file
:
284 sfile
= filepath
.split('/')[-1]
285 ofile
= os
.path
.normpath(os
.path
.join(schemas_idir
,sfile
))
286 self
.copy_file(filepath
,ofile
)
287 cmd
= '%s --makefile-install-rule %s'\
288 % (self
.with_gconftool
, ofile
)
289 err
, out
= commands
.getstatusoutput(cmd
)
293 self
.warn('Error: installation of gconf schema files failed: %s' % out
)
296 if not self
.disable_schemas_install
:
297 self
.install_schema()
299 def option_to_dir(self
):
301 for tup
in self
.config_files
:
303 data_files
.append(tup
)
305 option
= tup
[2].replace('-','_')
306 dest
= getattr(self
, option
, None)
308 data_files
.append((dest
, tup
[1]))
310 data_files
.append((tup
[0], tup
[1]))
311 dest
= os
.path
.normpath(self
.sysconfdir
+ '/' + tup
[0])
312 setattr(self
, option
, dest
)
313 self
.config_files
= data_files
315 def get_outputs(self
): return []
316 def get_inputs(self
): return []
318 class install_modules_check(Command
):
319 description
= 'check that all necessary Python modules are installed'
321 ('disable-modules-check', None,
322 'do not check that necessary modules is installed'),
323 ('enable-modules-check', None,
324 'check that necessary modules is installed [default]')]
326 boolean_options
.append('disable-modules-check')
327 negative_opt
= {'enable-modules-check' : 'disable-modules-check'}
329 def initialize_options(self
):
330 self
.disable_modules_check
= None
331 self
.modules_check
= self
.distribution
.modules_check
333 def finalize_options(self
):
334 self
.set_undefined_options(
336 ('disable_modules_check', 'disable_modules_check'))
339 if self
.disable_modules_check
:
340 self
.announce('Modules not checked')
341 elif self
.modules_check
:
343 self
.announce('All nescessary modules installed')
345 def get_outputs(self
): return []
346 def get_inputs(self
): return []
348 class install_desktop(install_data
):
349 description
= 'Installs generated desktop file'
351 ('with-desktop-file-dir=', None,
352 'specify directory for the straw.desktop file [default=PREFIX/share/applications]')]
354 def initialize_options(self
):
356 self
.build_dir
= None
357 self
.install_dir
= None
358 self
.skip_build
= None
359 self
.with_desktop_file_dir
= None
361 def finalize_options(self
):
362 self
.set_undefined_options('build_desktop', ('build_base', 'build_dir'))
363 self
.set_undefined_options('install',('install_data','install_dir'),
364 ('skip_build', 'skip_build'),
365 ('with_desktop_file_dir','with_desktop_file_dir'))
368 if not self
.skip_build
: self
.run_command('build_desktop')
369 src
= os
.path
.normpath(os
.path
.join(
370 self
.build_dir
, 'share/applications/straw.desktop'))
371 dest
= os
.path
.normpath(self
.install_dir
+ '/' + self
.with_desktop_file_dir
)
373 (out
, _
) = self
.copy_file(src
, dest
)
374 self
.outfiles
.append(out
)
376 def get_outputs (self
): return self
.outfiles
377 def get_inputs (self
):
378 return (os
.path
.join(self
.build_dir
, 'share/applications/straw.desktop'))
380 class translate(Command
):
381 description
= 'update .pot file and merge po files'
382 user_options
= [('pot', 'p', 'only update the pot file (no merge)')]
383 user_options
.extend([('dist=', 'd','Merge LANGCODE.po with existing PO template.')])
384 boolean_options
= ['pot']
386 def initialize_options(self
):
387 self
.intl_update
= None
392 def finalize_options(self
):
393 if not self
.intl_update
:
394 self
.intl_update
= commands
.getoutput('which intltool-update')
395 if not os
.path
.exists(self
.intl_update
):
396 sys
.exit('intltool-update does not exist in your PATH. ' + \
397 'Make sure it exists in your PATH..')
399 if not self
.pot_file
:
400 self
.distribution
.pot_file
401 if self
.pot
and self
.dist
:
402 sys
.exit('You can only specify one option at time...\n' + \
403 "'python setup.py translate --help' for more info")
406 # intltool-update needs to be run inside po/
407 if os
.path
.exists('./po/'):
410 sys
.exit('po/ directory not found.. not continuing...')
413 cmd
= '%s --pot' % self
.intl_update
414 err
, val
= commands
.getstatusoutput(cmd
)
417 sys
.exit('Error generating template file %s' % self
.pot_file
)
420 cmd
= '%s %s' % (self
.intl_update
, self
.dist
)
421 err
, val
= commands
.getstatusoutput(cmd
)
424 sys
.exit('Error merging %s.po with %s' % (self
.dist
,self
.pot_file
))
427 class install_constants(install_lib
):
428 description
= "Installs and substitutes file paths and other constants in constants.py.in"
429 def initialize_options(self
):
430 self
.build_dir
= None
431 self
.install_lib
= None
433 self
.build_dict
= None
434 install_lib
.initialize_options(self
)
436 def finalize_options(self
):
437 install_lib
.finalize_options(self
)
438 self
.set_undefined_options('install',
439 ('install_lib','install_lib'),
440 ('prefix','prefix'),)
441 self
.build_dict
= {'libdir': os
.path
.normpath(os
.path
.join(self
.install_lib
,'straw')),
442 'datadir': os
.path
.normpath(os
.path
.join(self
.prefix
,'share'))}
445 self
.announce("building constants.py...")
447 install_lib
.run(self
)
449 def fix_constants(self
):
450 if self
.distribution
.has_constants():
451 for fname
,vars_dict
in self
.distribution
.constants
:
452 vars_dict
.update(self
.build_dict
)
456 sfname
= '.'.join(fname
.split('.')[:2]) # foo.py.in -> foo.py
457 f
= open(os
.path
.normpath(os
.path
.join(self
.build_dir
, 'straw', sfname
)),'w')
458 f
.write(subst_vars(cdata
, vars_dict
))
460 self
.announce("... done.")
462 class StrawDistribution(Distribution
):
463 def __init__(self
, attrs
= None):
464 self
.modules_check
= 0
465 self
.msg_sources
= None
467 self
.translations
= []
468 self
.config_files
= []
469 self
.desktop_file
= []
471 self
.ext_modules
= []
472 Distribution
.__init
__(self
, attrs
)
474 'install_modules_check' : install_modules_check
,
475 'build' : straw_build
,
476 'build_mo' : build_mo
,
477 'translate' : translate
,
478 'build_desktop': build_desktop
,
479 'install' : straw_install
,
480 'install_mo' : install_mo
,
481 'install_desktop' : install_desktop
,
482 'install_constants': install_constants
,
483 'install_gconf' : install_gconf
}
485 def has_po_files(self
): return len(self
.translations
) > 0
486 def has_modules_check(self
): return isinstance(self
.modules_check
, types
.FunctionType
)
487 def has_config_files(self
): return len(self
.config_files
) > 0
488 def has_desktop_file(self
): return len(self
.desktop_file
) > 0
489 def has_constants(self
): return len(self
.constants
) > 0
492 from distutils
.core
import setup
493 kwds
['distclass'] = StrawDistribution