44# minimally patched to make it even more xgettext compatible
55# by Peter Funk <[email protected] > 66
7- """pygettext -- Python equivalent of xgettext(1)
7+ # for selftesting
8+ try :
9+ import fintl
10+ _ = fintl .gettext
11+ except ImportError :
12+ def _ (s ): return s
13+
14+
15+ __doc__ = _ ("""pygettext -- Python equivalent of xgettext(1)
816
917Many systems (Solaris, Linux, Gnu) provide extensive tools that ease the
1018internationalization of C programs. Most of these tools are independent of
3947
4048NOTE: pygettext attempts to be option and feature compatible with GNU xgettext
4149where ever possible. However some options are still missing or are not fully
42- implemented.
50+ implemented. Also, xgettext's use of command line switches with option
51+ arguments is broken, and in these cases, pygettext just defines additional
52+ switches.
4353
44- Usage: pygettext [options] filename ...
54+ Usage: pygettext [options] inputfile ...
4555
4656Options:
4757
6171 --help
6272 print this help message and exit
6373
64- -k [word]
65- --keyword[=word]
66- Additional keywords to look for. Without `word' means not to use the
67- default keywords. The default keywords, which are always looked for
68- if not explicitly disabled: _
74+ -k word
75+ --keyword=word
76+ Keywords to look for in addition to the default set, which are:
77+ %(DEFAULTKEYWORDS)s
78+
79+ You can have multiple -k flags on the command line.
6980
70- The default keyword list is different than GNU xgettext. You can have
71- multiple -k flags on the command line.
81+ -K
82+ --no-default-keywords
83+ Disable the default set of keywords (see above). Any keywords
84+ explicitly added with the -k/--keyword option are still recognized.
7285
7386 --no-location
74- Do not write filename/lineno location comments
87+ Do not write filename/lineno location comments.
7588
76- -n [style]
77- --add-location[=style]
89+ -n
90+ --add-location
7891 Write filename/lineno location comments indicating where each
7992 extracted string is found in the source. These lines appear before
80- each msgid. Two styles are supported:
93+ each msgid. The style of comments is controlled by the -S/--style
94+ option. This is the default.
95+
96+ -S stylename
97+ --style stylename
98+ Specify which style to use for location comments. Two styles are
99+ supported:
81100
82101 Solaris # File: filename, line: line-number
83- Gnu #: filename:line
102+ GNU #: filename:line
84103
85- If style is omitted, Gnu is used. The style name is case
86- insensitive. By default, locations are included.
104+ The style name is case insensitive. GNU style is the default.
87105
88106 -o filename
89107 --output=filename
90- Rename the default output file from messages.pot to filename.
108+ Rename the default output file from messages.pot to filename. If
109+ filename is `-' then the output is sent to standard out.
91110
92111 -p dir
93112 --output-dir=dir
111130 extracted from the input files. Each string to be excluded must
112131 appear on a line by itself in the file.
113132
114- """
133+ If `inputfile' is -, standard input is read.
134+
135+ """ )
115136
116137import os
117138import sys
118- import string
119139import time
120140import getopt
121141import tokenize
122142
123- __version__ = '1.0 '
143+ __version__ = '1.1 '
124144
145+ default_keywords = ['_' ]
146+ DEFAULTKEYWORDS = ', ' .join (default_keywords )
125147
126-
127- # for selftesting
128- try :
129- import fintl
130- _ = fintl .gettext
131- except ImportError :
132- def _ (s ): return s
148+ EMPTYSTRING = ''
133149
134150
151+
135152# The normal pot-file header. msgmerge and EMACS' po-mode work better if
136153# it's there.
137154pot_header = _ ('''\
@@ -189,7 +206,7 @@ def escape(s):
189206 s = list (s )
190207 for i in range (len (s )):
191208 s [i ] = escapes [ord (s [i ])]
192- return string .join (s , '' )
209+ return EMPTYSTRING .join (s )
193210
194211
195212def safe_eval (s ):
@@ -200,7 +217,7 @@ def safe_eval(s):
200217def normalize (s ):
201218 # This converts the various Python string types into a format that is
202219 # appropriate for .po files, namely much closer to C style.
203- lines = string .split (s , '\n ' )
220+ lines = s .split ('\n ' )
204221 if len (lines ) == 1 :
205222 s = '"' + escape (s ) + '"'
206223 else :
@@ -209,7 +226,8 @@ def normalize(s):
209226 lines [- 1 ] = lines [- 1 ] + '\n '
210227 for i in range (len (lines )):
211228 lines [i ] = escape (lines [i ])
212- s = '""\n "' + string .join (lines , '\\ n"\n "' ) + '"'
229+ lineterm = '\\ n"\n "'
230+ s = '""\n "' + lineterm .join (lines ) + '"'
213231 return s
214232
215233
@@ -245,7 +263,7 @@ def __openseen(self, ttype, tstring, lineno):
245263 # of messages seen. Reset state for the next batch. If there
246264 # were no strings inside _(), then just ignore this entry.
247265 if self .__data :
248- msg = string .join (self .__data , '' )
266+ msg = EMPTYSTRING .join (self .__data )
249267 if not msg in self .__options .toexclude :
250268 entry = (self .__curfile , self .__lineno )
251269 linenos = self .__messages .get (msg )
@@ -271,12 +289,14 @@ def write(self, fp):
271289 # as that generated by xgettext...
272290 print pot_header % {'time' : timestamp , 'version' : __version__ }
273291 for k , v in self .__messages .items ():
292+ if not options .writelocations :
293+ pass
274294 # location comments are different b/w Solaris and GNU:
275- if options .location == options .SOLARIS :
295+ elif options .locationstyle == options .SOLARIS :
276296 for filename , lineno in v :
277297 d = {'filename' : filename , 'lineno' : lineno }
278298 print _ ('# File: %(filename)s, line: %(lineno)d' ) % d
279- elif options .location == options .GNU :
299+ elif options .locationstyle == options .GNU :
280300 # fit as many locations on one line, as long as the
281301 # resulting line length doesn't exceeds 'options.width'
282302 locline = '#:'
@@ -298,14 +318,15 @@ def write(self, fp):
298318
299319
300320def main ():
301- default_keywords = [ '_' ]
321+ global default_keywords
302322 try :
303323 opts , args = getopt .getopt (
304324 sys .argv [1 :],
305- 'ad:Ehk:n:o:p:Vvw:x:' ,
306- ['extract-all' , 'default-domain' , 'escape' , 'help' , 'keyword' ,
325+ 'ad:Ehk:Kno:p:S:Vvw:x:' ,
326+ ['extract-all' , 'default-domain' , 'escape' , 'help' ,
327+ 'keyword=' , 'no-default-keywords' ,
307328 'add-location' , 'no-location' , 'output=' , 'output-dir=' ,
308- 'verbose' , 'version' , 'width=' , 'exclude-file=' ,
329+ 'style=' , ' verbose' , 'version' , 'width=' , 'exclude-file=' ,
309330 ])
310331 except getopt .error , msg :
311332 usage (1 , msg )
@@ -321,7 +342,8 @@ class Options:
321342 keywords = []
322343 outpath = ''
323344 outfile = 'messages.pot'
324- location = GNU
345+ writelocations = 1
346+ locationstyle = GNU
325347 verbose = 0
326348 width = 78
327349 excludefilename = ''
@@ -342,19 +364,17 @@ class Options:
342364 elif opt in ('-E' , '--escape' ):
343365 options .escape = 1
344366 elif opt in ('-k' , '--keyword' ):
345- if arg is None :
346- default_keywords = []
347367 options .keywords .append (arg )
368+ elif opt in ('-K' , '--no-default-keywords' ):
369+ default_keywords = []
348370 elif opt in ('-n' , '--add-location' ):
349- if arg is None :
350- arg = 'gnu'
351- try :
352- options .location = locations [string .lower (arg )]
353- except KeyError :
354- d = {'arg' :arg }
355- usage (1 , _ ('Invalid value for --add-location: %(arg)s' ) % d )
371+ options .writelocations = 1
356372 elif opt in ('--no-location' ,):
357- options .location = 0
373+ options .writelocations = 0
374+ elif opt in ('-S' , '--style' ):
375+ options .locationstyle = locations .get (arg .lower ())
376+ if options .locationstyle is None :
377+ usage (1 , _ ('Invalid value for --style: %s' ) % arg )
358378 elif opt in ('-o' , '--output' ):
359379 options .outfile = arg
360380 elif opt in ('-p' , '--output-dir' ):
@@ -368,9 +388,7 @@ class Options:
368388 try :
369389 options .width = int (arg )
370390 except ValueError :
371- d = {'arg' :arg }
372- usage (1 , _ ('Invalid value for --width: %(arg)s, must be int' )
373- % d )
391+ usage (1 , _ ('--width argument must be an integer: %s' ) % arg )
374392 elif opt in ('-x' , '--exclude-file' ):
375393 options .excludefilename = arg
376394
@@ -396,19 +414,37 @@ class Options:
396414 # slurp through all the files
397415 eater = TokenEater (options )
398416 for filename in args :
399- if options .verbose :
400- print _ ('Working on %(filename)s' ) % {'filename' :filename }
401- fp = open (filename )
402- eater .set_filename (filename )
403- tokenize .tokenize (fp .readline , eater )
404- fp .close ()
405-
406- if options .outpath :
407- options .outfile = os .path .join (options .outpath , options .outfile )
408- fp = open (options .outfile , 'w' )
409- eater .write (fp )
410- fp .close ()
417+ if filename == '-' :
418+ if options .verbose :
419+ print _ ('Reading standard input' )
420+ fp = sys .stdin
421+ closep = 0
422+ else :
423+ if options .verbose :
424+ print _ ('Working on %s' ) % filename
425+ fp = open (filename )
426+ closep = 1
427+ try :
428+ eater .set_filename (filename )
429+ tokenize .tokenize (fp .readline , eater )
430+ finally :
431+ if closep :
432+ fp .close ()
411433
434+ # write the output
435+ if options .outfile == '-' :
436+ fp = sys .stdout
437+ closep = 0
438+ else :
439+ if options .outpath :
440+ options .outfile = os .path .join (options .outpath , options .outfile )
441+ fp = open (options .outfile , 'w' )
442+ closep = 1
443+ try :
444+ eater .write (fp )
445+ finally :
446+ if closep :
447+ fp .close ()
412448
413449
414450if __name__ == '__main__' :
0 commit comments