2
# -*- coding: utf-8 -*-
3
# Copyright 2009 Didier Roche
5
# This file is part of Quickly ubuntu-application template
7
#This program is free software: you can redistribute it and/or modify it
8
#under the terms of the GNU General Public License version 3, as published
9
#by the Free Software Foundation.
11
#This program is distributed in the hope that it will be useful, but
12
#WITHOUT ANY WARRANTY; without even the implied warranties of
13
#MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14
#PURPOSE. See the GNU General Public License for more details.
16
#You should have received a copy of the GNU General Public License along
17
#with this program. If not, see <http://www.gnu.org/licenses/>.
26
from quickly import configurationhandler, templatetools
27
from internal import quicklyutils
30
from gettext import gettext as _
32
gettext.textdomain('quickly')
34
class LicenceError(Exception):
35
def __init__(self, msg):
40
BEGIN_LICENCE_TAG = '### BEGIN LICENSE'
41
END_LICENCE_TAG = '### END LICENSE'
46
$quickly license <Your_Licence>
48
Adds license to project files. Before using this command, you should:
50
1. Edit the file AUTHORS to include your authorship (this step is automatically done
51
if you directly launch "$ quickly release" or "$ quickly share" before changing license)
52
In this case, license is GPL-3 by default.
53
2. If you want to put your own quickly unsupported Licence, add a COPYING file containing
55
3. Executes either $ quickly license or $ quickly license <License>
56
where <License> can be either:
60
This will modify the Copyright file with the chosen licence (with GPL-3 by default).
61
Updating previous chosen Licence if needed.
62
If you previously removed the tags to add your own licence, it will leave it pristine.
63
If no name is attributed to the Copyright, it will try to retrieve it from Launchpad
64
(in quickly release or quickly share command only)
66
Finally, this will copy the Copyright at the head of every files.
68
Note that if you don't run quickly licence before calling quickly release or quickly
69
share, this one will execute it for you and guess the copyright holder from your
70
launchpad account if you didn't update it.
73
def get_supported_licenses():
74
"""Get supported licenses"""
76
available_licenses = []
78
for license_file in os.listdir(os.path.dirname(__file__) + "/available_licenses"):
79
result = re.split("header_(.*)", license_file)
81
available_licenses.append(result[1])
83
return available_licenses
86
def copy_license_to_files(license_content):
87
"""Copy license header to every .py files"""
89
# get the project name
90
if not configurationhandler.project_config:
91
configurationhandler.loadConfig()
92
project_name = configurationhandler.project_config['project']
94
# open each python file and main bin file
95
for root, dirs, files in os.walk('./'):
97
if name.endswith('.py') or os.path.join(root, name) == "./bin/" + project_name:
98
skip_until_end_found = False
100
target_file_name = os.path.join(root, name)
101
ftarget_file_name = file(target_file_name, 'r')
102
ftarget_file_name_out = file(ftarget_file_name.name + '.new', 'w')
103
for line in ftarget_file_name:
104
# seek if we have to add or Replace a License
105
if BEGIN_LICENCE_TAG in line:
106
ftarget_file_name_out.write(line) # write this line, otherwise will be skipped
107
skip_until_end_found = True
108
ftarget_file_name_out.write(license_content)
110
if END_LICENCE_TAG in line:
111
skip_until_end_found = False
113
if not skip_until_end_found:
114
ftarget_file_name_out.write(line)
116
ftarget_file_name.close()
117
ftarget_file_name_out.close()
119
if skip_until_end_found: # that means we didn't find the END_LICENCE_TAG, don't copy the file
120
print _("WARNING: %s was not found in the file %s. No licence replacement") % (END_LICENCE_TAG, ftarget_file_name.name)
121
os.remove(ftarget_file_name_out.name)
123
templatetools.apply_file_rights(ftarget_file_name.name, ftarget_file_name_out.name)
124
os.rename(ftarget_file_name_out.name, ftarget_file_name.name)
126
except (OSError, IOError), e:
127
msg = _("%s file was not found") % fcopyright_name
128
raise LicenceError(msg)
131
def licensing(license=None):
132
"""Add license or update it to the project files
137
fauthors_name = "AUTHORS"
138
flicense_name = "COPYING"
140
if not configurationhandler.project_config:
141
configurationhandler.loadConfig()
142
project_name = configurationhandler.project_config['project']
143
python_name = templatetools.python_name(project_name)
145
# check if we have a license tag in setup.py otherwise, default to GPL-3
148
license = quicklyutils.get_setup_value('license')
149
except quicklyutils.cant_deal_with_setup_value:
151
if license is None or license == '':
154
# get Copyright holders in AUTHORS file
157
for line in file(fauthors_name, 'r'):
158
if "<Your Name> <Your E-mail>" in line:
159
# if we have an author in setup.py, grab it
161
author = quicklyutils.get_setup_value('author')
162
author_email = quicklyutils.get_setup_value('author_email')
163
line = "Copyright (C) %s %s <%s>\n" % (datetime.datetime.now().year, author, author_email)
164
# update AUTHORS file
165
fout = file('%s.new' % fauthors_name, 'w')
169
os.rename(fout.name, fauthors_name)
170
except quicklyutils.cant_deal_with_setup_value:
171
msg = _('Copyright is not attributed. ' \
172
'Edit the AUTHORS file to include your name for the copyright replacing ' \
173
'<Your Name> <Your E-mail>. Update it in setup.py or use quickly share/quickly release ' \
174
'to fill it automatically')
175
raise LicenceError(msg)
176
license_content += "# %s" % line
177
except (OSError, IOError), e:
178
msg = _("%s file was not found") % fauthors_name
179
raise LicenceError(msg)
181
# add header to license_content
182
# check that COPYING file is provided if using a personal license
183
supported_licenses_list = get_supported_licenses()
184
if license in supported_licenses_list:
185
header_file_path = os.path.dirname(__file__) + "/available_licenses/header_" + license
187
header_file_path = flicense_name
189
for line in file(header_file_path, 'r'):
190
license_content += "# %s" % line
191
except (OSError, IOError), e:
192
if header_file_path == flicense_name:
193
msg = _("%s file was not found. It is compulsory for user defined license") % flicense_name
195
msg = _("Header of %s license not found. Quickly installation corrupted?") % header_file_path
196
raise LicenceError(msg)
199
# update license in config.py, setup.py and refresh COPYING if needed
201
config_file = '%s/%sconfig.py' % (python_name, python_name)
202
for line in file(config_file, 'r'):
203
fields = line.split(' = ') # Separate variable from value
204
if fields[0] == '__license__' and fields[1].strip() != "'%s'" % license:
205
fin = file(config_file, 'r')
206
fout = file(fin.name + '.new', 'w')
207
for line_input in fin:
208
fields = line_input.split(' = ') # Separate variable from value
209
if fields[0] == '__license__':
210
line_input = "%s = '%s'\n" % (fields[0], license)
211
fout.write(line_input)
215
os.rename(fout.name, fin.name)
216
if license in supported_licenses_list:
217
src_license_file = "/usr/share/common-licenses/" + license
218
if os.path.isfile(src_license_file):
219
shutil.copy("/usr/share/common-licenses/" + license, flicense_name)
222
quicklyutils.set_setup_value('license', license)
223
except quicklyutils.cant_deal_with_setup_value:
224
msg = _("Can't update license in setup.py file\n")
225
raise LicenceError(msg)
226
except (OSError, IOError), e:
227
msg = _("%s/%sconfig.py file not found.") % (python_name, python_name)
228
raise LicenceError(msg)
230
# update About dialog, if present:
231
about_dialog_file_name = quicklyutils.get_about_file_name()
232
if about_dialog_file_name:
233
copyright_holders = ""
235
# get copyright holders and authors
236
for line in file(fauthors_name, 'r'):
237
if "copyright" in line.lower() or "(c)" in line.lower():
238
copyright_holders += line
239
authors_holders += line
241
authors_holders += line
243
# update without last \n
244
quicklyutils.change_xml_elem(about_dialog_file_name, "object/property",
245
"name", "copyright", copyright_holders[:-1],
246
{'translatable': 'yes'})
247
quicklyutils.change_xml_elem(about_dialog_file_name, "object/property",
248
"name", "authors", authors_holders[:-1],
250
quicklyutils.change_xml_elem(about_dialog_file_name, "object/property",
251
"name", "license", license_content,
252
{'translatable': 'yes'})
253
copy_license_to_files(license_content)
256
def shell_completion(argv):
257
"""Propose available license as the third parameter"""
259
# if then license argument given, returns available licenses
261
print " ".join(get_supported_licenses())
264
if __name__ == "__main__":
266
templatetools.handle_additional_parameters(sys.argv, help, shell_completion)
268
if len(sys.argv) > 2:
269
print _("This command only take one optional argument: License\nUsage is: quickly license <license>")
271
if len(sys.argv) == 2:
272
license = sys.argv[1]
275
except LicenceError, error_message: