First import

This commit is contained in:
2022-02-18 12:09:05 +01:00
commit 332876f58c
73 changed files with 12572 additions and 0 deletions
@@ -0,0 +1,3 @@
from .error import Entity, Error
from .error_message import ErrorMessage
from .error_log import ErrorLog
+119
View File
@@ -0,0 +1,119 @@
from typing import Optional
from .error_message import ErrorMessage
class Entity():
"""Entity information
Args:
acronym: acronym of the entity. Must be a 3-characters captalized string
"""
def __init__(self, acronym: str) -> None:
self.acronym = acronym
def __str__(self) -> str:
return f"Entity {self.acronym}: {self.name}"
@property
def _acronyms(self) -> list:
return [
func
for func in dir(self)
if func.isupper() and
callable(getattr(self, func)) and
not func.startswith("__")
]
@property
def _names(self) -> dict:
return {acr: getattr(self, acr)() for acr in self._acronyms}
@property
def name(self) -> str:
try:
return self._names[self.acronym]
except KeyError:
raise KeyError(f'Unknown acronym {self.acronym}.')
@property
def acronym(self) -> str:
return self._acronym
@acronym.setter
def acronym(self, acronym: str) -> None:
self._acronym = acronym
def EFS(self) -> str:
return 'Excel File Structure'
def GMD(self) -> str:
return 'Growth Media'
def GOD(self) -> str:
return 'Geographic Origin'
def LID(self) -> str:
return 'Literature'
def STD(self) -> str:
return 'Strains'
def GID(self) -> str:
return 'Genomic Information'
def OTD(self) -> str:
return 'Ontobiotope'
def UCT(self) -> str:
return 'Uncategorized'
class Error():
"""Error information
Args:
message (str): Error message
entity (Entity, optional): Entity related to the error. If None will default to Uncategorized. Defaults to None.
data (str, optional): Data used for sorting the messages. Defaults to None.
"""
def __init__(self, code: str, pk: Optional[str] = None, data: Optional[str] = None) -> None:
self.code = code.upper()
self.pk = pk
self.data = data
def __str__(self):
return f"Error {self._code}: {self.message}"
@property
def code(self) -> str:
return self._code
@code.setter
def code(self, code: str) -> None:
self._code = code.upper()
@property
def pk(self) -> Optional[str]:
return self._pk
@pk.setter
def pk(self, pk: Optional[str] = None) -> None:
self._pk = pk
@property
def data(self) -> Optional[str]:
return self._data
@data.setter
def data(self, data: Optional[str]):
self._data = data
@property
def entity(self) -> Entity:
return Entity(self.code[:3])
@property
def message(self) -> str:
return ErrorMessage(self.code, self.pk, self.data).message
@@ -0,0 +1,77 @@
from typing import Optional, Union
from datetime import datetime
from .error import Error
class ErrorLog():
def __init__(self, input_filename: str, cc: Optional[str] = None, date: Optional[Union[str, datetime]] = None, limit: int = 100):
"""
Logger for Error instances.
Args:
input_filename (str): name of the file to be logged
cc (str, optional): name of the curator. Defaults to None.
date (str, optional): date (e.g. created, last modified) associated with the file. Useful for versioning. Defaults to None.
limit (int, optional): limit of errors to print to the report. Defaults to 100.
"""
self._input_filename = input_filename
self._cc = cc
self._date = date
self._errors = {}
self.limit = limit
self._counter = 0
def __str__(self) -> str:
output = f"""Error Log for file {self._input_filename}\nENTITY | CODE | MESSAGE"""
for acronym, error_list in self.get_errors().items():
for error in error_list:
output += f"\n{acronym:6} | {error.code:6} | {error.message[:100]}"
return output
@property
def input_filename(self) -> str:
return self._input_filename
@input_filename.setter
def input_filename(self, input_filename: str) -> None:
self._input_filename = input_filename
@property
def cc(self) -> Optional[str]:
return self._cc
@cc.setter
def cc(self, cc: Optional[str]) -> None:
self._cc = cc
@property
def date(self) -> Optional[Union[str, datetime]]:
return self._date
@date.setter
def date(self, date: Optional[Union[str, datetime]] = None) -> None:
if isinstance(date, str):
self._date = datetime.strptime(date, r'%d-%m-%Y')
else:
self._date = date
def get_errors(self) -> dict:
"""
Get all errors
Returns:
dict: Error intances grouped by entity acronym.
"""
return self._errors
def add_error(self, error: Error) -> None:
"""
Add an error.
Args:
error (Error): Error instance.
"""
if error.entity.acronym not in self._errors:
self._errors[error.entity.acronym] = [error]
else:
self._errors[error.entity.acronym].append(error)
@@ -0,0 +1,408 @@
from typing import Optional
class ErrorMessage():
"""Error message
Args:
code (str): Error code.
pk (str | optional): The instance's primary key that triggered the error. Defaults to None.
value (str | optional): The instance's value that triggered the error. Defaults to None.
"""
def __init__(self, code: str, pk: Optional[str] = None, value: Optional[str] = None):
self.code = code.upper()
self.pk = pk
self.value = value
@property
def _codes(self) -> list:
return [
func
for func in dir(self)
if func.isupper() and
callable(getattr(self, func)) and
not func.startswith("__")
]
@property
def _messages(self) -> dict:
return {code: getattr(self, code) for code in self._codes}
@property
def message(self) -> str:
if not self._validate_code():
raise ValueError(f"{self.code} not found")
return self._messages[self.code]()
@property
def code(self) -> str:
return self._code
@code.setter
def code(self, code: str) -> None:
self._code = code.upper()
def _validate_code(self) -> bool:
return self.code in self._codes
@property
def pk(self) -> str:
return self._pk
@pk.setter
def pk(self, pk: str) -> None:
self._pk = pk
@property
def value(self) -> str:
return self._value
@value.setter
def value(self, value: str) -> None:
self._value = value
"""
Excel File Structure Error Codes
"""
def EXL00(self):
return f"The provided file '{self.pk}' is not an excel(xlsx) file"
def EFS01(self):
return "The 'Growth media' sheet is missing. Please check the provided excel template."
def EFS02(self):
return "The 'Geographic origin' sheet is missing. Please check the provided excel template."
def EFS03(self):
return "The 'Literature' sheet is missing. Please check the provided excel template."
def EFS04(self):
return "The 'Sexual state' sheet is missing. Please check the provided excel template."
def EFS05(self):
return "The 'Strains' sheet is missing. Please check the provided excel template."
def EFS06(self):
return "The 'Ontobiotope' sheet is missing. Please check the provided excel template."
def EFS07(self):
return "The 'Markers' sheet is missing. Please check the provided excel template."
def EFS08(self):
return "The 'Genomic information' sheet is missing. Please check the provided excel template."
"""
Growth Media Error Codes
"""
def GMD01(self):
return "The 'Acronym' column is a mandatory field in the Growth Media sheet."
def GMD02(self):
return "The 'Acronym' column is empty or has missing values."
def GMD03(self):
return "The 'Description' column is a mandatory field in the Growth Media sheet. The column can not be empty."
def GMD04(self):
return f"The 'Description' for growth media with Acronym {self.pk} is missing."
"""
Geographic Origin Error Codes
"""
def GOD01(self):
return "The 'ID' column is a mandatory field in the Geographic Origin sheet."
def GOD02(self):
return "The 'ID' column is empty or has missing values."
def GOD03(self):
return "The 'Country' column is a mandatory field in the Geographic Origin sheet. The column can not be empty."
def GOD04(self):
return f"The 'Country' for geographic origin with ID {self.pk} is missing."
def GOD05(self):
return f"The 'Country' for geographic origin with ID {self.pk} is incorrect."
def GOD06(self):
return f"The 'Locality' column is a mandatory field in the Geographic Origin sheet. The column can not be empty."
def GOD07(self):
return f"The 'Locality' for geographic origin with ID {self.pk} is missing."
"""
Literature Error Codes
"""
def LID01(self):
return "The 'ID' column is a mandatory field in the Literature sheet."
def LID02(self):
return "The 'ID' column empty or missing values."
def LID03(self):
return "The 'Full reference' column is a mandatory field in the Literature sheet. The column can not be empty."
def LID04(self):
return f"The 'Full reference' for literature with ID {self.pk} is missing."
def LID05(self):
return "The 'Authors' column is a mandatory field in the Literature sheet. The column can not be empty."
def LID06(self):
return f"The 'Authors' for literature with ID {self.pk} is missing."
def LID07(self):
return "The 'Title' column is a mandatory field in the Literature sheet. The column can not be empty."
def LID08(self):
return f"The 'Title' for literature with ID {self.pk} is missing."
def LID09(self):
return "The 'Journal' column is a mandatory field in the Literature sheet. The column can not be empty."
def LID10(self):
return f"The 'Journal' for literature with ID {self.pk} is missing."
def LID11(self):
return "The 'Year' column is a mandatory field in the Literature sheet. The column can not be empty."
def LID12(self,):
return f"The 'Year' for literature with ID {self.pk} is missing."
def LID13(self):
return "The 'Volume' column is a mandatory field in the Literature sheet. The column can not be empty."
def LID14(self):
return f"The 'Volume' for literature with ID {self.pk} is missing."
def LID15(self):
return "The 'First page' column is a mandatory field. The column can not be empty."
def LID16(self):
return f"The 'First page' for literature with ID {self.pk} is missing."
def LID17(self):
msg = 'If journal; Title, Authors, journal, year and first page are required'
msg += 'If Book; Book Title, Authors, Year, Editors, Publishers'
return msg
"""
Strains Error Codes
"""
def STD01(self):
return "The 'Accession number' column is a mandatory field in the Strains sheet."
def STD02(self):
return "The 'Accession number' column is empty or has missing values."
def STD03(self):
return f"The 'Accesion number' must be unique. The '{self.value}' is repeated."
def STD04(self):
return (f"The 'Accession number' {self.pk} is not according to the specification."
" The value must be of the format '<Sequence of characters> <sequence of characters>'.")
def STD05(self):
return f"The 'Restriction on use' column is a mandatory field in the Strains Sheet. The column can not be empty."
def STD06(self):
return f"The 'Restriction on use' for strain with Accession Number {self.pk} is missing."
def STD07(self):
return (f"The 'Restriction on use' for strain with Accession Number {self.pk} is not according to the specification."
f" Your value is {self.value} and the accepted values are 1, 2, 3.")
def STD08(self):
return f"The 'Nagoya protocol restrictions and compliance conditions' column is a mandatory field in the Strains Sheet. The column can not be empty."
def STD09(self):
return f"The 'Nagoya protocol restrictions and compliance conditions' for strain with Accession Number {self.pk} is missing."
def STD10(self):
return (f"The 'Nagoya protocol restrictions and compliance conditions' for strain with Accession Number {self.pk} is not according to the specification."
f" Your value is {self.value} and the accepted values are 1, 2, 3.")
def STD11(self):
return (f"The 'Strain from a registered collection' for strain with Accession Number {self.pk} is not according to specification."
f" Your value is {self.value} and the accepted values are 1, 2, 3.")
def STD12(self):
return "The 'Risk group' column is a mandatory field in the Strains Sheet. The column can not be empty."
def STD13(self):
return f"The 'Risk group' for strain with Accession Number {self.pk} is missing."
def STD14(self):
return (f"The 'Risk group' for strain with Accession Number {self.pk} is not according to specification."
f" Your value is {self.value} and the accepted values are 1, 2, 3, 4.")
def STD15(self):
return (f"The 'Dual use' for strain with Accession Number {self.pk} is not according to specification."
f" Your value is {self.value} and the accepted values are 1, 2.")
def STD16(self):
return (f"The “Quarantine in europe” for strain with Accession Number {self.pk} is not according to specification."
f" Your value is {self.value} and the accepted values are 1, 2.")
def STD17(self):
return f"The 'Organism type' column is a mandatory field in the Strains Sheet. The column can not be empty."
def STD18(self):
return f"The 'Organism type' for strain with Accession Number {self.pk} is missing."
def STD19(self):
return (f"The 'Organism type' for strain with Accession Number {self.pk} is not according to specification."
f" Your value is {self.value} and the accepted values are 'Algae', 'Archaea', 'Bacteria', 'Cyanobacteria', "
"'Filamentous Fungi', 'Phage', 'Plasmid', 'Virus', 'Yeast', 1, 2, 3, 4, 5, 6, 7, 8, 9.")
def STD20(self):
return f"The 'Taxon name' column is a mandatory field in the Strains Sheet. The column can not be empty."
def STD21(self):
return f"The 'Taxon name' for strain with Accession Number {self.pk} is missing."
def STD22(self):
return f"The 'Taxon name' for strain with Accession Number {self.pk} is incorrect."
def STD23(self):
return (f"The 'Interspecific hybrid' for strain with Accession Number {self.pk} is not according to specification."
f" Your value is {self.value} and the accepted values are 1, 2.")
def STD24(self):
return f"The 'History of deposit' for strain with Accession Number {self.pk} is incorrect."
def STD25(self):
return (f"The 'Date of deposit' for strain with Accession Number {self.pk} is incorrect."
" The allowed formats are 'YYYY-MM-DD', 'YYYYMMDD', 'YYYYMM', and 'YYYY'.")
def STD26(self):
return (f"The 'Date of inclusion in the catalogue' for strain with Accession Number {self.pk} is incorrect."
" The allowed formats are 'YYYY-MM-DD', 'YYYYMMDD', 'YYYYMM', and 'YYYY'.")
def STD27(self):
return (f"The 'Date of collection' for strain with Accession Number {self.pk} is incorrect."
" The allowed formats are 'YYYY-MM-DD', 'YYYYMMDD', 'YYYYMM', and 'YYYY'.")
def STD28(self):
return (f"The 'Date of isolation' for strain with Accession Number {self.pk} is incorrect."
" The allowed formats are 'YYYY-MM-DD', 'YYYYMMDD', 'YYYYMM', and 'YYYY'.")
def STD29(self):
return (f"The 'Tested temperature growth range' for strain with Accession Number {self.pk} is incorrect."
" It must have two decimal numbers separated by ','")
def STD30(self):
return f"The 'Recommended growth temperature' column is a mandatory field in the Strains Sheet. The column can not be empty."
def STD31(self):
return f"The 'Recommended growth temperature' for strain with Accession Number {self.pk} is missing."
def STD32(self):
return (f"The 'Recommended growth temperature' for strain with Accession Number {self.pk} is incorrect."
" It must have two decimal numbers separated by ','.")
def STD33(self):
return f"The 'Recommended medium for growth' column is a mandatory field in the Strains Sheet. The column can not be empty."
def STD34(self):
return f"The 'Recommended medium for growth' for strain with Accession Number {self.pk} is missing."
def STD35(self):
return f"The value of 'Recommended medium for growth' for strain with Accession Number {self.pk} is not in the Growth Media Sheet."
def STD36(self):
return f"The 'Forms of supply' column is a mandatory field in the Strains Sheet. The column can not be empty."
def STD37(self):
return f"The 'Forms of supply' for strain with Accession Number {self.pk} is missing."
def STD38(self):
return f"The value of 'Forms of supply' for strain with Accession Number {self.pk} is not in the Forms of Supply Sheet."
def STD39(self):
return (f"The 'Coordinates of geographic origin' column for strain with Accession Number {self.pk} is incorrect."
"The allowed formats are two or three decimal numbers separated by ','. Moreover, the first number must be"
"between [-90, 90], the second between [-180, 180], and the third, if provided, can assume any value.")
def STD40(self):
return (f"The 'Altitude of geographic origin' column for strain with Accession Number {self.pk} is incorrect."
"The allowed formats are one decimal number between [-200, 8000].")
def STD41(self):
return f"The value of 'Ontobiotope term for the isolation habitat' for strain with Accession Number {self.pk} is not in the Ontobiotope Sheet."
def STD42(self):
return (f"The 'GMO' for strain with Accession Number {self.pk} is not according to specification."
f" Your value is {self.value} and the accepted values are 1, 2")
def STD43(self):
return (f"The 'Sexual State' for strain with Accession Number {self.pk} is not according to specification."
f" Your value is {self.value} and the accepted values are 'Mata', 'Matalpha', 'Mata/Matalpha', "
"'Matb', 'Mata/Matb', 'MTLa', 'MTLalpha', 'MTLa/MTLalpha', 'MAT1-1', 'MAT1-2', 'MAT1', 'MAT2', 'MT+', 'MT-'")
def STD44(self):
return (f"The 'Ploidy' for strain with Accession Number {self.pk} is not according to specification."
f" Your value is {self.value} and the accepted values are 0, 1, 2, 3, 4, 9")
def STD45(self):
msg = f"At least one of the values '{self.value}' of the literature field for strain {self.pk} are not in the literature sheet. "
msg += "If the those values are Pubmed ids or DOIs, please ignore this messsage"
return msg
"""
Genomic Information Error Codes
"""
def GID01(self):
return f"The 'Strain Acession Number' (Strain AN) column is a mandatory field in the Genomic Information Sheet."
def GID02(self):
return f"The 'Strain Acession Number' (Strain AN) column is empty or has missing values."
def GID03(self):
return f"The value of 'Strain Acession Number' (Strain AN) {self.value} is not in the Strains sheet."
def GID04(self):
return f"The 'Marker' column is a mandatory field in the Genomic Information Sheet. The column can not be empty."
def GID05(self):
return f"The 'Marker' for genomic information with Strain AN {self.pk} is missing."
def GID06(self):
return f"The 'Marker' for genomic information with Strain AN {self.pk} is incorrect."
def GID07(self):
return f"The 'INSDC AN' column is a mandatory field in the Genomic Information Sheet. The column can not be empty."
def GID08(self):
return f"The 'INSDC AN' for genomic information with Strain AN {self.pk} is missing."
def GID09(self):
return f"The 'INSDC AN' for genomic information with Strain AN {self.pk} is incorrect."
def GID10(self):
return (f"The 'Sequence' for genomic information with Strain AN {self.pk} is incorrect."
" It must be a sequence of 'G', 'T', 'A', 'C' characteres of any length and without white spaces.")
"""
Ontobiotope Error Codes
"""
def OTD01(self):
return "The 'ID' columns is a mandatory field in the Ontobiotope Sheet."
def OTD02(self):
return "The 'ID' columns is empty or has missing values."
def OTD03(self):
return "The 'Name' columns is a mandatory field in the Ontobiotope Sheet. The column can not be empty."
def OTD04(self):
return f"The 'Name' for ontobiotope with ID {self.pk} is missing."