forked from enviPath/enviPy
[Chore] Leftovers (#426)
Co-authored-by: Tim Lorsbach <tim@lorsba.ch> Reviewed-on: enviPath/enviPy#426
This commit is contained in:
@ -1620,7 +1620,7 @@ class PathwayNode(Schema):
|
||||
image: str = Field(None, alias="image")
|
||||
imageSize: int = Field(None, alias="image_size")
|
||||
name: str = Field(None, alias="name")
|
||||
proposed: List[Dict[str, str]] = Field([], alias="proposed_intermediate")
|
||||
proposed: List[Dict[str, str]] = []
|
||||
smiles: str = Field(None, alias="smiles")
|
||||
pseudo: bool = Field(False, alias="pseudo")
|
||||
|
||||
@ -1910,7 +1910,7 @@ def add_pathway_node(request, package_uuid, pathway_uuid, n: Form[CreateNode]):
|
||||
else:
|
||||
node_depth = -1
|
||||
|
||||
n = Node.create(
|
||||
node = Node.create(
|
||||
pw,
|
||||
n.nodeAsSmiles,
|
||||
node_depth,
|
||||
@ -1919,7 +1919,7 @@ def add_pathway_node(request, package_uuid, pathway_uuid, n: Form[CreateNode]):
|
||||
description=n.nodeReason,
|
||||
)
|
||||
|
||||
return redirect(n.url)
|
||||
return redirect(node.url)
|
||||
except ValueError:
|
||||
return 403, {"message": "Adding node failed!"}
|
||||
|
||||
|
||||
@ -1008,8 +1008,6 @@ class PackageManager(object):
|
||||
data: Dict[str, Any],
|
||||
owner: User,
|
||||
preserve_uuids=False,
|
||||
add_import_timestamp=True,
|
||||
trust_reviewed=False,
|
||||
) -> Package:
|
||||
importer = PackageImporter(data, preserve_uuids)
|
||||
imported_package = importer.do_import()
|
||||
@ -1830,6 +1828,7 @@ class SPathway(object):
|
||||
|
||||
if edge.rule:
|
||||
e["rule"] = edge.rule.simple_json()
|
||||
|
||||
if edge.probability:
|
||||
e["probability"] = edge.probability
|
||||
|
||||
|
||||
115
epdb/models.py
115
epdb/models.py
@ -894,34 +894,46 @@ class Compound(
|
||||
if parsed is None:
|
||||
raise InvalidSMILESException("Given SMILES is invalid")
|
||||
|
||||
if name is not None:
|
||||
# Clean for potential XSS
|
||||
name = nh3.clean(name, tags=s.ALLOWED_HTML_TAGS).strip()
|
||||
|
||||
standardized_smiles = FormatConverter.standardize(smiles, remove_stereo=True)
|
||||
|
||||
qs = CompoundStructure.objects.filter(smiles=smiles, compound__package=package)
|
||||
|
||||
# Check if we find a direct match for a given SMILES
|
||||
if CompoundStructure.objects.filter(smiles=smiles, compound__package=package).exists():
|
||||
return CompoundStructure.objects.get(smiles=smiles, compound__package=package).compound
|
||||
if qs.exists():
|
||||
found_structure = qs.first()
|
||||
found_compound = found_structure.compound
|
||||
|
||||
if name:
|
||||
found_structure.add_alias(name)
|
||||
found_compound.add_alias(name)
|
||||
|
||||
return found_compound
|
||||
|
||||
qs = CompoundStructure.objects.filter(smiles=standardized_smiles, compound__package=package)
|
||||
|
||||
# Check if we can find the standardized one
|
||||
if CompoundStructure.objects.filter(
|
||||
smiles=standardized_smiles, compound__package=package
|
||||
).exists():
|
||||
found_c = CompoundStructure.objects.get(
|
||||
smiles=standardized_smiles, compound__package=package
|
||||
).compound
|
||||
if qs.exists():
|
||||
found_structure = qs.first()
|
||||
found_compound = found_structure.compound
|
||||
|
||||
# As a direct match wasn't found add a new structure
|
||||
# TODO return newly created structure
|
||||
_ = found_c.add_structure(smiles, molfile=molfile, name=name, description=description)
|
||||
# We've only found the standardized one, create the very structure
|
||||
_ = found_compound.add_structure(
|
||||
smiles, molfile=molfile, name=name, description=description
|
||||
)
|
||||
|
||||
return found_c
|
||||
if name:
|
||||
found_compound.add_alias(name)
|
||||
|
||||
return found_compound
|
||||
|
||||
# Generate Compound
|
||||
c = Compound()
|
||||
c.package = package
|
||||
|
||||
if name is not None:
|
||||
# Clean for potential XSS
|
||||
name = nh3.clean(name, tags=s.ALLOWED_HTML_TAGS).strip()
|
||||
|
||||
if name is None or name == "":
|
||||
name = f"Compound {Compound.objects.filter(package=package).count() + 1}"
|
||||
|
||||
@ -1218,8 +1230,15 @@ class CompoundStructure(
|
||||
# Overwrite SMILES from molfile
|
||||
smiles = FormatConverter.to_smiles(mol)
|
||||
|
||||
# Clean for potential XSS
|
||||
if name is not None:
|
||||
name = nh3.clean(name, tags=s.ALLOWED_HTML_TAGS).strip()
|
||||
|
||||
if CompoundStructure.objects.filter(compound=compound, smiles=smiles).exists():
|
||||
found_cs = CompoundStructure.objects.get(smiles=smiles, compound=compound)
|
||||
found_cs = CompoundStructure.objects.get(compound=compound, smiles=smiles)
|
||||
|
||||
if name:
|
||||
found_cs.add_alias(name)
|
||||
|
||||
if found_cs.molfile is None and (molfile is not None and molfile.strip() != ""):
|
||||
logger.info(
|
||||
@ -1236,16 +1255,17 @@ class CompoundStructure(
|
||||
cs = CompoundStructure()
|
||||
# Clean for potential XSS
|
||||
if name is not None:
|
||||
cs.name = nh3.clean(name, tags=s.ALLOWED_HTML_TAGS).strip()
|
||||
cs.name = name
|
||||
|
||||
if description is not None:
|
||||
# We have a default here only set the value if it carries some payload
|
||||
if description is not None and description.strip() != "":
|
||||
cs.description = nh3.clean(description, tags=s.ALLOWED_HTML_TAGS).strip()
|
||||
|
||||
cs.compound = compound
|
||||
cs.smiles = smiles
|
||||
|
||||
# Check if molfile is present and valid
|
||||
if molfile is not None and molfile.strip() != "":
|
||||
# If molfile is not None, it hase to be a valid Molfile as we've survived the parsing check
|
||||
if molfile is not None:
|
||||
cs.molfile = molfile
|
||||
|
||||
if "normalized_structure" in kwargs:
|
||||
@ -1464,6 +1484,9 @@ class SimpleAmbitRule(SimpleRule):
|
||||
if not FormatConverter.is_valid_smirks(smirks):
|
||||
raise ValueError(f'SMIRKS "{smirks}" is invalid!')
|
||||
|
||||
if name is not None:
|
||||
name = nh3.clean(name, tags=s.ALLOWED_HTML_TAGS).strip()
|
||||
|
||||
query = SimpleAmbitRule.objects.filter(package=package, smirks=smirks)
|
||||
|
||||
if reactant_filter_smarts is not None and reactant_filter_smarts.strip() != "":
|
||||
@ -1475,14 +1498,17 @@ class SimpleAmbitRule(SimpleRule):
|
||||
if query.exists():
|
||||
if query.count() > 1:
|
||||
logger.error(f"More than one rule matched this one! {query}")
|
||||
return query.first()
|
||||
|
||||
found_rule = query.first()
|
||||
|
||||
if name:
|
||||
found_rule.add_alias(name)
|
||||
|
||||
return found_rule
|
||||
|
||||
r = SimpleAmbitRule()
|
||||
r.package = package
|
||||
|
||||
if name is not None:
|
||||
name = nh3.clean(name, tags=s.ALLOWED_HTML_TAGS).strip()
|
||||
|
||||
if name is None or name == "":
|
||||
name = f"Rule {Rule.objects.filter(package=package).count() + 1}"
|
||||
|
||||
@ -1615,6 +1641,9 @@ class ParallelRule(Rule):
|
||||
f"Simple rule {sr.uuid} does not belong to package {package.uuid}!"
|
||||
)
|
||||
|
||||
if name is not None:
|
||||
name = nh3.clean(name, tags=s.ALLOWED_HTML_TAGS).strip()
|
||||
|
||||
# Deduplication check
|
||||
query = ParallelRule.objects.annotate(
|
||||
srs_count=Count("simple_rules", filter=Q(simple_rules__in=simple_rules), distinct=True)
|
||||
@ -1626,15 +1655,19 @@ class ParallelRule(Rule):
|
||||
|
||||
if existing_rule_qs.exists():
|
||||
if existing_rule_qs.count() > 1:
|
||||
logger.error(f"Found more than one reaction for given input! {existing_rule_qs}")
|
||||
return existing_rule_qs.first()
|
||||
logger.error(
|
||||
f"Found more than one ParallelRule for given input! {existing_rule_qs}"
|
||||
)
|
||||
|
||||
found_rule = existing_rule_qs.first()
|
||||
if name:
|
||||
found_rule.add_alias(name)
|
||||
|
||||
return found_rule
|
||||
|
||||
r = ParallelRule()
|
||||
r.package = package
|
||||
|
||||
if name is not None:
|
||||
name = nh3.clean(name, tags=s.ALLOWED_HTML_TAGS).strip()
|
||||
|
||||
if name is None or name == "":
|
||||
name = f"Rule {Rule.objects.filter(package=package).count() + 1}"
|
||||
|
||||
@ -1730,6 +1763,10 @@ class Reaction(
|
||||
rules: Union[Rule | List[Rule]] = None,
|
||||
multi_step: bool = False,
|
||||
):
|
||||
# Clean for potential XSS
|
||||
if name is not None and name.strip() != "":
|
||||
name = nh3.clean(name, tags=s.ALLOWED_HTML_TAGS).strip()
|
||||
|
||||
_educts = []
|
||||
_products = []
|
||||
|
||||
@ -1784,14 +1821,21 @@ class Reaction(
|
||||
logger.error(
|
||||
f"Found more than one reaction for given input! {existing_reaction_qs}"
|
||||
)
|
||||
return existing_reaction_qs.first()
|
||||
|
||||
found_reaction = existing_reaction_qs.first()
|
||||
|
||||
if name:
|
||||
found_reaction.add_alias(name)
|
||||
|
||||
return found_reaction
|
||||
|
||||
r = Reaction()
|
||||
r.package = package
|
||||
|
||||
# Clean for potential XSS
|
||||
if name is not None and name.strip() != "":
|
||||
r.name = nh3.clean(name, tags=s.ALLOWED_HTML_TAGS).strip()
|
||||
if name is None or name == "":
|
||||
name = f"Reaction {Reaction.objects.filter(package=package).count() + 1}"
|
||||
|
||||
r.name = name
|
||||
|
||||
if description is not None and description.strip() != "":
|
||||
r.description = nh3.clean(description, tags=s.ALLOWED_HTML_TAGS).strip()
|
||||
@ -2420,6 +2464,7 @@ class Node(EnviPathModel, AliasMixin, ScenarioMixin, AdditionalInformationMixin)
|
||||
},
|
||||
"predicted_properties": predicted_properties,
|
||||
"is_engineered_intermediate": self.kv.get("is_engineered_intermediate", False),
|
||||
"proposed": self.get_proposed_info(),
|
||||
"timeseries": self.get_timeseries_data(),
|
||||
**structure_data,
|
||||
}
|
||||
@ -2516,7 +2561,7 @@ class Node(EnviPathModel, AliasMixin, ScenarioMixin, AdditionalInformationMixin)
|
||||
|
||||
return res
|
||||
|
||||
def is_proposed_intermediate(self):
|
||||
def get_proposed_info(self):
|
||||
collected = defaultdict(dict)
|
||||
for ai in self.additional_information.filter(
|
||||
type__in=["ProposedIntermediate", "TransformationProductImportance", "Confidence"],
|
||||
|
||||
@ -134,7 +134,7 @@
|
||||
<!-- Reactions -->
|
||||
{% if compound.related_reactions %}
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<input type="checkbox" />
|
||||
<div class="collapse-title text-xl font-medium">Reactions</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
@ -153,7 +153,7 @@
|
||||
<!-- Pathways -->
|
||||
{% if compound.related_pathways %}
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<input type="checkbox" />
|
||||
<div class="collapse-title text-xl font-medium">Pathways</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
@ -172,7 +172,7 @@
|
||||
<!-- Scenarios -->
|
||||
{% if compound.scenarios.all %}
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<input type="checkbox" />
|
||||
<div class="collapse-title text-xl font-medium">Scenarios</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
@ -240,7 +240,7 @@
|
||||
<!-- External Identifiers -->
|
||||
{% if compound.get_external_identifiers %}
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<input type="checkbox" />
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
External Identifier
|
||||
</div>
|
||||
|
||||
@ -92,6 +92,25 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Pathways -->
|
||||
{% if compound.related_pathways %}
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" />
|
||||
<div class="collapse-title text-xl font-medium">Pathways</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
{% for r in compound.related_pathways %}
|
||||
<li>
|
||||
<a href="{{ r.url }}" class="hover:bg-base-200"
|
||||
>{{ r.name }} <i>({{ r.package.name }})</i></a
|
||||
>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if compound_structure.half_lifes %}
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" />
|
||||
@ -144,7 +163,7 @@
|
||||
{% if compound_structure.scenarios.all %}
|
||||
<!-- Scenarios -->
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" checked />
|
||||
<input type="checkbox" />
|
||||
<div class="collapse-title text-xl font-medium">Scenarios</div>
|
||||
<div class="collapse-content">
|
||||
<ul class="menu bg-base-100 rounded-box">
|
||||
|
||||
@ -106,7 +106,7 @@ class ReactionTest(TestCase):
|
||||
multi_step=False,
|
||||
)
|
||||
|
||||
self.assertEqual(r.name, "no name")
|
||||
self.assertEqual(r.name, "Reaction 1")
|
||||
self.assertEqual(r.description, "no description")
|
||||
|
||||
def test_deduplication(self):
|
||||
|
||||
Reference in New Issue
Block a user