This commit is contained in:
Daniel Knuettel 2017-12-28 00:13:55 +01:00
commit e170f25508
33 changed files with 1107 additions and 0 deletions

0
licor/__init__.py Normal file
View File

185
licor/__main__.py Normal file
View File

@ -0,0 +1,185 @@
#
# Copyright(c) Daniel Knüttel
#
# This program is free software.
# Anyways if you think this program is worth it
# and we meet shout a drink for me.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Dieses Programm ist Freie Software: Sie können es unter den Bedingungen
# der GNU Affero General Public License, wie von der Free Software Foundation,
# Version 3 der Lizenz oder (nach Ihrer Wahl) jeder neueren
# veröffentlichten Version, weiterverbreiten und/oder modifizieren.
#
# Dieses Programm wird in der Hoffnung, dass es nützlich sein wird, aber
# OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite
# Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK.
# Siehe die GNU Affero General Public License für weitere Details.
#
# Sie sollten eine Kopie der GNU Affero General Public License zusammen mit diesem
# Programm erhalten haben. Wenn nicht, siehe <http://www.gnu.org/licenses/>.
from .main import (list_this_path, list_all, list_db,
print_uncommented_line_based,
print_uncommented_block_based,
print_template_options)
import docopt, datetime, sys
usage = '''\
Insert license/copyright/warranty disclaimer to source files.
Usage:
licor list-db [<path>]
licor list-all [<path>]
licor list-path [<path>]
licor list-templates
licor print-templ <format> [options]
licor insert-header <format> [<path>] [options]
Options:
--comment-start=<comment-start> Comment start token to use [default: //]
--comment-stop=<comment-stop> Comment stop token to use [default: */]
--border=<border> Border character for some fancy stuff [default: *]
-f --fancy Use more fancy comments
--after-comment=<after-comment> A string to seperate border and content (defaults to one blank)
-c --confirm Wait for user confirmation before modifying files
--format=<format> Use a special comment format [default: block]
--license=<license> Use this license template [default: GPLv3]
--single-file Use single-file templates
--copyright Use templates containing copyright information
-a <author> --author=<author> Set the author (required for --copyright)
-p <project> --project=<project> Set the project (required unless --single-file is specified)
-e <ending> --file-ending=<ending> Search for files ending with this ending [default: c]
-i --ignore-db Ignore the database of processed files
--ignore-paths=<paths> Ignore all paths with one of `<paths>` in it (comma-seperated) [default: .git]
--pad-to=<pad-to> Pad comment blocks to this width [default: 0]
'''
if( __name__ == "__main__"):
args = docopt.docopt(usage)
if(args["list-db"]):
path = args["<path>"]
if(not path):
path = "."
try:
list_db(path)
except Exception as e:
print(e)
sys.exit(1)
if(args["list-path"]):
path = args["<path>"]
if(not path):
path = "."
ending = args["--file-ending"]
ignore_db = args["--ignore-db"]
list_this_path(path, ending, ignore_db = ignore_db)
if(args["list-all"]):
path = args["<path>"]
if(not path):
path = "."
ending = args["--file-ending"]
ignore_paths = args["--ignore-paths"].split(",")
ignore_db = args["--ignore-db"]
list_all(path, ending, ignore_paths, ignore_db = ignore_db)
if(args["print-templ"]):
form = args["<format>"]
license_name = args["--license"]
modifiers = []
if(args["--single-file"]):
modifiers.append("single-file")
if(args["--copyright"]):
modifiers.append("copyright")
data = {}
if(args["--author"]):
data["author"] = args["--author"]
if(args["--project"]):
data["project"] = args["--project"]
data["year"] = str(datetime.datetime.now().year)
after_comment = " "
if(args["--after-comment"]):
after_comment = args["--after-comment"]
try:
pad_to = int(args["--pad-to"])
except:
print("Failed to convert {} to int".format(args["--pad-to"]))
sys.exit(1)
if(form == "line"):
print_uncommented_line_based(license_name, modifiers, data, args["--comment-start"],
fancy = args["--fancy"], after_comment = after_comment,
pad_to = pad_to)
elif(form == "block"):
method = args["--format"]
if(not method):
method = "line"
print_uncommented_block_based(license_name, modifiers, data,
args["--comment-start"], args["--comment-stop"],
border = args["--border"],
fancy = args["--fancy"], after_comment = after_comment,
method = method, pad_to = pad_to)
else:
print("Unknown format ({}). Use line or block.".format(form))
if(args["list-templates"]):
print_template_options()
if(args["insert-header"]):
form = args["<format>"]
license_name = args["--license"]
modifiers = []
if(args["--single-file"]):
modifiers.append("single-file")
if(args["--copyright"]):
modifiers.append("copyright")
data = {}
if(args["--author"]):
data["author"] = args["--author"]
if(args["--project"]):
data["project"] = args["--project"]
data["year"] = str(datetime.datetime.now().year)
after_comment = " "
if(args["--after-comment"]):
after_comment = args["--after-comment"]
try:
pad_to = int(args["--pad-to"])
except:
print("Failed to convert {} to int".format(args["--pad-to"]))
sys.exit(1)
path = args["<path>"]
ignore_paths = args["--ignore-paths"].split(",")
ignore_db = args["--ignore-db"]
insert_templates_all(path, args["--file-ending"], ignore_paths, license_name,
modifiers, data, args["--comment-start"], args["--comment-stop"],
form, method = method, border = args["--border"], fancy = args["--fancy"],
after_comment = after_comment, pad_to = pad_to, ignore_db = args["--ignore-db"],
confirm = args["--confirmation"])

