1 # Copyright (C) 2012 W. Trevor King <wking@tremily.us>
3 # This file is part of update-copyright.
5 # update-copyright is free software: you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by the Free
7 # Software Foundation, either version 3 of the License, or (at your option) any
10 # update-copyright is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 # You should have received a copy of the GNU General Public License along with
16 # update-copyright. If not, see <http://www.gnu.org/licenses/>.
18 import codecs as _codecs
19 import difflib as _difflib
20 import locale as _locale
22 import os.path as _os_path
24 import textwrap as _textwrap
27 from . import LOG as _LOG
30 ENCODING = _locale.getpreferredencoding() or _sys.getdefaultencoding()
33 def long_author_formatter(copyright_year_string, authors):
35 >>> print '\\n'.join(long_author_formatter(
36 ... copyright_year_string='Copyright (C) 1990-2010',
37 ... authors=['Jack', 'Jill', 'John']))
38 Copyright (C) 1990-2010 Jack
42 lines = ['%s %s' % (copyright_year_string, authors[0])]
43 for author in authors[1:]:
44 lines.append(' '*(len(copyright_year_string)+1) + author)
47 def short_author_formatter(copyright_year_string, authors):
49 >>> print '\\n'.join(short_author_formatter(
50 ... copyright_year_string='Copyright (C) 1990-2010',
51 ... authors=['Jack', 'Jill', 'John']*5))
52 Copyright (C) 1990-2010 Jack, Jill, John, Jack, Jill, John, Jack, Jill, John, Jack, Jill, John, Jack, Jill, John
54 blurb = '%s %s' % (copyright_year_string, ', '.join(authors))
57 def copyright_string(original_year, final_year, authors, text, info={},
58 author_format_fn=long_author_formatter,
59 formatter_kwargs={}, prefix=('', '', None), wrap=True,
62 >>> print(copyright_string(original_year=2005, final_year=2005,
63 ... authors=['A <a@a.com>', 'B <b@b.edu>'],
64 ... text=['BLURB',], prefix=('# ', '# ', None),
65 ... )) # doctest: +REPORT_UDIFF
66 # Copyright (C) 2005 A <a@a.com>
70 >>> print(copyright_string(original_year=2005, final_year=2009,
71 ... authors=['A <a@a.com>', 'B <b@b.edu>'],
72 ... text=['BLURB',], prefix=('/* ', ' * ', ' */'),
73 ... )) # doctest: +REPORT_UDIFF
74 /* Copyright (C) 2005-2009 A <a@a.com>
79 >>> print(copyright_string(original_year=2005, final_year=2009,
80 ... authors=['A <a@a.com>', 'B <b@b.edu>'],
82 ... )) # doctest: +REPORT_UDIFF
83 Copyright (C) 2005-2009 A <a@a.com>
87 >>> print(copyright_string(original_year=2005, final_year=2005,
88 ... authors=['A <a@a.com>', 'B <b@b.edu>'],
89 ... text=['This file is part of %(program)s.',],
90 ... author_format_fn=short_author_formatter,
91 ... info={'program':'update-copyright'},
93 ... )) # doctest: +REPORT_UDIFF
94 Copyright (C) 2005 A <a@a.com>, B <b@b.edu>
98 >>> print(copyright_string(original_year=2005, final_year=2005,
99 ... authors=['A <a@a.com>', 'B <b@b.edu>'],
100 ... text=[('This file is part of %(program)s. '*3
102 ... info={'program':'update-copyright'},
103 ... author_format_fn=short_author_formatter,
105 ... )) # doctest: +REPORT_UDIFF
106 Copyright (C) 2005 A <a@a.com>, B <b@b.edu>
108 This file is part of update-copyright. This file is part of update-copyright. This file is part of update-copyright.
110 for key in ['initial_indent', 'subsequent_indent']:
111 if key not in wrap_kwargs:
112 wrap_kwargs[key] = prefix[1]
114 if original_year == final_year:
115 date_range = '%s' % original_year
117 date_range = '%s-%s' % (original_year, final_year)
118 copyright_year_string = 'Copyright (C) %s' % date_range
120 lines = author_format_fn(copyright_year_string, authors,
122 for i,line in enumerate(lines):
124 lines[i] = prefix[0] + line
126 lines[i] = prefix[1] + line
128 for i,paragraph in enumerate(text):
130 text[i] = paragraph % info
131 except ValueError, e:
133 "{}: can't format {} with {}".format(e, paragraph, info))
137 ('{}: copright text must be a list of paragraph strings, '
138 'not {}').format(e, repr(text)))
142 text = [_textwrap.fill(p, **wrap_kwargs) for p in text]
144 assert wrap_kwargs['subsequent_indent'] == '', \
145 wrap_kwargs['subsequent_indent']
146 sep = '\n{}\n'.format(prefix[1].rstrip())
147 ret = sep.join(['\n'.join(lines)] + text)
149 ret += ('\n{}'.format(prefix[2]))
152 def tag_copyright(contents, prefix=('# ', '# ', None), tag=None):
154 >>> contents = '''Some file
156 ... # Copyright (copyright begins)
157 ... # (copyright continues)
162 >>> print tag_copyright(contents, tag='-xyz-CR-zyx-')
169 >>> contents = '''Some file
171 ... /* Copyright (copyright begins)
172 ... * (copyright continues)
179 >>> print tag_copyright(
180 ... contents, prefix=('/* ', ' * ', ' */'), tag='-xyz-CR-zyx-')
190 start = prefix[0] + 'Copyright'
191 middle = prefix[1].rstrip()
193 for line in contents.splitlines():
194 if not incopy and line.startswith(start):
197 elif incopy and not line.startswith(middle):
199 assert line.startswith(end), line
202 lines.append(line.rstrip('\n'))
203 if incopy and end and line.startswith(end):
205 return '\n'.join(lines)+'\n'
207 def update_copyright(contents, prefix=('# ', '# ', None), tag=None, **kwargs):
209 >>> contents = '''Some file
211 ... # Copyright (copyright begins)
212 ... # (copyright continues)
217 >>> print update_copyright(
218 ... contents, original_year=2008, authors=['Jack', 'Jill'],
219 ... text=['BLURB',], prefix=('# ', '# ', None), tag='--tag--'
220 ... ) # doctest: +ELLIPSIS, +REPORT_UDIFF
223 # Copyright (C) 2008-... Jack
231 current_year = _time.gmtime()[0]
232 string = copyright_string(final_year=current_year, prefix=prefix, **kwargs)
233 contents = tag_copyright(contents=contents, prefix=prefix, tag=tag)
234 return contents.replace(tag, string)
236 def get_contents(filename, unicode=False, encoding=None):
237 if _os_path.isfile(filename):
241 f = _codecs.open(filename, 'r', encoding=encoding)
243 f = open(filename, 'r')
249 def set_contents(filename, contents, original_contents=None, unicode=False,
250 encoding=None, dry_run=False):
251 if original_contents is None:
252 original_contents = get_contents(
253 filename=filename, unicode=unicode, encoding=encoding)
254 _LOG.debug('check contents of {}'.format(filename))
255 if contents != original_contents:
256 if original_contents is None:
257 _LOG.info('creating {}'.format(filename))
259 _LOG.info('updating {}'.format(filename))
260 _LOG.debug(u'\n'.join(
261 _difflib.unified_diff(
262 original_contents.splitlines(), contents.splitlines(),
263 fromfile=_os_path.normpath(
264 _os_path.join('a', filename)),
265 tofile=_os_path.normpath(_os_path.join('b', filename)),
271 f = _codecs.open(filename, 'w', encoding=encoding)
273 f = file(filename, 'w')
276 _LOG.debug('no change in {}'.format(filename))
278 def list_files(root='.'):
279 for dirpath,dirnames,filenames in _os.walk(root):
280 for filename in filenames:
281 yield _os_path.normpath(_os_path.join(root, dirpath, filename))