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='', 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='# '
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>'],
74 ... )) # doctest: +REPORT_UDIFF
75 Copyright (C) 2005-2009 A <a@a.com>
79 >>> print(copyright_string(original_year=2005, final_year=2005,
80 ... authors=['A <a@a.com>', 'B <b@b.edu>'],
81 ... text=['This file is part of %(program)s.',],
82 ... author_format_fn=short_author_formatter,
83 ... info={'program':'update-copyright'},
85 ... )) # doctest: +REPORT_UDIFF
86 Copyright (C) 2005 A <a@a.com>, B <b@b.edu>
90 >>> print(copyright_string(original_year=2005, final_year=2005,
91 ... authors=['A <a@a.com>', 'B <b@b.edu>'],
92 ... text=[('This file is part of %(program)s. '*3
94 ... info={'program':'update-copyright'},
95 ... author_format_fn=short_author_formatter,
97 ... )) # doctest: +REPORT_UDIFF
98 Copyright (C) 2005 A <a@a.com>, B <b@b.edu>
100 This file is part of update-copyright. This file is part of update-copyright. This file is part of update-copyright.
102 for key in ['initial_indent', 'subsequent_indent']:
103 if key not in wrap_kwargs:
104 wrap_kwargs[key] = prefix
106 if original_year == final_year:
107 date_range = '%s' % original_year
109 date_range = '%s-%s' % (original_year, final_year)
110 copyright_year_string = 'Copyright (C) %s' % date_range
112 lines = author_format_fn(copyright_year_string, authors,
114 for i,line in enumerate(lines):
115 lines[i] = prefix + line
117 for i,paragraph in enumerate(text):
119 text[i] = paragraph % info
120 except ValueError, e:
122 "{}: can't format {} with {}".format(e, paragraph, info))
126 ('{}: copright text must be a list of paragraph strings, '
127 'not {}').format(e, repr(text)))
131 text = [_textwrap.fill(p, **wrap_kwargs) for p in text]
133 assert wrap_kwargs['subsequent_indent'] == '', \
134 wrap_kwargs['subsequent_indent']
135 sep = '\n%s\n' % prefix.rstrip()
136 return sep.join(['\n'.join(lines)] + text)
138 def tag_copyright(contents, tag=None):
140 >>> contents = '''Some file
142 ... # Copyright (copyright begins)
143 ... # (copyright continues)
148 >>> print tag_copyright(contents, tag='-xyz-CR-zyx-')
158 for line in contents.splitlines():
159 if incopy == False and line.startswith('# Copyright'):
162 elif incopy == True and not line.startswith('#'):
165 lines.append(line.rstrip('\n'))
166 return '\n'.join(lines)+'\n'
168 def update_copyright(contents, tag=None, **kwargs):
170 >>> contents = '''Some file
172 ... # Copyright (copyright begins)
173 ... # (copyright continues)
178 >>> print update_copyright(contents, original_year=2008,
179 ... authors=['Jack', 'Jill'],
180 ... text=['BLURB',], prefix='# ', tag='--tag--'
181 ... ) # doctest: +ELLIPSIS, +REPORT_UDIFF
184 # Copyright (C) 2008-... Jack
192 current_year = _time.gmtime()[0]
193 string = copyright_string(final_year=current_year, **kwargs)
194 contents = tag_copyright(contents=contents, tag=tag)
195 return contents.replace(tag, string)
197 def get_contents(filename, unicode=False, encoding=None):
198 if _os_path.isfile(filename):
202 f = _codecs.open(filename, 'r', encoding=encoding)
204 f = open(filename, 'r')
210 def set_contents(filename, contents, original_contents=None, unicode=False,
211 encoding=None, dry_run=False):
212 if original_contents is None:
213 original_contents = get_contents(
214 filename=filename, unicode=unicode, encoding=encoding)
215 _LOG.debug('check contents of {}'.format(filename))
216 if contents != original_contents:
217 if original_contents is None:
218 _LOG.info('creating {}'.format(filename))
220 _LOG.info('updating {}'.format(filename))
221 _LOG.debug(u'\n'.join(
222 _difflib.unified_diff(
223 original_contents.splitlines(), contents.splitlines(),
224 fromfile=_os_path.normpath(
225 _os_path.join('a', filename)),
226 tofile=_os_path.normpath(_os_path.join('b', filename)),
232 f = _codecs.open(filename, 'w', encoding=encoding)
234 f = file(filename, 'w')
237 _LOG.debug('no change in {}'.format(filename))
239 def list_files(root='.'):
240 for dirpath,dirnames,filenames in _os.walk(root):
241 for filename in filenames:
242 yield _os_path.normpath(_os_path.join(root, dirpath, filename))