153
licor/comment.py Normal file
View File

@ -0,0 +1,153 @@
#
# Copyright(c) Daniel Knüttel
#
# This program is free software.
# Anyways if you think this program is worth it
# and we meet shout a drink for me.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Dieses Programm ist Freie Software: Sie können es unter den Bedingungen
# der GNU Affero General Public License, wie von der Free Software Foundation,
# Version 3 der Lizenz oder (nach Ihrer Wahl) jeder neueren
# veröffentlichten Version, weiterverbreiten und/oder modifizieren.
#
# Dieses Programm wird in der Hoffnung, dass es nützlich sein wird, aber
# OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite
# Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK.
# Siehe die GNU Affero General Public License für weitere Details.
#
# Sie sollten eine Kopie der GNU Affero General Public License zusammen mit diesem
# Programm erhalten haben. Wenn nicht, siehe <http://www.gnu.org/licenses/>.
def pad_line(line, pad_to):
"""
Pad line with blanks until the line is ``pad_to``
long.
"""
return line + " " * (pad_to - len(line))
def uncomment_line_based(text, comment_start,
fancy = False,
after_comment = " ",
pad_to = 0):
"""
Generate an uncommented version of the text that can be inserted into
a source file.
If ``fancy`` is False, the code will be just uncommented
by inserting a ``comment_start`` and a ``after_comment`` at every nonempty line.
If ``fancy`` is True the block will be padded with blanks
(either to ``pad_to`` or until the longest line is matched)
and there will be another ``comment_start`` at the end of
every line.
Example::
uncomment_line_based("This is a text\n\nblock\n", "#")
Will result in::
# This is a text
# block
The trailing newline will be preserved.
"""
text = text.split("\n")
if(not fancy):
text = [comment_start + after_comment + line if line else line for line in text]
else:
max_length = len(max(text, key = lambda x: len(x)))
if(max_length > pad_to):
pad_to = max_length
text = [comment_start + after_comment +
pad_line(line, pad_to) +
after_comment + comment_start
for line in text]
return "\n".join(text)
def uncomment_multiline_line_oriented(text, comment_start,
comment_stop, after_comment = " ",
fancy = False, border = "*", pad_to = 0):
"""
Just like ``uncomment_line_based``, but with start and stop
for comments.
**Note**: ``border`` must be a length-1 string.
"""
text = text.split("\n")
max_length = len(max(text, key = lambda x: len(x)))
if(max_length > pad_to):
pad_to = max_length
if(not fancy):
text = [comment_start + after_comment + pad_line(line, pad_to) +
after_comment + comment_stop
if line else line for line in text]
else:
text_res = [comment_start + after_comment + border * pad_to
+ after_comment + comment_stop]
text_res += [comment_start + after_comment +
pad_line(line, pad_to) +
after_comment + comment_stop
for line in text]
text_res += [comment_start + after_comment + border * pad_to
+ after_comment + comment_stop]
text = text_res
return "\n".join(text)
def uncomment_multiline_block_oriented(text, comment_start, comment_stop,
after_comment = " ", fancy = False,
border = "*",
pad_to = 0):
"""
Uncomment a text block block oriented.
"""
text = text.split("\n")
max_length = len(max(text, key = lambda x: len(x)))
if(max_length > pad_to):
pad_to = max_length
indent = " " * (len(comment_start) - 1) + border
text_res = [comment_start + after_comment + border * pad_to
+ after_comment + border]
text_res += [indent + after_comment + pad_line(line, pad_to) +
after_comment + border
for line in text]
text_res += [indent + after_comment + border * pad_to
+ after_comment + comment_stop]
text = text_res
return "\n".join(text)

68
licor/filediscovery.py Normal file
View File

@ -0,0 +1,68 @@
#
# Copyright(c) Daniel Knüttel
#
# This program is free software.
# Anyways if you think this program is worth it
# and we meet shout a drink for me.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Dieses Programm ist Freie Software: Sie können es unter den Bedingungen
# der GNU Affero General Public License, wie von der Free Software Foundation,
# Version 3 der Lizenz oder (nach Ihrer Wahl) jeder neueren
# veröffentlichten Version, weiterverbreiten und/oder modifizieren.
#
# Dieses Programm wird in der Hoffnung, dass es nützlich sein wird, aber
# OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite
# Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK.
# Siehe die GNU Affero General Public License für weitere Details.
#
# Sie sollten eine Kopie der GNU Affero General Public License zusammen mit diesem
# Programm erhalten haben. Wenn nicht, siehe <http://www.gnu.org/licenses/>.
import glob, os
def discover_this_path(path, file_ending):
"""
Discover all matching files in this path.
Return an iterator yielding the filepaths.
"""
return (os.path.abspath(p) for p in glob.iglob(os.path.join(path, "*." + file_ending)))
def discover_all(path, file_ending, ignore_paths = []):
"""
Discover all matching files in this path and
all subpaths.
Yield the filepaths.
"""
for p in os.walk(path):
path = p[0]
splitted = path.split(os.sep)
if(any( [ignore in splitted for ignore in ignore_paths ])):
continue
for i in discover_this_path(path, file_ending):
yield i

69
licor/io.py Normal file
View File

@ -0,0 +1,69 @@
import os
#
# Copyright(c) Daniel Knüttel
#
# This program is free software.
# Anyways if you think this program is worth it
# and we meet shout a drink for me.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Dieses Programm ist Freie Software: Sie können es unter den Bedingungen
# der GNU Affero General Public License, wie von der Free Software Foundation,
# Version 3 der Lizenz oder (nach Ihrer Wahl) jeder neueren
# veröffentlichten Version, weiterverbreiten und/oder modifizieren.
#
# Dieses Programm wird in der Hoffnung, dass es nützlich sein wird, aber
# OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite
# Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK.
# Siehe die GNU Affero General Public License für weitere Details.
#
# Sie sollten eine Kopie der GNU Affero General Public License zusammen mit diesem
# Programm erhalten haben. Wenn nicht, siehe <http://www.gnu.org/licenses/>.
def check_file_perm(filename):
"""
Check wether this process can open this file for R/W.
"""
if(not os.path.exists(filename)):
raise IOError("File not Found: {}".format(filename))
if(not (os.access(filename, os.R_OK) and os.access(filename, os.W_OK))):
raise IOError("File not readable/writable: {}".format(filename))
def insert_header(filename, header, chunk_size = 1024, encoding = "UTF-8"):
"""
Insert the header ``header`` into the file with the name ``filename``.
"""
check_file_perm(filename)
with open(filename, encoding = encoding) as fin:
os.unlink(filename)
with open(filename, "w", encoding = encoding) as fout:
fout.write(header)
chunk = fin.read(chunk_size)
while(chunk):
fout.write(chunk)
chunk = fin.read(chunk_size)

174
licor/main.py Normal file
View File

