1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
#!/usr/bin/env python3
""" Get the copyright rules from a root, and get the copyright rules on a file.
Based on the `copyright.yml` files -- see `FORMAT.md` for its description.
"""
import os, re, fnmatch
from datetime import date
import yaml
from .exceptions import *
__all__ = ["get_copyright_rules", "get_copyright"]
__default_maintainer = ((2016, date.today().year),
'Thomas "Cakeisalie5" Touhey', 'thomas@touhey.fr')
def get_copyright_rules(root):
""" Get the copyright rules from a root. """
root = os.path.join(root, '')
rules = {}
# Copyright file thing.
for rt, _, _ in os.walk(root):
# Ignore file.
try:
with open(os.path.join(rt, '.gitignore')) as f:
rulz = []
for line in f.readlines():
# Get what's before the comment.
line = re.sub('([^\\\\](\\\\\\\\)*)#.*$', '\\1', line)
line = re.sub('\\\\(.*)', '\\1', line)
line = line.strip()
if line: rulz.append(line)
for l in rulz:
if l[0] == '/':
nm = l[1:].split('/')
bases = [os.path.join(rt, *nm)]
else:
nm = l.split('/')
bases = [os.path.join(rt, *nm),
os.path.join(rt, '**', *nm)]
for base in bases:
rules[base] = '===IGNORED==='
except FileNotFoundError:
pass
# Copyright file.
try:
with open(os.path.join(rt, 'copyright.yml')) as f:
d_rules = yaml.load_all(f.read())
# Read each rule.
for rule in d_rules:
ml = rule['files']
if type(ml) != list:
ml = [ml]
l = rule['license'] if 'license' in rule else 'LGPL-3'
authors = []
if 'copyright' in rule:
for author in rule['copyright']:
if len(author) == 3:
authors.append(((author[0], author[0]),
author[1], author[2]))
else:
authors.append(((author[0], author[1]),
author[2], author[3]))
if not authors:
authors.append(__default_maintainer)
for m in ml:
spl = m.split('/')
m = os.path.join(rt, *spl)
rules[m] = {'authors': authors, 'license': l}
except FileNotFoundError:
pass
return rules
def __match(rule, path):
""" Check if a path matches a rule. """
# Check if the full path is matched.
if fnmatch.fnmatch(path, rule):
return True
# Check if one of the parent directories is matched.
while True:
dirname, filename = os.path.split(path)
if not dirname: break
if fnmatch.fnmatch(dirname, rule):
return True
path = dirname
# Nothing is matched. Exit!
return False
def get_copyright(rules, path):
""" Get a path's copyright using a set of rules. """
if not os.path.isfile(path):
raise NotAFileException
if os.path.basename(path) == 'copyright.yml':
raise IgnoredFileException
match = None
for rule in rules:
# Check if the rule matches the path.
if not __match(rule, path):
continue
# Check if it is the first thing.
if not match:
match = rule
continue
# If the current rule is more precise, take it instead.
# TODO: of course that length rule is stupid and doesn't take into
# account things such as "arch/**/info.yml is more precise than
# arch/myplatform/mymodule/*", but it's a quick hack.
if len(rule) > len(match):
match = rule
if not match:
raise NoCopyrightException
rule = rules[match]
if rule == '===IGNORED===':
raise IgnoredFileException
return (rule['authors'], rule['license'])
# End of file.
|