Skip to content

Commit 881916b

Browse files
Added comments to harvest
1 parent fdeecfc commit 881916b

1 file changed

Lines changed: 81 additions & 17 deletions

File tree

src/hermes_toml/harvest.py

Lines changed: 81 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@
77
from hermes.commands.harvest.base import HermesHarvestCommand, HermesHarvestPlugin
88

99
class TomlHarvestSettings(BaseModel):
10+
"""Settings class for this plugin"""
1011
filename: str = 'pyproject.toml'
1112

1213

1314
class TomlHarvestPlugin(HermesHarvestPlugin):
15+
"""Base class for the hermes plugin that harvests .toml files"""
16+
1417
settings_class = TomlHarvestSettings
1518
table_with_mapping = {
1619
"project": [
@@ -27,75 +30,136 @@ class TomlHarvestPlugin(HermesHarvestPlugin):
2730
allowed_keys_for_person = ["givenName", "lastName", "email", "@id", "@type"]
2831

2932
def __call__(self, command: HermesHarvestCommand):
33+
#set the working directory to the correct location
3034
path = command.args.path
3135
old_path = pathlib.Path.cwd()
3236
if path != old_path:
3337
os.chdir(path)
3438

39+
#harvesting the data from the .toml file specified in the Settings class
3540
data = self.read_from_toml(command.settings.toml.filename)
3641

42+
#resetting the working directory
3743
if path != old_path:
3844
os.chdir(old_path)
3945

46+
#returning the harvested data and some metadata
4047
return data, {"filename": command.settings.toml.filename}
4148

4249
@classmethod
4350
def read_from_toml(cls, file):
51+
#load the toml file as a dictionary
4452
data = toml.load(file)
53+
4554
ret_data = {}
55+
56+
#iterate over each table
57+
#read it's information and store it according to the mapping
58+
#if more than one table existis raise an error as
59+
#the information could be overlapping and there should only be one table
4660
for table, mapping in cls.table_with_mapping.items():
4761
table = data.get(table)
4862
if not table is None:
4963
if len(ret_data.keys()) != 0:
5064
raise ValueError("Both project and tool.poetry table exist.")
65+
#read the data from the table
5166
ret_data = cls.read_from_one_table(table, mapping)
5267

68+
#return the result
5369
return ret_data
5470

5571
@classmethod
5672
def read_from_one_table(cls, table, mapping):
5773
ret_data = {}
74+
75+
#iterate over each mapping
5876
for (field1, field2) in mapping:
59-
if not table.get(field2) is None:
60-
if field2 == "requires-python":
61-
ret_data[field1] = "Python " + table[field2]
62-
elif field1 in ["author", "maintainer"]:
63-
temp = cls.handle_person_in_unknown_format(table[field2])
64-
if isinstance(temp, dict) and len(temp.keys()) > 0:
65-
temp["@type"] = "Person"
77+
if not table.get(field2) is None:
78+
#if this field exists
79+
#some cases need additional processing
80+
if field2 == "requires-python":
81+
#add python to the python version number for the runtime platform
82+
ret_data[field1] = "Python " + table[field2]
83+
84+
elif field1 in ["author", "maintainer"]:
85+
#the integrity of the format of the person(s) is assured
86+
temp = cls.handle_person_in_unknown_format(table[field2])
87+
88+
#check if it is one person in the right format or none
89+
if isinstance(temp, dict) and len(temp.keys()) > 0:
90+
#store the persons data and add the @type field
91+
temp["@type"] = "Person"
92+
ret_data[field1] = temp
93+
94+
#check if how many persons are in the list
95+
elif isinstance(temp, list):
96+
if len(temp) > 1:
97+
#add for every person the @type field
98+
for person in temp:
99+
person["@type"] = "Person"
100+
101+
#store the data of the persons
66102
ret_data[field1] = temp
67-
elif isinstance(temp, list):
68-
if len(temp) > 1:
69-
for person in temp:
70-
person["@type"] = "Person"
71-
ret_data[field1] = temp
72-
elif len(temp) == 1:
73-
temp[0]["@type"] = "Person"
74-
ret_data[field1] = temp[0]
75-
else:
76-
ret_data[field1] = table[field2]
103+
104+
elif len(temp) == 1:
105+
#store the persons data and add the @type field
106+
temp[0]["@type"] = "Person"
107+
ret_data[field1] = temp[0]
108+
109+
else:
110+
#add the data of a field that needs no processing
111+
ret_data[field1] = table[field2]
112+
113+
else:
114+
#if it doesn't exist
115+
continue
116+
117+
#return the important data of the table
77118
return ret_data
78119

79120
@classmethod
80121
def handle_person_in_unknown_format(cls, persons):
122+
#check wheter it is one or are more persons
81123
if isinstance(persons, list):
124+
#in case of potentially at least two persons
82125
return_list = []
126+
#for each person
83127
for person in persons:
128+
129+
#check if the datatype is correct
84130
if isinstance(person, dict):
131+
#remove all attributes that aren't allowed
85132
temp = cls.remove_forbidden_keys(person)
133+
#if this leads to the dataset losing all values don't add it to the return list
86134
if len(temp.keys()) > 0:
87135
return_list.append(temp)
136+
88137
else:
138+
#if the person isn't a dictionary raise an Error
89139
raise ValueError("A person must be a dict.")
140+
141+
#return the person(s)
90142
return return_list
143+
144+
#if it is only one or no person
145+
#check for the right datatype
91146
if isinstance(persons, dict):
147+
#if it is correct return the person with all forbidden keys
148+
#the 'person' may be an empty dictionary if all keys are incorrect
92149
return cls.remove_forbidden_keys(persons)
150+
151+
#raise an error if the persons data is not in the right format
93152
raise ValueError("A person must be a dict.")
94153

95154
@classmethod
96155
def remove_forbidden_keys(cls, person):
156+
#the keys are extracted as the dictionary may be resized
97157
keys = list(person.keys())
158+
159+
#check for every key if it is allowed and if not remove it
98160
for key in keys:
99161
if not key in cls.allowed_keys_for_person:
100162
del person[key]
163+
164+
#return the persons data
101165
return person

0 commit comments

Comments
 (0)