forked from enviPath/enviPy
Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a8974b1b8 | ||
|
|
20b3e73347 | ||
|
|
8a1ed2fc6d | ||
|
|
a6b901aa47 | ||
|
|
423ddf16d1 | ||
|
|
a7b2e60660 | ||
|
|
ae3a164e74 | ||
|
|
2e2abf0287 |
@@ -0,0 +1,19 @@
|
||||
# Generated by Django 6.0.3 on 2026-11-09 21:43
|
||||
|
||||
import django.utils.timezone
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('bayer', '0006_remove_newsentry_url'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='newsentry',
|
||||
name='publication_date',
|
||||
field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='Date'),
|
||||
),
|
||||
]
|
||||
@@ -272,7 +272,6 @@ def visualize_pes(request):
|
||||
return HttpResponse(image_data, content_type="image/png")
|
||||
|
||||
|
||||
@package_permission_required()
|
||||
def news_detail(request, news_entry_uuid):
|
||||
current_user = _anonymous_or_real(request)
|
||||
context = get_base_context(request, current_user)
|
||||
|
||||
@@ -29,6 +29,8 @@ class SamplingAlgorithm(enum.Enum):
|
||||
class BB4GConfig(EnviPyModel):
|
||||
sampling_algorithm: SamplingAlgorithm = SamplingAlgorithm.EXACT
|
||||
cutoff: int = -5
|
||||
model: str = "rat"
|
||||
mode: str | None = None
|
||||
|
||||
class UI:
|
||||
title = "BB4G Configuration"
|
||||
@@ -44,6 +46,18 @@ class BB4GConfig(EnviPyModel):
|
||||
order=2,
|
||||
placeholder="If unset defaults to -5"
|
||||
)
|
||||
model = UIConfig(
|
||||
widget=WidgetType.TEXT,
|
||||
label="BB4G Model",
|
||||
order=3,
|
||||
placeholder="If unset defaults to rat"
|
||||
)
|
||||
mode = UIConfig(
|
||||
widget=WidgetType.TEXT,
|
||||
label="BB4G Mode",
|
||||
order=4,
|
||||
placeholder="If unset defaults to None"
|
||||
)
|
||||
|
||||
|
||||
# Once stable these will be exposed by enviPy-plugins lib
|
||||
@@ -167,6 +181,8 @@ class BB4G(Classifier):
|
||||
"smiles": smi,
|
||||
"sampling_alg": self.config.sampling_algorithm.value,
|
||||
"cutoff": self.config.cutoff,
|
||||
"model": self.config.model,
|
||||
"mode": self.config.mode,
|
||||
}
|
||||
|
||||
retries = 0
|
||||
|
||||
@@ -2159,6 +2159,7 @@ class CreateEdge(Schema):
|
||||
products: str | None = None # Node URIs comma sep
|
||||
multistep: str | None = None
|
||||
edgeReason: str | None = None
|
||||
probability: float | None = None
|
||||
|
||||
|
||||
@router.post(
|
||||
@@ -2226,6 +2227,10 @@ def add_pathway_edge(request, package_uuid, pathway_uuid, e: Form[CreateEdge]):
|
||||
multi_step=multi_step,
|
||||
)
|
||||
|
||||
if e.probability:
|
||||
new_e.kv["probability"] = e.probability
|
||||
new_e.save()
|
||||
|
||||
# Update depths as sideeffect of above operation
|
||||
pw.update_depths()
|
||||
|
||||
|
||||
+9
-2
@@ -376,9 +376,12 @@ class PackageManager(object):
|
||||
groups = GroupManager.get_groups(user)
|
||||
|
||||
# EDIT START
|
||||
|
||||
if package.classification_level == Package.Classification.SECRET:
|
||||
if package.data_pool not in groups:
|
||||
if user.principal_type == user.PrincipalType.APP:
|
||||
if not user.app_details.secret_allowed or package.data_pool != user.app_details.data_pool:
|
||||
return False
|
||||
|
||||
elif package.data_pool not in groups:
|
||||
return False
|
||||
|
||||
# EDIT END
|
||||
@@ -440,6 +443,10 @@ class PackageManager(object):
|
||||
@staticmethod
|
||||
def check_package_classification(user, pack: Package):
|
||||
if pack.classification_level == Package.Classification.SECRET:
|
||||
if user.principal_type == user.PrincipalType.APP:
|
||||
if pack.data_pool == user.app_details.data_pool:
|
||||
return pack
|
||||
|
||||
if pack.data_pool.user_member.filter(id=user.id).exists():
|
||||
return pack
|
||||
|
||||
|
||||
+102
-15
@@ -2071,7 +2071,10 @@ class Pathway(EnviPathModel, AliasMixin, ScenarioMixin, AdditionalInformationMix
|
||||
def empty_due_to_threshold(self):
|
||||
return self.kv.get("empty_due_to_threshold", False)
|
||||
|
||||
def d3_json(self):
|
||||
def merged_d3_json(self):
|
||||
return self.d3_json(merged=True)
|
||||
|
||||
def d3_json(self, merged=False):
|
||||
# Ideally it would be something like this but
|
||||
# to reduce crossing in edges do a DFS
|
||||
# nodes = [n.d3_json() for n in self.nodes]
|
||||
@@ -2079,15 +2082,68 @@ class Pathway(EnviPathModel, AliasMixin, ScenarioMixin, AdditionalInformationMix
|
||||
nodes = []
|
||||
processed = set()
|
||||
|
||||
structure_to_combined_nodes = dict()
|
||||
node_to_combined_node = dict()
|
||||
queue = list()
|
||||
for n in self.root_nodes:
|
||||
queue.append(n)
|
||||
|
||||
# Add unconnected nodes
|
||||
for n in self.nodes.order_by("url"):
|
||||
if len(n.out_edges.all()) == 0:
|
||||
if n not in queue:
|
||||
queue.append(n)
|
||||
class CombinedNode(object):
|
||||
|
||||
def __init__(self, representative: "Node"):
|
||||
self.representative = representative
|
||||
self.nodes = set([self.representative])
|
||||
|
||||
def ids(self):
|
||||
return [n.id for n in self.nodes]
|
||||
|
||||
def d3_json(self):
|
||||
d3_json = self.representative.d3_json()
|
||||
compound = self.representative.default_node_label.compound
|
||||
d3_json["name"] = compound.get_name()
|
||||
d3_json["smiles"] = compound.default_structure.smiles
|
||||
d3_json["node_label_id"] = compound.default_structure.url
|
||||
d3_json["image"] = f"{compound.default_structure.url}?image=svg",
|
||||
d3_json["image_svg"] = IndigoUtils.mol_to_svg(
|
||||
compound.default_structure.molfile
|
||||
if compound.default_structure.molfile is not None
|
||||
and compound.default_structure.molfile.strip()
|
||||
else compound.default_structure.smiles,
|
||||
width=40,
|
||||
height=40,
|
||||
),
|
||||
|
||||
return d3_json
|
||||
|
||||
def __repr__(self):
|
||||
return f"CombinedNode({self.nodes})"
|
||||
|
||||
if merged:
|
||||
for n in self.nodes:
|
||||
def_struct = n.default_node_label.compound.default_structure
|
||||
if def_struct in structure_to_combined_nodes:
|
||||
structure_to_combined_nodes[def_struct].nodes.add(n)
|
||||
else:
|
||||
cn = CombinedNode(n)
|
||||
structure_to_combined_nodes[def_struct] = cn
|
||||
|
||||
# for n in self.nodes.order_by("url"):
|
||||
# if len(n.out_edges.all()) == 0:
|
||||
# if n not in queue:
|
||||
# queue.append(n)
|
||||
|
||||
for cn in structure_to_combined_nodes.values():
|
||||
for n in cn.nodes:
|
||||
node_to_combined_node[n] = cn
|
||||
|
||||
queue = list(structure_to_combined_nodes.values())
|
||||
else:
|
||||
for n in self.nodes:
|
||||
queue.append(n)
|
||||
|
||||
# Add unconnected nodes
|
||||
for n in self.nodes.order_by("url"):
|
||||
if len(n.out_edges.all()) == 0:
|
||||
if n not in queue:
|
||||
queue.append(n)
|
||||
|
||||
for i in queue:
|
||||
processed.add(i)
|
||||
@@ -2097,25 +2153,56 @@ class Pathway(EnviPathModel, AliasMixin, ScenarioMixin, AdditionalInformationMix
|
||||
processed.add(current)
|
||||
nodes.append(current.d3_json())
|
||||
|
||||
for e in self.edges.filter(start_nodes=current).order_by("url").distinct():
|
||||
if merged:
|
||||
q = Q(start_nodes__in=current.ids())
|
||||
else:
|
||||
q = Q(start_nodes=current)
|
||||
|
||||
for e in self.edges.filter(q).order_by("url").distinct():
|
||||
for prod in e.end_nodes.all().order_by("url"):
|
||||
if prod not in queue and prod not in processed:
|
||||
queue.append(prod)
|
||||
|
||||
if merged:
|
||||
def_struct = n.default_node_label.compound.default_structure
|
||||
if def_struct in structure_to_combined_nodes:
|
||||
structure_to_combined_nodes[def_struct].nodes.add(n)
|
||||
else:
|
||||
cn = CombinedNode(n)
|
||||
structure_to_combined_nodes[def_struct] = cn
|
||||
if cn not in queue and cn not in processed:
|
||||
queue.append(cn)
|
||||
else:
|
||||
if prod not in queue and prod not in processed:
|
||||
queue.append(prod)
|
||||
|
||||
# We shouldn't lose or make up nodes...
|
||||
if len(nodes) != len(self.nodes):
|
||||
logger.debug(
|
||||
f"{self.get_name()}: Num Nodes {len(nodes)} vs. DB Nodes {len(self.nodes)}"
|
||||
)
|
||||
if not merged:
|
||||
if len(nodes) != len(self.nodes):
|
||||
logger.debug(
|
||||
f"{self.get_name()}: Num Nodes {len(nodes)} vs. DB Nodes {len(self.nodes)}"
|
||||
)
|
||||
|
||||
links = [e.d3_json() for e in self.edges]
|
||||
|
||||
# D3 links Nodes based on indices in nodes array
|
||||
combined_node_depth_to_idx = dict()
|
||||
node_url_to_idx = dict()
|
||||
for i, n in enumerate(nodes):
|
||||
n["id"] = i
|
||||
node_url_to_idx[n["url"]] = i
|
||||
|
||||
# Add potential missing mappings
|
||||
if merged:
|
||||
cn_idx_mapping = dict()
|
||||
for n in nodes:
|
||||
for cn in processed:
|
||||
for sub_n in cn.nodes:
|
||||
if n["url"] == sub_n.url:
|
||||
cn_idx_mapping[cn] = n["id"]
|
||||
|
||||
for n in processed:
|
||||
for sub_n in n.nodes:
|
||||
node_url_to_idx[sub_n.url] = cn_idx_mapping[n]
|
||||
|
||||
adjusted_links = []
|
||||
for link in links:
|
||||
# Check if we'll need pseudo nodes
|
||||
|
||||
@@ -2313,6 +2313,7 @@ def package_pathway(request, package_uuid, pathway_uuid):
|
||||
|
||||
context["pathway"] = current_pathway
|
||||
context["current_object"] = current_pathway
|
||||
context["merged"] = request.GET.get("merged", False) == "true"
|
||||
|
||||
context["breadcrumbs"] = [
|
||||
{"Home": s.SERVER_URL},
|
||||
|
||||
@@ -15,7 +15,6 @@ dependencies = [
|
||||
"django-polymorphic>=4.1.0",
|
||||
"enviformer",
|
||||
"envipy-additional-information",
|
||||
"envipy-ambit>=0.1.0",
|
||||
"envipy-plugins",
|
||||
"epam-indigo>=1.30.1",
|
||||
"gunicorn>=23.0.0",
|
||||
|
||||
@@ -266,7 +266,7 @@
|
||||
|
||||
<div id="services-container" class="flex justify-center gap-4">
|
||||
{% for ne in news_entries %}
|
||||
<div class="card-body flex flex-col h-full justify-between p-5">
|
||||
<div class="card-body flex flex-col h-full justify-between p-5 w-96"> <!-- Fixed width applied via w-96 -->
|
||||
<div>
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
<div class="bg-primary/10 text-primary rounded-lg p-1.5">
|
||||
@@ -296,6 +296,7 @@
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mt-6 text-right">
|
||||
<a
|
||||
href="https://community.envipath.org/c/announcements/10"
|
||||
|
||||
@@ -227,6 +227,29 @@
|
||||
Reaction Names
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% if merged %}{{ current_object.url }}{% else %}{{ current_object.url }}?merged=true{% endif %}" id="merged-toggle-button" class="cursor-pointer">
|
||||
<svg
|
||||
id="merged-icon"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-eye"
|
||||
>
|
||||
<path
|
||||
d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"
|
||||
/>
|
||||
<circle cx="12" cy="12" r="3" />
|
||||
</svg>
|
||||
Merged View
|
||||
</a>
|
||||
</li>
|
||||
{% if pathway.setting.model.app_domain %}
|
||||
<li>
|
||||
<a id="app-domain-toggle-button" class="cursor-pointer">
|
||||
@@ -544,8 +567,11 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if merged %}
|
||||
{{ pathway.merged_d3_json|json_script:"pathway" }}
|
||||
{% else %}
|
||||
{{ pathway.d3_json|json_script:"pathway" }}
|
||||
|
||||
{% endif %}
|
||||
<script>
|
||||
// Global switch for compound names view
|
||||
var compoundNamesViewEnabled = false;
|
||||
@@ -557,6 +583,8 @@
|
||||
var timeseriesViewEnabled = false;
|
||||
// Predicted Property View
|
||||
var predictedPropertyViewEnabled = false;
|
||||
// Merged View
|
||||
var mergedViewEnabled = new URLSearchParams(window.location.search).get("merged") !== null;
|
||||
|
||||
function goFullscreen(id) {
|
||||
var element = document.getElementById(id);
|
||||
@@ -702,6 +730,23 @@
|
||||
});
|
||||
}
|
||||
|
||||
const mergedViewBtn = document.getElementById(
|
||||
"merged-toggle-button",
|
||||
);
|
||||
if (mergedViewBtn) {
|
||||
const icon = document.getElementById("merged-icon");
|
||||
if (mergedViewEnabled) {
|
||||
// Change to eye-off icon
|
||||
icon.innerHTML =
|
||||
'<path d="M9.88 9.88a3 3 0 1 0 4.24 4.24"/><path d="M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68"/><path d="M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61"/><line x1="2" x2="22" y1="2" y2="22"/>';
|
||||
} else {
|
||||
// Change back to eye icon
|
||||
icon.innerHTML =
|
||||
'<path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/>';
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Timeseries toggle
|
||||
const timeseriesBtn = document.getElementById("timeseries-toggle-button");
|
||||
if (timeseriesBtn) {
|
||||
|
||||
@@ -214,6 +214,7 @@ class EdgeExportSchema(RefEdgeExportSchema):
|
||||
start_nodes: List[RefNodeExportSchema]
|
||||
end_nodes: List[RefNodeExportSchema]
|
||||
scenarios: List[RefScenarioExportSchema]
|
||||
kv: Optional[dict]
|
||||
|
||||
|
||||
class PathwayExportSchema(RefPathwayExportSchema):
|
||||
@@ -623,6 +624,7 @@ class PackageImporter:
|
||||
new_e.description = e.description
|
||||
new_e.aliases = e.aliases
|
||||
new_e.edge_label = self._cache[e.edge_label.uuid]
|
||||
new_e.kv = e.kv
|
||||
new_e.save()
|
||||
|
||||
for sn in e.start_nodes:
|
||||
|
||||
@@ -802,7 +802,6 @@ dependencies = [
|
||||
{ name = "django-polymorphic" },
|
||||
{ name = "enviformer" },
|
||||
{ name = "envipy-additional-information" },
|
||||
{ name = "envipy-ambit" },
|
||||
{ name = "envipy-plugins" },
|
||||
{ name = "epam-indigo" },
|
||||
{ name = "gunicorn" },
|
||||
@@ -859,7 +858,6 @@ requires-dist = [
|
||||
{ name = "emcee", marker = "extra == 'pepper-plugin'", specifier = ">=3.1.6" },
|
||||
{ name = "enviformer", git = "ssh://git@git.envipath.com/enviPath/enviformer.git?rev=main" },
|
||||
{ name = "envipy-additional-information", git = "ssh://git@git.envipath.com/enviPath/enviPy-additional-information.git?branch=develop" },
|
||||
{ name = "envipy-ambit", git = "ssh://git@git.envipath.com/enviPath/enviPy-ambit.git" },
|
||||
{ name = "envipy-plugins", git = "ssh://git@git.envipath.com/enviPath/enviPy-plugins.git?rev=v0.1.0" },
|
||||
{ name = "epam-indigo", specifier = ">=1.30.1" },
|
||||
{ name = "gunicorn", specifier = ">=23.0.0" },
|
||||
@@ -899,14 +897,6 @@ dependencies = [
|
||||
{ name = "pydantic" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "envipy-ambit"
|
||||
version = "0.1.0"
|
||||
source = { git = "ssh://git@git.envipath.com/enviPath/enviPy-ambit.git#0c424ba153105a54f758569a784d5871989338d8" }
|
||||
dependencies = [
|
||||
{ name = "jpype1" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "envipy-plugins"
|
||||
version = "0.1.0"
|
||||
@@ -1190,30 +1180,6 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/e8/685f47e0d754320684db4425a0967f7d3fa70126bffd76110b7009a0090f/joblib-1.5.2-py3-none-any.whl", hash = "sha256:4e1f0bdbb987e6d843c70cf43714cb276623def372df3c22fe5266b2670bc241", size = 308396, upload-time = "2025-08-27T12:15:45.188Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jpype1"
|
||||
version = "1.6.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "packaging" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/34/49/6090a131d84b22c6aae13b1853092028b060fd17da1af87c0e42ad69d50f/jpype1-1.6.0.tar.gz", hash = "sha256:2d46b2a14f8f0e6f17d8aa22b4fc3a64b2790851ebf1409ad79a37c698fd6e9a", size = 1057888, upload-time = "2025-07-07T14:04:11.244Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/38/88/2156a27251492169f947850293d9870d49d784f1355fad7e920095636721/jpype1-1.6.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:5454322887505097c46f41521becf31cda2303f54e35cb42e20f1a180055a558", size = 582187, upload-time = "2025-07-07T13:50:39.034Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/5d/51bde8695cc3eabcc465779f6dc23b149194bbcdcb8d221a9572422053f4/jpype1-1.6.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cf646459023a0dd71b3cc3aeeb977225a93f94c97839bb4e6146977b166c7caf", size = 468341, upload-time = "2025-07-07T13:50:40.739Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7a/a1/50cdc2bf9e51c0828faabec6fad50d61aada5a57d0bc435f4db0c16eb2ca/jpype1-1.6.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:7a98b34bc68a117881382dffa9b02d5e1d0d94325f85d7f564c33cc9e9d2916b", size = 511724, upload-time = "2025-07-07T13:50:42.479Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/a4/6038228e44cbcdb8f96ff2518cd6c577730f31fb62e9f46de7efdfabc2de/jpype1-1.6.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b56d7b662ce353c7f876e9ff3d4e775918348340795801e1f00c3b6241006264", size = 495897, upload-time = "2025-07-07T13:50:44.018Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/e4/af69d43779da0e49d37d7fd8a4a01bede03f6a3bab450eab1c10cf48e20e/jpype1-1.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:cf41134bc59c28de2721614ed00a34f76f69f2b525583a5c42fee5c7bae05d40", size = 355702, upload-time = "2025-07-07T13:50:45.368Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3f/1b/7167cfb702cfbcb17b0973150608f9cb92c3f409ebaaff655f7389617766/jpype1-1.6.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ce1da9ff01010a4529de194aecc053bfc8ab25440ea6b63579ef8c8d381da21d", size = 582384, upload-time = "2025-07-07T13:50:47.418Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c0/48/8ae425d8842bc76eb51052bbea5941dac230c8f6b58614ef2b7cb2da1a74/jpype1-1.6.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4a387430cd4f3f68761013dca7f71b79d8d64b47dfd56eedcbd44c894d98d7f2", size = 468237, upload-time = "2025-07-07T13:50:48.925Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/2f/dbdc15aa99404dda0315a9883add7422c9ac7acce28ce24b66c89052c2fb/jpype1-1.6.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:6c9d99f41a5d05a8a2b6aeda796f646904c1c2b68aed0cc9a3bbc165483d9e1e", size = 511905, upload-time = "2025-07-07T13:50:50.87Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/00/0d/50fcdd6d3bb42a87cbda8b04fc72283a9c6d955ada0d011190ce31e0e027/jpype1-1.6.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:55ba7257988a69bee84f7cd1444131725d5447999149fdafdba25bf46e4b1a3f", size = 496001, upload-time = "2025-07-07T13:50:52.711Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/b8/25214a9ebecbd31447b685500dca5fe2ac070df38358d6823f591a8ce52e/jpype1-1.6.0-cp313-cp313-win_amd64.whl", hash = "sha256:ef8dd72442d91cde7e5eefef24ab71323cdd4137283a59f79d265a6620f7d0ab", size = 355727, upload-time = "2025-07-07T13:51:00.402Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/29/a0/b2347572998020de8ce3ee0a285a1b84b052b522e8d452ee9ad330570918/jpype1-1.6.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:dc0c1c8b989b9857f87648980a746084b323858b0450225eab3642bb674645d6", size = 471150, upload-time = "2025-07-07T13:50:54.254Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/62/5e0f64a185f37303d0dd07e7b7a927cd5237fdc3c8176add949ed8cafaa2/jpype1-1.6.0-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:cbbba16381ccd23530ad4ef09f7b2b1b12bd7fd0f6ca9fe4c7b4e3da8fe4cf63", size = 514015, upload-time = "2025-07-07T13:50:56.299Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/72/68/84050ed2679e2d2ee2030a60d3e5a59a29d0533cd03fd8d9891e36592b0f/jpype1-1.6.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1a3814e4f65d67e36bdb03b8851d5ece8d7a408aa3a24251ea0609bb8fba77dd", size = 497229, upload-time = "2025-07-07T13:50:57.842Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jsonref"
|
||||
version = "1.1.0"
|
||||
|
||||
Reference in New Issue
Block a user