@ -0,0 +1,174 @@
#
# Copyright(c) Daniel Knüttel
#
# This program is free software.
# Anyways if you think this program is worth it
# and we meet shout a drink for me.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Dieses Programm ist Freie Software: Sie können es unter den Bedingungen
# der GNU Affero General Public License, wie von der Free Software Foundation,
# Version 3 der Lizenz oder (nach Ihrer Wahl) jeder neueren
# veröffentlichten Version, weiterverbreiten und/oder modifizieren.
#
# Dieses Programm wird in der Hoffnung, dass es nützlich sein wird, aber
# OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite
# Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK.
# Siehe die GNU Affero General Public License für weitere Details.
#
# Sie sollten eine Kopie der GNU Affero General Public License zusammen mit diesem
# Programm erhalten haben. Wenn nicht, siehe <http://www.gnu.org/licenses/>.
from .work import work_all, work_this_path
from .templates import get_license_meta, format_license_template, get_templates_available
from .comment import uncomment_line_based, uncomment_multiline_line_oriented, uncomment_multiline_block_oriented
import os
from .io import insert_header, check_file_perm
db_filename = ".licor.list"
def get_ignored(path):
try:
with open(os.path.join(path, db_filename)) as f:
return f.read().split("\n")
except:
return []
def write_ignored(path, ignored):
with open(os.path.join(path, db_filename)) as f:
f.write("\n".join([i for i in ingored if i]))
def get_confirmation(text):
while(True):
print(text, " ", end = "")
res = input("(y/n) ")
if(res in ("Y", "y")):
return True
if(res in ("n", "N")):
return False
print("please enter Y or N")
def get_path_confirmation(path):
return not get_confirmation("use " + path)
def raw_insert_into_db(db_path, path):
ignored = get_ignored(db_path)
if(not path in ignored):
ignored.append(path)
write_ignored(db_path, ignored)
def list_this_path(path, file_ending, ignore_db = False):
if(ignore_db):
ignore_files = get_ignored(path)
else:
ignore_files = []
work_this_path(path, file_ending, [print], ignore_files = ignore_files)
def list_all(path, file_ending, ignore_paths, ignore_db = False):
if(not ignore_db):
ignore_files = get_ignored(path)
else:
ignore_files = []
work_all(path, file_ending, [print], ignore_paths = ignore_paths, ignore_files = ignore_files)
def list_db(path):
with open(os.path.join(path, db_filename)) as f:
print(f.read())
def print_uncommented_line_based(license_name, modifiers, data,
comment_start, fancy = False, after_comment = " ", pad_to = 0):
data = format_license_template(license_name, data, modifiers)
print(uncomment_line_based(data, comment_start, fancy = fancy,
after_comment = after_comment, pad_to = pad_to))
def print_uncommented_block_based(license_name, modifiers, data,
comment_start, comment_stop, method = "line", border = "*", fancy = False, after_comment = " ", pad_to = 0):
data = format_license_template(license_name, data, modifiers)
if(method == "block"):
print(uncomment_multiline_block_oriented(data,
comment_start, comment_stop,
after_comment = after_comment,
fancy = fancy, border = border,
pad_to = pad_to))
else:
print(uncomment_multiline_line_oriented(data,
comment_start, comment_stop,
after_comment = after_comment,
fancy = fancy, border = border,
pad_to = pad_to))
def print_template_options():
meta = get_templates_available()
for template_name, data in meta.items():
print(template_name)
for modifier in data["modifiers"]:
print("\t\t", modifier)
def insert_templates_all(path, file_ending, ignore_paths, license_name, modifiers, data,
comment_start, comment_stop, format_, method = "line", border = "*",
fancy = False, after_comment = " ", pad_to = 0,
ignore_db = False, confirm = False):
if(not ignore_db):
ignore_files = get_ignored(path)
else:
ignore_files = []
# check for file permissions
try:
work_all(path, file_ending, [check_file_perm], ignore_paths = ignore_paths, ignore_files = ignore_files)
except Exception as e:
print(e)
sys.exit(1)
callbacks = []
data = format_license_template(license_name, data, modifiers)
if(format_ == "line"):
text = uncomment_line_based(data, comment_start, fancy = fancy,
after_comment = after_comment, pad_to = pad_to)
else:
if(method == "block"):
text = uncomment_multiline_block_oriented(data,
comment_start, comment_stop,
after_comment = after_comment,
fancy = fancy, border = border,
pad_to = pad_to)
else:
text = uncomment_multiline_line_oriented(data,
comment_start, comment_stop,
after_comment = after_comment,
fancy = fancy, border = border,
pad_to = pad_to)
if(confirm):
callbacks.append(get_path_confirmation)
callbacks.append(lambda x: insert_header(x, text))
if(not ignore_db):
callback.append(lambda x: raw_insert_into_db(path, x))
work_all(path, file_ending, callbacks, ignore_paths = ignore_paths, ignore_files = ignore_files)

156
licor/templates.py Normal file
View File

