cmem-cmemc 24.3.0rc1__tar.gz → 24.3.0rc2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/PKG-INFO +1 -1
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/commands/graph.py +76 -19
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/commands/migration.py +2 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/commands/python.py +2 -2
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/completion.py +11 -5
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/migrations/access_conditions_243.py +4 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/migrations/bootstrap_data.py +2 -4
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/migrations/shapes_widget_integrations_243.py +80 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/string_processor.py +7 -1
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/utils.py +18 -30
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/pyproject.toml +1 -1
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/LICENSE +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/README-public.md +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/__init__.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/_cmemc.zsh +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/command.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/command_group.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/commands/__init__.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/commands/acl.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/commands/admin.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/commands/client.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/commands/config.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/commands/dataset.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/commands/metrics.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/commands/project.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/commands/query.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/commands/resource.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/commands/scheduler.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/commands/store.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/commands/user.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/commands/validation.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/commands/variable.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/commands/vocabulary.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/commands/workflow.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/commands/workspace.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/constants.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/context.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/exceptions.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/manual_helper/__init__.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/manual_helper/graph.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/manual_helper/multi_page.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/manual_helper/single_page.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/migrations/__init__.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/migrations/abc.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/migrations/workspace_configurations.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/object_list.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/parameter_types/__init__.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/parameter_types/path.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/smart_path/__init__.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/smart_path/clients/__init__.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/smart_path/clients/http.py +0 -0
- {cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/title_helper.py +0 -0
|
@@ -4,13 +4,16 @@ import gzip
|
|
|
4
4
|
import hashlib
|
|
5
5
|
import io
|
|
6
6
|
import json
|
|
7
|
+
import mimetypes
|
|
7
8
|
import os
|
|
9
|
+
from json import JSONDecodeError
|
|
8
10
|
from xml.dom import minidom # nosec
|
|
9
11
|
from xml.etree.ElementTree import ( # nosec
|
|
10
12
|
Element,
|
|
11
13
|
SubElement,
|
|
12
14
|
tostring,
|
|
13
15
|
)
|
|
16
|
+
from xml.sax import SAXParseException
|
|
14
17
|
|
|
15
18
|
import click
|
|
16
19
|
from click import Argument
|
|
@@ -20,6 +23,9 @@ from cmem.cmempy.dp.proxy import graph as graph_api
|
|
|
20
23
|
from cmem.cmempy.dp.proxy.graph import get_graph_import_tree, get_graph_imports
|
|
21
24
|
from cmem.cmempy.dp.proxy.sparql import get as sparql_api
|
|
22
25
|
from jinja2 import Template
|
|
26
|
+
from rdflib import Graph
|
|
27
|
+
from rdflib.exceptions import ParserError
|
|
28
|
+
from rdflib.plugins.parsers.notation3 import BadSyntax
|
|
23
29
|
from six.moves.urllib.parse import quote
|
|
24
30
|
from treelib import Tree
|
|
25
31
|
|
|
@@ -103,7 +109,7 @@ def _get_graph_to_file( # noqa: PLR0913
|
|
|
103
109
|
|
|
104
110
|
|
|
105
111
|
def _get_export_names(
|
|
106
|
-
app: ApplicationContext, iris: list[str], template: str, file_extension: str = "ttl"
|
|
112
|
+
app: ApplicationContext, iris: list[str], template: str, file_extension: str = ".ttl"
|
|
107
113
|
) -> dict:
|
|
108
114
|
"""Get a dictionary of generated file names based on a template.
|
|
109
115
|
|
|
@@ -131,7 +137,7 @@ def _get_export_names(
|
|
|
131
137
|
hash=hashlib.sha256(iri.encode("utf-8")).hexdigest(),
|
|
132
138
|
iriname=convert_uri_to_filename(iri),
|
|
133
139
|
)
|
|
134
|
-
_name_created = f"{Template(template).render(template_data)}
|
|
140
|
+
_name_created = f"{Template(template).render(template_data)}{file_extension}"
|
|
135
141
|
_names[iri] = _name_created
|
|
136
142
|
if len(_names.values()) != len(set(_names.values())):
|
|
137
143
|
raise ValueError(
|
|
@@ -542,9 +548,9 @@ def _validate_export_command_input_parameters(
|
|
|
542
548
|
)
|
|
543
549
|
@click.option(
|
|
544
550
|
"--mime-type",
|
|
545
|
-
default="
|
|
551
|
+
default="text/turtle",
|
|
546
552
|
show_default=True,
|
|
547
|
-
type=click.Choice(["application/n-triples", "text/turtle"]),
|
|
553
|
+
type=click.Choice(["application/n-triples", "text/turtle", "application/rdf+xml"]),
|
|
548
554
|
help="Define the requested mime type",
|
|
549
555
|
)
|
|
550
556
|
@click.option(
|
|
@@ -589,8 +595,11 @@ def export_command( # noqa: PLR0913
|
|
|
589
595
|
app.echo_debug("output is directory")
|
|
590
596
|
# pre-calculate all filenames with the template,
|
|
591
597
|
# in order to output errors on naming clashes as early as possible
|
|
592
|
-
|
|
593
|
-
|
|
598
|
+
extension = mimetypes.guess_extension(mime_type)
|
|
599
|
+
_names = _get_export_names(
|
|
600
|
+
app, iris, template, f"{extension}.gz" if compress else f"{extension}"
|
|
601
|
+
)
|
|
602
|
+
_graph_file_names = _get_export_names(app, iris, template, f"{extension}.graph")
|
|
594
603
|
# create directory
|
|
595
604
|
if not Path(output_dir).exists():
|
|
596
605
|
app.echo_warning("Output directory does not exist: " + "will create it.")
|
|
@@ -661,6 +670,57 @@ def validate_input_path(input_path: str) -> None:
|
|
|
661
670
|
)
|
|
662
671
|
|
|
663
672
|
|
|
673
|
+
def _get_graph_supported_formats() -> dict[str, str]:
|
|
674
|
+
return {
|
|
675
|
+
"application/rdf+xml": "xml",
|
|
676
|
+
"application/ld+json": "json-ld",
|
|
677
|
+
"text/turtle": "turtle",
|
|
678
|
+
"application/n-triples": "nt",
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
def _guess_rdf_mime_type(content: str) -> str:
|
|
683
|
+
formats = _get_graph_supported_formats()
|
|
684
|
+
for mime_type, rdf_format in formats.items():
|
|
685
|
+
try:
|
|
686
|
+
g = Graph()
|
|
687
|
+
g.parse(data=content, format=rdf_format)
|
|
688
|
+
except (SAXParseException, JSONDecodeError, BadSyntax, ParserError):
|
|
689
|
+
continue
|
|
690
|
+
else:
|
|
691
|
+
return mime_type
|
|
692
|
+
raise ValueError("Unknown format")
|
|
693
|
+
|
|
694
|
+
|
|
695
|
+
def _parse_triple_file(triple_file: str) -> tuple[io.BytesIO, str]:
|
|
696
|
+
"""Parse the content of the triple file."""
|
|
697
|
+
buffer = io.BytesIO()
|
|
698
|
+
transport_params = {}
|
|
699
|
+
|
|
700
|
+
if Path(str(triple_file)).schema in ["http", "https"]:
|
|
701
|
+
transport_params["headers"] = {
|
|
702
|
+
"Accept": "text/turtle; q=1.0, application/x-turtle; q=0.9, text/n3;"
|
|
703
|
+
" q=0.8, application/rdf+xml; q=0.5, text/plain; q=0.1"
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
with ClickSmartPath.open(triple_file, transport_params=transport_params) as file_obj:
|
|
707
|
+
buffer.write(file_obj.read())
|
|
708
|
+
|
|
709
|
+
buffer.seek(0)
|
|
710
|
+
is_gzip = buffer.read(2) == b"\x1f\x8b"
|
|
711
|
+
buffer.seek(0)
|
|
712
|
+
|
|
713
|
+
if is_gzip:
|
|
714
|
+
with gzip.GzipFile(fileobj=buffer, mode="rb") as gzip_file:
|
|
715
|
+
graph_content = gzip_file.read().decode("utf-8")
|
|
716
|
+
else:
|
|
717
|
+
graph_content = buffer.read().decode("utf-8")
|
|
718
|
+
|
|
719
|
+
content_type = _guess_rdf_mime_type(graph_content)
|
|
720
|
+
buffer.seek(0)
|
|
721
|
+
return buffer, content_type
|
|
722
|
+
|
|
723
|
+
|
|
664
724
|
@click.command(cls=CmemcCommand, name="import")
|
|
665
725
|
@click.option(
|
|
666
726
|
"--replace",
|
|
@@ -722,8 +782,12 @@ def import_command(
|
|
|
722
782
|
graphs = read_rdf_graph_files(input_path)
|
|
723
783
|
else:
|
|
724
784
|
# in case a directory is the source AND IRI is given
|
|
725
|
-
graphs = [
|
|
726
|
-
|
|
785
|
+
graphs = []
|
|
786
|
+
for _ in _get_graph_supported_formats():
|
|
787
|
+
extension = mimetypes.guess_extension(_)
|
|
788
|
+
graphs += [(file, iri) for file in Path(input_path).glob(f"*{extension}")]
|
|
789
|
+
graphs += [(file, iri) for file in Path(input_path).glob(f"*{extension}.gz")]
|
|
790
|
+
|
|
727
791
|
elif Path(input_path).is_file():
|
|
728
792
|
if iri is None:
|
|
729
793
|
raise ValueError(
|
|
@@ -748,17 +812,10 @@ def import_command(
|
|
|
748
812
|
continue
|
|
749
813
|
# prevents re-replacing of graphs in a single run
|
|
750
814
|
_replace = False if graph_iri in processed_graphs else replace
|
|
751
|
-
_buffer =
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
"Accept": "text/turtle; q=1.0, application/x-turtle; q=0.9, text/n3;"
|
|
756
|
-
" q=0.8, application/rdf+xml; q=0.5, text/plain; q=0.1"
|
|
757
|
-
}
|
|
758
|
-
with ClickSmartPath.open(triple_file, transport_params=transport_prams) as _:
|
|
759
|
-
_buffer.write(_.read())
|
|
760
|
-
_buffer.seek(0)
|
|
761
|
-
response = graph_api.post_streamed(graph_iri, _buffer, replace=_replace)
|
|
815
|
+
_buffer, content_type = _parse_triple_file(triple_file)
|
|
816
|
+
response = graph_api.post_streamed(
|
|
817
|
+
graph_iri, _buffer, replace=_replace, content_type=content_type
|
|
818
|
+
)
|
|
762
819
|
request_headers = response.request.headers
|
|
763
820
|
request_headers.pop("Authorization")
|
|
764
821
|
app.echo_debug(f"cmemc request headers: {request_headers}")
|
|
@@ -18,6 +18,7 @@ from cmem_cmemc.migrations.bootstrap_data import MigrateBootstrapData
|
|
|
18
18
|
from cmem_cmemc.migrations.shapes_widget_integrations_243 import (
|
|
19
19
|
ChartsOnNodeShapesToToWidgetIntegrations,
|
|
20
20
|
ChartsOnPropertyShapesToWidgetIntegrations,
|
|
21
|
+
TableReportPropertyShapesToWidgetIntegrations,
|
|
21
22
|
WorkflowTriggerPropertyShapesToWidgetIntegrations,
|
|
22
23
|
)
|
|
23
24
|
from cmem_cmemc.migrations.workspace_configurations import MigrateWorkspaceConfiguration
|
|
@@ -54,6 +55,7 @@ def get_migrations(ctx: click.Context) -> list[dict]: # noqa: ARG001
|
|
|
54
55
|
ChartsOnNodeShapesToToWidgetIntegrations(),
|
|
55
56
|
ChartsOnPropertyShapesToWidgetIntegrations(),
|
|
56
57
|
WorkflowTriggerPropertyShapesToWidgetIntegrations(),
|
|
58
|
+
TableReportPropertyShapesToWidgetIntegrations(),
|
|
57
59
|
]
|
|
58
60
|
]
|
|
59
61
|
data.sort(key=lambda x: x["first_version"])
|
|
@@ -181,11 +181,11 @@ def list_command(app: ApplicationContext, raw: bool, id_only: bool, available: b
|
|
|
181
181
|
return
|
|
182
182
|
|
|
183
183
|
table_published = [
|
|
184
|
-
(_.name, str(_.published)[:10], _.description) for _ in published_packages
|
|
184
|
+
(_.name, _.version, str(_.published)[:10], _.description) for _ in published_packages
|
|
185
185
|
]
|
|
186
186
|
app.echo_info_table(
|
|
187
187
|
table_published,
|
|
188
|
-
headers=["Name", "Published", "Description"],
|
|
188
|
+
headers=["Name", "Version", "Published", "Description"],
|
|
189
189
|
sort_column=0,
|
|
190
190
|
empty_table_message="No available python packages found.",
|
|
191
191
|
)
|
|
@@ -460,7 +460,7 @@ def installed_package_names(ctx: Context, param: Argument, incomplete: str) -> l
|
|
|
460
460
|
|
|
461
461
|
def published_package_names(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
|
|
462
462
|
"""List of plugin packages scraped from pypi.org."""
|
|
463
|
-
options = [(_.name, f"{_.description}") for _ in get_published_packages()]
|
|
463
|
+
options = [(_.name, f"{_.version}: {_.description}") for _ in get_published_packages()]
|
|
464
464
|
return finalize_completion(candidates=options, incomplete=incomplete, sort_by=SORT_BY_KEY)
|
|
465
465
|
|
|
466
466
|
|
|
@@ -600,13 +600,19 @@ def sparql_files(ctx: Context, param: Argument, incomplete: str) -> list[Complet
|
|
|
600
600
|
def triple_files(ctx: Context, param: Argument, incomplete: str) -> list[CompletionItem]:
|
|
601
601
|
"""Prepare a list of triple files."""
|
|
602
602
|
return (
|
|
603
|
-
file_list(incomplete=incomplete, suffix=".ttl", description="
|
|
604
|
-
+ file_list(incomplete=incomplete, suffix=".nt", description="
|
|
603
|
+
file_list(incomplete=incomplete, suffix=".ttl", description="Turtle file")
|
|
604
|
+
+ file_list(incomplete=incomplete, suffix=".nt", description="NTriples file")
|
|
605
|
+
+ file_list(incomplete=incomplete, suffix=".rdf", description="RDF/XML file")
|
|
606
|
+
+ file_list(incomplete=incomplete, suffix=".jsonld", description="JSON-LD file")
|
|
607
|
+
+ file_list(incomplete=incomplete, suffix=".ttl.gz", description="Turtle file (compressed)")
|
|
605
608
|
+ file_list(
|
|
606
|
-
incomplete=incomplete, suffix=".
|
|
609
|
+
incomplete=incomplete, suffix=".nt.gz", description="NTriples file (compressed)"
|
|
607
610
|
)
|
|
608
611
|
+ file_list(
|
|
609
|
-
incomplete=incomplete, suffix=".
|
|
612
|
+
incomplete=incomplete, suffix=".rdf.gz", description="RDF/XML file (compressed)"
|
|
613
|
+
)
|
|
614
|
+
+ file_list(
|
|
615
|
+
incomplete=incomplete, suffix=".jsonld.gz", description="JSON-LD file (compressed)"
|
|
610
616
|
)
|
|
611
617
|
)
|
|
612
618
|
|
{cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/migrations/access_conditions_243.py
RENAMED
|
@@ -20,6 +20,7 @@ SELECT ?subject
|
|
|
20
20
|
FROM <urn:elds-backend-access-conditions-graph>
|
|
21
21
|
WHERE {
|
|
22
22
|
?subject a ?class .
|
|
23
|
+
FILTER NOT EXISTS { ?subject shui:isSystemResource true }
|
|
23
24
|
FILTER (?class IN (auth:AccessCondition, shui:SparqlQuery) ) .
|
|
24
25
|
}
|
|
25
26
|
"""
|
|
@@ -31,6 +32,7 @@ WHERE {
|
|
|
31
32
|
?s ?p ?o .
|
|
32
33
|
?s a ?class .
|
|
33
34
|
FILTER (?class IN (auth:AccessCondition, shui:SparqlQuery) ) .
|
|
35
|
+
FILTER NOT EXISTS { ?s shui:isSystemResource true }
|
|
34
36
|
}
|
|
35
37
|
}
|
|
36
38
|
"""
|
|
@@ -59,6 +61,7 @@ SELECT DISTINCT ?acl_id
|
|
|
59
61
|
WHERE {
|
|
60
62
|
GRAPH ?acl_graph {
|
|
61
63
|
?acl_id a auth:AccessCondition .
|
|
64
|
+
FILTER NOT EXISTS { ?acl_id shui:isSystemResource true }
|
|
62
65
|
?acl_id ?property ?old_term .
|
|
63
66
|
FILTER (?old_term in (
|
|
64
67
|
<urn:elds-backend-all-actions>,
|
|
@@ -85,6 +88,7 @@ INSERT { GRAPH ?acl_graph { ?s ?p <{{NEW_IRI}}> . } }
|
|
|
85
88
|
WHERE {
|
|
86
89
|
GRAPH ?acl_graph {
|
|
87
90
|
?s ?p ?o .
|
|
91
|
+
FILTER NOT EXISTS { ?s shui:isSystemResource true }
|
|
88
92
|
FILTER (?o = <{{OLD_IRI}}> )
|
|
89
93
|
}
|
|
90
94
|
FILTER (?acl_graph IN (<urn:elds-backend-access-conditions-graph>, <https://ns.eccenca.com/data/ac/>))
|
|
@@ -20,10 +20,8 @@ class MigrateBootstrapData(MigrationRecipe):
|
|
|
20
20
|
def is_applicable(self) -> bool:
|
|
21
21
|
"""Test if the recipe can be applied."""
|
|
22
22
|
status_info = get_complete_status_info()
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"UNKNOWN",
|
|
26
|
-
)
|
|
23
|
+
shapes_status = status_info["shapes"]["version"]
|
|
24
|
+
return bool(shapes_status != status_info["explore"]["version"])
|
|
27
25
|
|
|
28
26
|
def apply(self) -> None:
|
|
29
27
|
"""Apply the recipe to the current version."""
|
|
@@ -192,3 +192,83 @@ WHERE {
|
|
|
192
192
|
def apply(self) -> None:
|
|
193
193
|
"""Apply the recipe to the current version."""
|
|
194
194
|
self._update(self.move_query)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
class TableReportPropertyShapesToWidgetIntegrations(MigrationRecipe):
|
|
198
|
+
"""24.3 Migrate Table Report Property Shapes to Widget Integrations"""
|
|
199
|
+
|
|
200
|
+
id = "table-reports-on-pshapes-24.3"
|
|
201
|
+
description = (
|
|
202
|
+
"Migrate Table Reports (which use shui:null) on Property Shapes to Widget Integrations"
|
|
203
|
+
)
|
|
204
|
+
component: components = "explore"
|
|
205
|
+
first_version = "24.3"
|
|
206
|
+
tags: ClassVar[list[str]] = ["shapes", "user"]
|
|
207
|
+
check_query = """{{DEFAULT_PREFIXES}}
|
|
208
|
+
SELECT ?propertyShape
|
|
209
|
+
WHERE {
|
|
210
|
+
GRAPH ?shapeCatalog {
|
|
211
|
+
?shapeCatalog a shui:ShapeCatalog .
|
|
212
|
+
?propertyShape a sh:PropertyShape ;
|
|
213
|
+
shui:valueQuery ?valueQuery ;
|
|
214
|
+
sh:path shui:null .
|
|
215
|
+
FILTER NOT EXISTS { ?propertyShape shui:isSystemResource true }
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
"""
|
|
219
|
+
move_query = """{{DEFAULT_PREFIXES}}
|
|
220
|
+
DELETE {
|
|
221
|
+
GRAPH ?shapeCatalog {
|
|
222
|
+
?propertyShape ?p ?o .
|
|
223
|
+
?nodeShape sh:property ?propertyShape .
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
INSERT {
|
|
227
|
+
GRAPH ?shapeCatalog {
|
|
228
|
+
?propertyShape a shui:WidgetIntegration ;
|
|
229
|
+
shui:WidgetIntegration_widget ?newTableReport ;
|
|
230
|
+
rdfs:label ?name ;
|
|
231
|
+
rdfs:comment ?description ;
|
|
232
|
+
sh:order ?order ;
|
|
233
|
+
shui:WidgetIntegration_group ?group .
|
|
234
|
+
?nodeShape shui:WidgetIntegration_integrate ?propertyShape .
|
|
235
|
+
|
|
236
|
+
?newTableReport a shui:TableReport ;
|
|
237
|
+
rdfs:label ?newTableReportLabel ;
|
|
238
|
+
shui:TableReport_hideFooter ?hideFooter ;
|
|
239
|
+
shui:TableReport_hideHeader ?hideHeader ;
|
|
240
|
+
shui:TableReport_query ?valueQuery .
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
WHERE {
|
|
244
|
+
GRAPH ?shapeCatalog {
|
|
245
|
+
?shapeCatalog a shui:ShapeCatalog .
|
|
246
|
+
?propertyShape a sh:PropertyShape ;
|
|
247
|
+
sh:path shui:null ;
|
|
248
|
+
shui:valueQuery ?valueQuery .
|
|
249
|
+
FILTER NOT EXISTS { ?propertyShape shui:isSystemResource true }
|
|
250
|
+
?propertyShape ?p ?o .
|
|
251
|
+
OPTIONAL {?propertyShape sh:name ?name }
|
|
252
|
+
OPTIONAL {?propertyShape sh:description ?description }
|
|
253
|
+
OPTIONAL {?propertyShape sh:order ?order }
|
|
254
|
+
OPTIONAL {?propertyShape sh:group ?group }
|
|
255
|
+
OPTIONAL {?propertyShape sh:name ?name }
|
|
256
|
+
OPTIONAL {?propertyShape shui:valueQueryHideHeader ?hideHeaderValue }
|
|
257
|
+
OPTIONAL {?propertyShape shui:valueQueryHideFooter ?hideFooterValue }
|
|
258
|
+
OPTIONAL {?nodeShape sh:property ?propertyShape }
|
|
259
|
+
BIND ( IRI(CONCAT(STR(?propertyShape), "-TableReport")) AS ?newTableReport )
|
|
260
|
+
BIND ( STRLANG(CONCAT("Table Report: ", ?name), lang(?name)) AS ?newTableReportLabel )
|
|
261
|
+
BIND ( COALESCE(?hideHeaderValue, false) as ?hideHeader)
|
|
262
|
+
BIND ( COALESCE(?hideFooterValue, false) as ?hideFooter)
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
"""
|
|
266
|
+
|
|
267
|
+
def is_applicable(self) -> bool:
|
|
268
|
+
"""Test if the recipe can be applied."""
|
|
269
|
+
table_report_property_shapes = self._select(self.check_query)
|
|
270
|
+
return len(table_report_property_shapes) > 0
|
|
271
|
+
|
|
272
|
+
def apply(self) -> None:
|
|
273
|
+
"""Apply the recipe to the current version."""
|
|
274
|
+
self._update(self.move_query)
|
|
@@ -24,7 +24,13 @@ class TimeAgo(StringProcessor):
|
|
|
24
24
|
|
|
25
25
|
def process(self, text: str) -> str:
|
|
26
26
|
"""Process a single string content and output the processed string."""
|
|
27
|
-
|
|
27
|
+
if text is None:
|
|
28
|
+
return ""
|
|
29
|
+
try:
|
|
30
|
+
text_as_int = int(text)
|
|
31
|
+
except ValueError:
|
|
32
|
+
return text
|
|
33
|
+
stamp = datetime.fromtimestamp(text_as_int / 1000, tz=timezone.utc)
|
|
28
34
|
return str(timeago.format(stamp, datetime.now(tz=timezone.utc)))
|
|
29
35
|
|
|
30
36
|
|
|
@@ -12,7 +12,6 @@ from typing import TYPE_CHECKING
|
|
|
12
12
|
from zipfile import BadZipFile, ZipFile
|
|
13
13
|
|
|
14
14
|
import requests
|
|
15
|
-
from bs4 import BeautifulSoup
|
|
16
15
|
from cmem.cmempy.dp.proxy.graph import get_graphs_list
|
|
17
16
|
from cmem.cmempy.queries import QueryCatalog
|
|
18
17
|
from cmem.cmempy.workspace.projects.project import get_projects
|
|
@@ -288,41 +287,30 @@ class PublishedPackage:
|
|
|
288
287
|
name: str
|
|
289
288
|
description: str
|
|
290
289
|
published: str
|
|
290
|
+
version: str
|
|
291
291
|
|
|
292
292
|
|
|
293
293
|
def get_published_packages() -> list[PublishedPackage]:
|
|
294
294
|
"""Get a scraped list of plugin packages scraped from pypi.org."""
|
|
295
|
-
|
|
296
|
-
packages = []
|
|
295
|
+
url = "https://download.eccenca.com/cmem-plugin-index/cmem-plugin-index.json"
|
|
297
296
|
package_names = []
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
description = _.findChildren(class_="package-snippet__description")[0].getText()
|
|
314
|
-
except IndexError:
|
|
315
|
-
description = "no description"
|
|
316
|
-
published = _.findChildren(name="time")[0].attrs["datetime"]
|
|
317
|
-
if name not in package_names:
|
|
318
|
-
package_names.append(name)
|
|
319
|
-
packages.append(
|
|
320
|
-
PublishedPackage(
|
|
321
|
-
name=name,
|
|
322
|
-
description=description,
|
|
323
|
-
published=published,
|
|
324
|
-
)
|
|
297
|
+
packages = []
|
|
298
|
+
for _ in requests.get(url, timeout=5).json():
|
|
299
|
+
name = _["name"]
|
|
300
|
+
if name == "cmem-plugin-base":
|
|
301
|
+
continue
|
|
302
|
+
if not name.startswith("cmem-plugin-"):
|
|
303
|
+
continue
|
|
304
|
+
if name not in package_names:
|
|
305
|
+
package_names.append(name)
|
|
306
|
+
packages.append(
|
|
307
|
+
PublishedPackage(
|
|
308
|
+
name=name,
|
|
309
|
+
description=_["summary"],
|
|
310
|
+
published=_["latest_version_time"],
|
|
311
|
+
version=_["latest_version"],
|
|
325
312
|
)
|
|
313
|
+
)
|
|
326
314
|
return packages
|
|
327
315
|
|
|
328
316
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cmem_cmemc-24.3.0rc1 → cmem_cmemc-24.3.0rc2}/cmem_cmemc/migrations/workspace_configurations.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|