1 # Copyright (C) 2012 W. Trevor King
3 # This file is part of update-copyright.
5 # update-copyright is free software: you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License as
7 # published by the Free Software Foundation, either version 3 of the
8 # License, or (at your option) any later version.
10 # update-copyright is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with update-copyright. If not, see
17 # <http://www.gnu.org/licenses/>.
19 import codecs as _codecs
20 import difflib as _difflib
21 import locale as _locale
23 import os.path as _os_path
25 import textwrap as _textwrap
28 from . import LOG as _LOG
31 ENCODING = _locale.getpreferredencoding() or _sys.getdefaultencoding()
34 def long_author_formatter(copyright_year_string, authors):
36 >>> print '\\n'.join(long_author_formatter(
37 ... copyright_year_string='Copyright (C) 1990-2010',
38 ... authors=['Jack', 'Jill', 'John']))
39 Copyright (C) 1990-2010 Jack
43 lines = ['%s %s' % (copyright_year_string, authors[0])]
44 for author in authors[1:]:
45 lines.append(' '*(len(copyright_year_string)+1) + author)
48 def short_author_formatter(copyright_year_string, authors):
50 >>> print '\\n'.join(short_author_formatter(
51 ... copyright_year_string='Copyright (C) 1990-2010',
52 ... authors=['Jack', 'Jill', 'John']*5))
53 Copyright (C) 1990-2010 Jack, Jill, John, Jack, Jill, John, Jack, Jill, John, Jack, Jill, John, Jack, Jill, John
55 blurb = '%s %s' % (copyright_year_string, ', '.join(authors))
58 def copyright_string(original_year, final_year, authors, text, info={},
59 author_format_fn=long_author_formatter,
60 formatter_kwargs={}, prefix=('', '', None), wrap=True,
63 >>> print(copyright_string(original_year=2005, final_year=2005,
64 ... authors=['A <a@a.com>', 'B <b@b.edu>'],
65 ... text=['BLURB',], prefix=('# ', '# ', None),
66 ... )) # doctest: +REPORT_UDIFF
67 # Copyright (C) 2005 A <a@a.com>
71 >>> print(copyright_string(original_year=2005, final_year=2009,
72 ... authors=['A <a@a.com>', 'B <b@b.edu>'],
73 ... text=['BLURB',], prefix=('/* ', ' * ', ' */'),
74 ... )) # doctest: +REPORT_UDIFF
75 /* Copyright (C) 2005-2009 A <a@a.com>
80 >>> print(copyright_string(original_year=2005, final_year=2009,
81 ... authors=['A <a@a.com>', 'B <b@b.edu>'],
83 ... )) # doctest: +REPORT_UDIFF
84 Copyright (C) 2005-2009 A <a@a.com>
88 >>> print(copyright_string(original_year=2005, final_year=2005,
89 ... authors=['A <a@a.com>', 'B <b@b.edu>'],
90 ... text=['This file is part of %(program)s.',],
91 ... author_format_fn=short_author_formatter,
92 ... info={'program':'update-copyright'},
94 ... )) # doctest: +REPORT_UDIFF
95 Copyright (C) 2005 A <a@a.com>, B <b@b.edu>
99 >>> print(copyright_string(original_year=2005, final_year=2005,
100 ... authors=['A <a@a.com>', 'B <b@b.edu>'],
101 ... text=[('This file is part of %(program)s. '*3
103 ... info={'program':'update-copyright'},
104 ... author_format_fn=short_author_formatter,
106 ... )) # doctest: +REPORT_UDIFF
107 Copyright (C) 2005 A <a@a.com>, B <b@b.edu>
109 This file is part of update-copyright. This file is part of update-copyright. This file is part of update-copyright.
111 for key in ['initial_indent', 'subsequent_indent']:
112 if key not in wrap_kwargs:
113 wrap_kwargs[key] = prefix[1]
115 if original_year == final_year:
116 date_range = '%s' % original_year
118 date_range = '%s-%s' % (original_year, final_year)
119 copyright_year_string = 'Copyright (C) %s' % date_range
121 lines = author_format_fn(copyright_year_string, authors,
123 for i,line in enumerate(lines):
125 lines[i] = prefix[0] + line
127 lines[i] = prefix[1] + line
129 for i,paragraph in enumerate(text):
131 text[i] = paragraph % info
132 except ValueError, e:
134 "{}: can't format {} with {}".format(e, paragraph, info))
138 ('{}: copright text must be a list of paragraph strings, '
139 'not {}').format(e, repr(text)))
143 text = [_textwrap.fill(p, **wrap_kwargs) for p in text]
145 assert wrap_kwargs['subsequent_indent'] == '', \
146 wrap_kwargs['subsequent_indent']
147 sep = '\n{}\n'.format(prefix[1].rstrip())
148 ret = sep.join(['\n'.join(lines)] + text)
150 ret += ('\n{}'.format(prefix[2]))
153 def tag_copyright(contents, prefix=('# ', '# ', None), tag=None):
155 >>> contents = '''Some file
157 ... # Copyright (copyright begins)
158 ... # (copyright continues)
163 >>> print tag_copyright(contents, tag='-xyz-CR-zyx-')
170 >>> contents = '''Some file
172 ... /* Copyright (copyright begins)
173 ... * (copyright continues)
180 >>> print tag_copyright(
181 ... contents, prefix=('/* ', ' * ', ' */'), tag='-xyz-CR-zyx-')
191 start = prefix[0] + 'Copyright'
192 middle = prefix[1].rstrip()
194 for line in contents.splitlines():
195 if not incopy and line.startswith(start):
198 elif incopy and not line.startswith(middle):
200 assert line.startswith(end), line
203 lines.append(line.rstrip('\n'))
204 if incopy and end and line.startswith(end):
206 return '\n'.join(lines)+'\n'
208 def update_copyright(contents, prefix=('# ', '# ', None), tag=None, **kwargs):
210 >>> contents = '''Some file
212 ... # Copyright (copyright begins)
213 ... # (copyright continues)
218 >>> print update_copyright(
219 ... contents, original_year=2008, authors=['Jack', 'Jill'],
220 ... text=['BLURB',], prefix=('# ', '# ', None), tag='--tag--'
221 ... ) # doctest: +ELLIPSIS, +REPORT_UDIFF
224 # Copyright (C) 2008-... Jack
232 current_year = _time.gmtime()[0]
233 string = copyright_string(final_year=current_year, prefix=prefix, **kwargs)
234 contents = tag_copyright(contents=contents, prefix=prefix, tag=tag)
235 return contents.replace(tag, string)
237 def get_contents(filename, unicode=False, encoding=None):
238 if _os_path.isfile(filename):
242 f = _codecs.open(filename, 'r', encoding=encoding)
244 f = open(filename, 'r')
250 def set_contents(filename, contents, original_contents=None, unicode=False,
251 encoding=None, dry_run=False):
252 if original_contents is None:
253 original_contents = get_contents(
254 filename=filename, unicode=unicode, encoding=encoding)
255 _LOG.debug('check contents of {}'.format(filename))
256 if contents != original_contents:
257 if original_contents is None:
258 _LOG.info('creating {}'.format(filename))
260 _LOG.info('updating {}'.format(filename))
261 _LOG.debug(u'\n'.join(
262 _difflib.unified_diff(
263 original_contents.splitlines(), contents.splitlines(),
264 fromfile=_os_path.normpath(
265 _os_path.join('a', filename)),
266 tofile=_os_path.normpath(_os_path.join('b', filename)),
272 f = _codecs.open(filename, 'w', encoding=encoding)
274 f = file(filename, 'w')
277 _LOG.debug('no change in {}'.format(filename))
279 def list_files(root='.'):
280 for dirpath,dirnames,filenames in _os.walk(root):
281 for filename in filenames:
282 yield _os_path.normpath(_os_path.join(root, dirpath, filename))