@ -0,0 +1,156 @@
#
# Copyright(c) Daniel Knüttel
#
# This program is free software.
# Anyways if you think this program is worth it
# and we meet shout a drink for me.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Dieses Programm ist Freie Software: Sie können es unter den Bedingungen
# der GNU Affero General Public License, wie von der Free Software Foundation,
# Version 3 der Lizenz oder (nach Ihrer Wahl) jeder neueren
# veröffentlichten Version, weiterverbreiten und/oder modifizieren.
#
# Dieses Programm wird in der Hoffnung, dass es nützlich sein wird, aber
# OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite
# Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK.
# Siehe die GNU Affero General Public License für weitere Details.
#
# Sie sollten eine Kopie der GNU Affero General Public License zusammen mit diesem
# Programm erhalten haben. Wenn nicht, siehe <http://www.gnu.org/licenses/>.
import pkg_resources, json
from itertools import permutations
from string import Template
class TemplateException(Exception):
pass
def get_resource_string(name):
"""
Return the resource string with the given name UTF-8 encoded.
"""
return pkg_resources.resource_string(__name__,"templates/" + name).decode("UTF-8")
def get_license_template(name, modifiers = []):
"""
Return a ``dict`` containing all necessary information for
filling a license template::
{
"name": <template-name>,
"keywords": ["author", "date", ...],
"text": <template string>
}
``modifiers`` is a list specifying the template.
A typical call might be::
get_license_template("AGPL", modifiers = ["single-file"])
"""
templates_avail = json.loads(get_resource_string("licenses_avail.json"))
if( not name in templates_avail):
raise TemplateException("Unknown license: {}".format(name))
unsupported = [mod for mod in modifiers if not mod in templates_avail[name]["modifiers"]]
if(unsupported):
raise TemplateException("Unknown modifiers: {}. Supported are: {}".format(
",".join(unsupported), ",".join(templates_avail[name]["modifiers"])))
for perm in permutations(modifiers):
mods = ".".join(perm)
if(mods):
meta_name = ".".join((name, mods, "meta"))
data_name = ".".join((name, mods, "tx"))
else:
meta_name = ".".join((name, "meta"))
data_name = ".".join((name, "tx"))
try:
meta = json.loads(get_resource_string(meta_name))
except:
continue
data = get_resource_string(data_name)
meta.update({"text": data})
return meta
raise TemplateException("Database licenses_avail.json is desynced. Unable to locate resource.")
def get_license_meta(name, modifiers = []):
"""
Return a ``dict`` containing all necessary information for
filling a license template::
{
"name": <template-name>,
"keywords": ["author", "date", ...]
}
``modifiers`` is a list specifying the template.
A typical call might be::
get_license_meta("AGPL", modifiers = ["single-file"])
"""
templates_avail = json.loads(get_resource_string("licenses_avail.json"))
if( not name in templates_avail):
raise TemplateException("Unknown license: {}".format(name))
unsupported = [mod for mod in modifiers if not mod in templates_avail[name]["modifiers"]]
if(unsupported):
raise TemplateException("Unknown modifiers: {}. Supported are: {}".format(
",".join(unsupported), ",".join(templates_avail[name]["modifiers"])))
for perm in permutations(modifiers):
mods = ".".join(perm)
if(mods):
meta_name = ".".join((name, mods, "meta"))
else:
meta_name = ".".join((name, "meta"))
try:
meta = json.loads(get_resource_string(meta_name))
except:
continue
return meta
raise TemplateException("Database licenses_avail.json is desynced. Unable to locate resource.")
def format_license_template(name, data, modifiers = []):
"""
Return a formatted version of the license Template.
This text is ready to be uncommented an placed into a source file.
"""
template = get_license_template(name, modifiers)
missing = [k for k in template["keywords"] if not k in data]
if(missing):
raise TemplateException("missing keywords: {}".format(",".join(missing)))
return Template(template["text"]).substitute(data)
def get_templates_available():
"""
Return a ``dict`` containing information about the available templates.
"""
return json.loads(get_resource_string("licenses_avail.json"))

View File

@ -0,0 +1,4 @@
{
"keywords": ["author", "year", "project"],
"name": "AGPLv3"
}

View File

@ -0,0 +1,17 @@
Copyright (c) ${year} ${author}
This file is part of ${project}.
${project} is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
${project} is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with ${project}. If not, see <http://www.gnu.org/licenses/>.

View File

@ -0,0 +1,5 @@
{
"keywords": ["project"],
"name": "AGPLv3"
}

View File

@ -0,0 +1,5 @@
{
"keywords": ["author", "year"],
"name": "AGPLv3"
}

View File

@ -0,0 +1,14 @@
Copyright (c) ${year} ${author}
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

View File

