Repository navigation
Expand file tree
/
Copy pathrelease_rules.py
More file actions
191 lines (151 loc) · 5.9 KB
/
Copy pathrelease_rules.py
File metadata and controls
191 lines (151 loc) · 5.9 KB
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
"""Rules to validate repo for release"""
import json
from hashlib import sha256
from mite_extras import MiteParser
from mite_schema import SchemaManager
from mite_data_lib.config.filenames import names
from mite_data_lib.models.metadata import ArtifactMetadata
from mite_data_lib.models.validation import ArtifactContext, ValidationIssue
def entry_check(
ctx: ArtifactContext, meta: ArtifactMetadata
) -> tuple[list[ValidationIssue], list[ValidationIssue]]:
"""For each entry, check if it passes mite_extras validation"""
e = []
w = []
model = SchemaManager()
for entry in ctx.data.glob("MITE*.json"):
parser = MiteParser()
try:
parser.parse_mite_json(json.loads(entry.read_text()))
model.validate_mite(parser.to_json())
except Exception as error:
e.append(
ValidationIssue(
severity="error",
location=entry.stem,
message=f"MITE entry {entry.name} failed validation: {error!s}",
)
)
return e, w
def fasta_check(
ctx: ArtifactContext, meta: ArtifactMetadata
) -> tuple[list[ValidationIssue], list[ValidationIssue]]:
"""For each mite entry, check if fasta exists (and vice versa) and if header matches"""
e = []
w = []
for entry in ctx.data.glob("MITE*.json"):
data = json.loads(entry.read_text())
db_ids = [data["enzyme"]["databaseIds"].get(i) for i in ("genpept", "uniprot")]
fasta_path = ctx.fasta.joinpath(f"{data['accession']}.fasta")
if data["status"] != "active":
if fasta_path.exists():
e.append(
ValidationIssue(
severity="error",
location=data["accession"],
message=f"Entry retired but still has an accompanying fasta file - investigate!",
)
)
continue
if not fasta_path.exists():
e.append(
ValidationIssue(
severity="error",
location=data["accession"],
message=f"Has no accompanying .fasta file in {ctx.fasta}",
)
)
continue
fasta_text = fasta_path.read_text()
if fasta_text.split()[0].removeprefix(">") != data["accession"]:
e.append(
ValidationIssue(
severity="error",
location=data["accession"],
message=f"Mismatch in MITE accession in header of .fasta file {fasta_path}",
)
)
if not fasta_text.split()[1] in db_ids:
e.append(
ValidationIssue(
severity="error",
location=data["accession"],
message=f"Mismatch in protein accession in header of .fasta file {fasta_path}",
)
)
for entry in ctx.fasta.glob("MITE*.fasta"):
if not ctx.data.joinpath(f"{entry.stem}.json").exists():
e.append(
ValidationIssue(
severity="error",
location=entry.stem,
message=f"Fasta-file {entry} has no corresponding MITE file - investigate!",
)
)
return e, w
def prot_acc_check(
ctx: ArtifactContext, meta: ArtifactMetadata
) -> tuple[list[ValidationIssue], list[ValidationIssue]]:
"""Validate hash of mite prot acc file"""
e = []
w = []
path = ctx.metadata / names.prot_acc
if meta.hash_mite_prot_acc != sha256(path.read_text().encode("utf-8")).hexdigest():
e.append(
ValidationIssue(
severity="error",
location="mite_prot_accessions.csv",
message=f"Hash compromised - was the file meddled with?",
)
)
return e, w
def molfiles_check(
ctx: ArtifactContext, meta: ArtifactMetadata
) -> tuple[list[ValidationIssue], list[ValidationIssue]]:
"""Validate hashes of molfiles"""
def _format_error(filename: str):
return ValidationIssue(
severity="error",
location=filename,
message=f"Hash compromised - was the file meddled with?",
)
e = []
w = []
smarts = ctx.metadata / names.smarts
if meta.smarts != sha256(smarts.read_text().encode("utf-8")).hexdigest():
e.append(_format_error("dump_smarts.csv"))
smiles = ctx.metadata / names.smiles
if meta.smiles != sha256(smiles.read_text().encode("utf-8")).hexdigest():
e.append(_format_error("dump_smiles.csv"))
return e, w
def summary_check(
ctx: ArtifactContext, meta: ArtifactMetadata
) -> tuple[list[ValidationIssue], list[ValidationIssue]]:
"""Validate hashes of summary files"""
def _hash_from_json(payload: dict) -> str:
json_str = json.dumps(
payload, indent=2, ensure_ascii=False, sort_keys=True, separators=(",", ":")
)
return sha256(json_str.encode("utf-8")).hexdigest()
def _format_error(filename: str):
return ValidationIssue(
severity="error",
location=filename,
message=f"Hash compromised - was the file meddled with?",
)
e = []
w = []
summary_json = ctx.metadata / names.summary_json
with open(summary_json) as f:
data = json.load(f)
if meta.hash_general_summary != _hash_from_json(data):
e.append(_format_error("metadata_general.json"))
summary_mibig = ctx.metadata / names.summary_mibig
with open(summary_mibig) as f:
data = json.load(f)
if meta.hash_mibig_summary != _hash_from_json(data):
e.append(_format_error("metadata_mibig.json"))
summary = ctx.metadata / names.summary_csv
if meta.summary != sha256(summary.read_text().encode("utf-8")).hexdigest():
e.append(_format_error("summary.csv"))
return e, w