@ -0,0 +1,5 @@
{
"keywords": [],
"name": "AGPLv3"
}

View File

@ -0,0 +1,12 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the Affero GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

14
licor/templates/AGPLv3.tx Normal file
View File

@ -0,0 +1,14 @@
This file is part of ${project}.
${project} is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
${project} is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with ${project}. If not, see <http://www.gnu.org/licenses/>.

View File

@ -0,0 +1,4 @@
{
"keywords": ["author", "year", "project"],
"name": "GPLv3"
}

View File

@ -0,0 +1,16 @@
Copyright (c) ${year} ${author}
This file is part of ${project}.
${project} is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
${project} is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with ${project}. If not, see <http://www.gnu.org/licenses/>.

View File

@ -0,0 +1,5 @@
{
"keywords": ["project"],
"name": "GPLv3"
}

View File

@ -0,0 +1,5 @@
{
"keywords": ["author", "year"],
"name": "GPLv3"
}

View File

@ -0,0 +1,14 @@
Copyright (c) ${year} ${author}
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

View File

@ -0,0 +1,5 @@
{
"keywords": [],
"name": "GPLv3"
}

View File

@ -0,0 +1,12 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

14
licor/templates/GPLv3.tx Normal file
View File

@ -0,0 +1,14 @@
This file is part of ${project}.
${project} is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
${project} is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with ${project}. If not, see <http://www.gnu.org/licenses/>.

View File

@ -0,0 +1,4 @@
{
"keywords": ["author", "year", "project"],
"name": "LGPLv3"
}

View File

@ -0,0 +1,17 @@
Copyright (c) ${year} ${author}
This file is part of ${project}.
${project} is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
${project} is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with ${project}. If not, see <http://www.gnu.org/licenses/>.

View File

@ -0,0 +1,5 @@
{
"keywords": ["project"],
"name": "LGPLv3"
}

View File

@ -0,0 +1,5 @@
{
"keywords": ["author", "year"],
"name": "LGPLv3"
}

View File

@ -0,0 +1,14 @@
Copyright (c) ${year} ${author}
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

View File

@ -0,0 +1,5 @@
{
"keywords": ["year", "author"],
"name": "LGPLv3"
}

View File

@ -0,0 +1,12 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

14
licor/templates/LGPLv3.tx Normal file
View File

@ -0,0 +1,14 @@
This file is part of ${project}.
${project} is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
${project} is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with ${project}. If not, see <http://www.gnu.org/licenses/>.

View File

@ -0,0 +1,5 @@
{
"GPLv3": {"modifiers": ["single-file", "copyright"]},
"AGPLv3": {"modifiers": ["single-file", "copyright"]},
"LGPLv3": {"modifiers": ["single-file", "copyright"]}
}

70
licor/work.py Normal file
View File

@ -0,0 +1,70 @@
#
# Copyright(c) Daniel Knüttel
#
# This program is free software.
# Anyways if you think this program is worth it
# and we meet shout a drink for me.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Dieses Programm ist Freie Software: Sie können es unter den Bedingungen
# der GNU Affero General Public License, wie von der Free Software Foundation,
# Version 3 der Lizenz oder (nach Ihrer Wahl) jeder neueren
# veröffentlichten Version, weiterverbreiten und/oder modifizieren.
#
# Dieses Programm wird in der Hoffnung, dass es nützlich sein wird, aber
# OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite
# Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK.
# Siehe die GNU Affero General Public License für weitere Details.
#
# Sie sollten eine Kopie der GNU Affero General Public License zusammen mit diesem
# Programm erhalten haben. Wenn nicht, siehe <http://www.gnu.org/licenses/>.
from .filediscovery import discover_all, discover_this_path
import os
def work_one(path, callbacks):
"""
Run all callbacks for the given path.
All the callbacks should return any value that
evals to False. If one callback returns a value
that evals to True the rest of the callbacks is skipped.
"""
for callback in callbacks:
if(callback(path)):
break
def work_all(path, file_ending, callbacks, ignore_paths = [], ignore_files = []):
"""
Walk over all matching files matched by ``discover_all``.
"""
for this_path in discover_all(path, file_ending, ignore_paths):
if(this_path in ignore_files):
continue
work_one(this_path, callbacks)
def work_this_path(path, file_ending, callbacks, ignore_files = []):
"""
Walk over all matching files matched by ``discover_this_path``.
"""
for this_path in discover_this_path(path, file_ending):
if(this_path in ignore_files):
continue
work_one(this_path, callbacks)