1818 get_databus_id_parts_from_file_url ,
1919 compute_sha256_and_length ,
2020)
21- from databusclient .filehandling .format import convert_file , get_converted_filename
21+ from databusclient .filehandling .format import (
22+ convert_file ,
23+ get_converted_filename ,
24+ normalize_format ,
25+ get_format_class ,
26+ detect_format_from_filename ,
27+ FORMAT_TO_EXTENSION ,
28+ )
2229
2330# Compression format mappings
2431COMPRESSION_EXTENSIONS = {
@@ -316,6 +323,8 @@ def _download_file(
316323 client_id = None ,
317324 compression = None ,
318325 convert_format = None ,
326+ graph_name = None ,
327+ base_uri = None ,
319328 validate_checksum : bool = False ,
320329 expected_checksum : str | None = None ,
321330) -> None :
@@ -331,6 +340,8 @@ def _download_file(
331340 compression: Target compression format for on-the-fly conversion.
332341 Source compression is auto-detected from the file extension.
333342 convert_format: Target RDF/tabular format for on-the-fly conversion.
343+ graph_name: Named graph URI for Triple -> Quad conversion (Layer 3).
344+ base_uri: Base URI for CSV -> Triple conversion (Layer 3).
334345 validate_checksum: Whether to validate checksums after downloading.
335346 expected_checksum: The expected checksum of the file.
336347 """
@@ -555,10 +566,6 @@ def _download_file(
555566 # already matches target format, skip decompression and conversion
556567 # entirely — no work needed for the format part.
557568 if needs_format_conversion and source_compression is not None :
558- from databusclient .filehandling .format import (
559- detect_format_from_filename ,
560- normalize_format ,
561- )
562569 detected_input_format = detect_format_from_filename (file )
563570 normalized_target = normalize_format (convert_format )
564571 if detected_input_format == normalized_target :
@@ -599,10 +606,57 @@ def _download_file(
599606
600607 conversion_input_path = temp_decompressed_path
601608
602- # Convert format on uncompressed input.
609+ # Determine whether this is a Quad -> Triple (Layer 3) conversion.
610+ # This direction produces multiple output files (one per named
611+ # graph) written into a subdirectory, rather than a single file —
612+ # so it is handled separately from the standard single-file path
613+ # below (no recompression, no single-file delete-and-replace).
614+ normalized_convert_format = normalize_format (convert_format )
615+ target_class = get_format_class (normalized_convert_format )
616+ source_format_for_mapping = detect_format_from_filename (conversion_input_path )
617+ source_class_for_mapping = (
618+ get_format_class (source_format_for_mapping )
619+ if source_format_for_mapping else None
620+ )
621+ is_quad_to_triple = (
622+ source_class_for_mapping == "quads" and target_class == "triples"
623+ )
624+
625+ if is_quad_to_triple :
626+ # Output directory name = original filename with compression and
627+ # format extensions stripped (e.g. "data.nq.gz" -> "data").
628+ output_stem = get_converted_filename (file , convert_format )
629+ target_ext = FORMAT_TO_EXTENSION .get (normalized_convert_format , "" )
630+ if target_ext and output_stem .lower ().endswith (target_ext ):
631+ output_stem = output_stem [: - len (target_ext )]
632+ output_dir = os .path .join (localDir , output_stem )
633+
634+ convert_file (
635+ conversion_input_path ,
636+ output_dir ,
637+ convert_format ,
638+ graph_name = graph_name ,
639+ base_uri = base_uri ,
640+ )
641+
642+ # Delete the original downloaded (possibly compressed) file —
643+ # the split output directory replaces it.
644+ if os .path .exists (filename ):
645+ os .remove (filename )
646+ print (f"Removed original file: { os .path .basename (filename )} " )
647+ return
648+
649+ # Standard single-output-file path (Layer 2, and the remaining
650+ # Layer 3 directions: Triple<->Quad, Triple<->TSD, Quad->TSD).
603651 converted_basename = get_converted_filename (file , convert_format )
604652 converted_uncompressed_path = os .path .join (localDir , converted_basename )
605- convert_file (conversion_input_path , converted_uncompressed_path , convert_format )
653+ convert_file (
654+ conversion_input_path ,
655+ converted_uncompressed_path ,
656+ convert_format ,
657+ graph_name = graph_name ,
658+ base_uri = base_uri ,
659+ )
606660
607661 # Delete the original downloaded file after successful format conversion,
608662 # unless the converted output is the same file (same format, same path).
@@ -612,12 +666,18 @@ def _download_file(
612666 print (f"Removed original file: { os .path .basename (filename )} " )
613667
614668 # Recompress converted output when needed.
669+ # Three cases:
670+ # 1. Source was compressed + --compression given -> use target compression
671+ # 2. Source was compressed, no --compression given -> recompress with original
672+ # 3. Source was NOT compressed + --compression given -> compress the output
673+ # 4. Source was NOT compressed, no --compression given -> no compression
615674 if source_compression is not None :
616675 if should_convert_compression and compression :
617676 final_compression = compression
618677 else :
619678 final_compression = source_compression
620- elif should_convert_compression and compression :
679+ elif compression :
680+ # Source was uncompressed but user explicitly requested --compression
621681 final_compression = compression
622682 else :
623683 final_compression = None
@@ -651,6 +711,8 @@ def _download_files(
651711 client_id : str = None ,
652712 compression : str = None ,
653713 convert_format : str = None ,
714+ graph_name : str = None ,
715+ base_uri : str = None ,
654716 validate_checksum : bool = False ,
655717 checksums : dict | None = None ,
656718) -> None :
@@ -665,6 +727,8 @@ def _download_files(
665727 client_id: Client ID for token exchange.
666728 compression: Target compression format for on-the-fly conversion.
667729 convert_format: Target RDF/tabular format for on-the-fly conversion.
730+ graph_name: Named graph URI for Triple -> Quad conversion (Layer 3).
731+ base_uri: Base URI for CSV -> Triple conversion (Layer 3).
668732 validate_checksum: Whether to validate checksums after downloading.
669733 checksums: Dictionary mapping URLs to their expected checksums.
670734 """
@@ -681,11 +745,12 @@ def _download_files(
681745 client_id = client_id ,
682746 compression = compression ,
683747 convert_format = convert_format ,
748+ graph_name = graph_name ,
749+ base_uri = base_uri ,
684750 validate_checksum = validate_checksum ,
685751 expected_checksum = expected ,
686752 )
687753
688-
689754def _get_sparql_query_of_collection (uri : str , databus_key : str | None = None ) -> str :
690755 """Get SPARQL query of collection members from databus collection URI.
691756
@@ -829,6 +894,8 @@ def _download_collection(
829894 client_id : str = None ,
830895 compression : str = None ,
831896 convert_format : str = None ,
897+ graph_name : str = None ,
898+ base_uri : str = None ,
832899 validate_checksum : bool = False ,
833900) -> None :
834901 """Download all files in a databus collection.
@@ -843,6 +910,8 @@ def _download_collection(
843910 client_id: Client ID for token exchange.
844911 compression: Target compression format for on-the-fly conversion.
845912 convert_format: Target RDF/tabular format for on-the-fly conversion.
913+ graph_name: Named graph URI for Triple -> Quad conversion (Layer 3).
914+ base_uri: Base URI for CSV -> Triple conversion (Layer 3).
846915 validate_checksum: Whether to validate checksums after downloading.
847916 """
848917 query = _get_sparql_query_of_collection (uri , databus_key = databus_key )
@@ -864,6 +933,8 @@ def _download_collection(
864933 client_id = client_id ,
865934 compression = compression ,
866935 convert_format = convert_format ,
936+ graph_name = graph_name ,
937+ base_uri = base_uri ,
867938 validate_checksum = validate_checksum ,
868939 checksums = checksums if checksums else None ,
869940 )
@@ -878,6 +949,8 @@ def _download_version(
878949 client_id : str = None ,
879950 compression : str = None ,
880951 convert_format : str = None ,
952+ graph_name : str = None ,
953+ base_uri : str = None ,
881954 validate_checksum : bool = False ,
882955) -> None :
883956 """Download all files in a databus artifact version.
@@ -891,6 +964,8 @@ def _download_version(
891964 client_id: Client ID for token exchange.
892965 compression: Target compression format for on-the-fly conversion.
893966 convert_format: Target RDF/tabular format for on-the-fly conversion.
967+ graph_name: Named graph URI for Triple -> Quad conversion (Layer 3).
968+ base_uri: Base URI for CSV -> Triple conversion (Layer 3).
894969 validate_checksum: Whether to validate checksums after downloading.
895970 """
896971 json_str = fetch_databus_jsonld (uri , databus_key = databus_key )
@@ -911,6 +986,8 @@ def _download_version(
911986 client_id = client_id ,
912987 compression = compression ,
913988 convert_format = convert_format ,
989+ graph_name = graph_name ,
990+ base_uri = base_uri ,
914991 validate_checksum = validate_checksum ,
915992 checksums = checksums ,
916993 )
@@ -926,6 +1003,8 @@ def _download_artifact(
9261003 client_id : str = None ,
9271004 compression : str = None ,
9281005 convert_format : str = None ,
1006+ graph_name : str = None ,
1007+ base_uri : str = None ,
9291008 validate_checksum : bool = False ,
9301009) -> None :
9311010 """Download files in a databus artifact.
@@ -940,6 +1019,8 @@ def _download_artifact(
9401019 client_id: Client ID for token exchange.
9411020 compression: Target compression format for on-the-fly conversion.
9421021 convert_format: Target RDF/tabular format for on-the-fly conversion.
1022+ graph_name: Named graph URI for Triple -> Quad conversion (Layer 3).
1023+ base_uri: Base URI for CSV -> Triple conversion (Layer 3).
9431024 validate_checksum: Whether to validate checksums after downloading.
9441025 """
9451026 json_str = fetch_databus_jsonld (uri , databus_key = databus_key )
@@ -966,6 +1047,8 @@ def _download_artifact(
9661047 client_id = client_id ,
9671048 compression = compression ,
9681049 convert_format = convert_format ,
1050+ graph_name = graph_name ,
1051+ base_uri = base_uri ,
9691052 validate_checksum = validate_checksum ,
9701053 checksums = checksums ,
9711054 )
@@ -1042,6 +1125,8 @@ def _download_group(
10421125 client_id : str = None ,
10431126 compression : str = None ,
10441127 convert_format : str = None ,
1128+ graph_name : str = None ,
1129+ base_uri : str = None ,
10451130 validate_checksum : bool = False ,
10461131) -> None :
10471132 """Download files in a databus group.
@@ -1056,6 +1141,8 @@ def _download_group(
10561141 client_id: Client ID for token exchange.
10571142 compression: Target compression format for on-the-fly conversion.
10581143 convert_format: Target RDF/tabular format for on-the-fly conversion.
1144+ graph_name: Named graph URI for Triple -> Quad conversion (Layer 3).
1145+ base_uri: Base URI for CSV -> Triple conversion (Layer 3).
10591146 validate_checksum: Whether to validate checksums after downloading.
10601147 """
10611148 json_str = fetch_databus_jsonld (uri , databus_key = databus_key )
@@ -1072,6 +1159,8 @@ def _download_group(
10721159 client_id = client_id ,
10731160 compression = compression ,
10741161 convert_format = convert_format ,
1162+ graph_name = graph_name ,
1163+ base_uri = base_uri ,
10751164 validate_checksum = validate_checksum ,
10761165 )
10771166
@@ -1121,6 +1210,8 @@ def download(
11211210 client_id = "vault-token-exchange" ,
11221211 compression = None ,
11231212 convert_format = None ,
1213+ graph_name = None ,
1214+ base_uri = None ,
11241215 validate_checksum : bool = False ,
11251216) -> None :
11261217 """Download datasets from databus.
@@ -1136,8 +1227,10 @@ def download(
11361227 auth_url: Keycloak token endpoint URL. Default is "https://auth.dbpedia.org/realms/dbpedia/protocol/openid-connect/token".
11371228 client_id: Client ID for token exchange. Default is "vault-token-exchange".
11381229 compression: Target compression format for on-the-fly conversion (supported: bz2, gz, xz).
1139- Source compression is auto-detected from the file extension.
1230+ Source compression is auto-detected from the file extension.
11401231 convert_format: Target RDF/tabular format for on-the-fly conversion.
1232+ graph_name: Named graph URI for Triple -> Quad conversion (Layer 3).
1233+ base_uri: Base URI for CSV -> Triple conversion (Layer 3).
11411234 validate_checksum: Whether to validate checksums after downloading.
11421235 """
11431236 for databusURI in databusURIs :
@@ -1167,6 +1260,8 @@ def download(
11671260 client_id ,
11681261 compression ,
11691262 convert_format ,
1263+ graph_name = graph_name ,
1264+ base_uri = base_uri ,
11701265 validate_checksum = validate_checksum ,
11711266 )
11721267 elif file is not None :
@@ -1188,6 +1283,8 @@ def download(
11881283 client_id = client_id ,
11891284 compression = compression ,
11901285 convert_format = convert_format ,
1286+ graph_name = graph_name ,
1287+ base_uri = base_uri ,
11911288 validate_checksum = validate_checksum ,
11921289 expected_checksum = expected ,
11931290 )
@@ -1202,6 +1299,8 @@ def download(
12021299 client_id = client_id ,
12031300 compression = compression ,
12041301 convert_format = convert_format ,
1302+ graph_name = graph_name ,
1303+ base_uri = base_uri ,
12051304 validate_checksum = validate_checksum ,
12061305 )
12071306 elif artifact is not None :
@@ -1218,6 +1317,8 @@ def download(
12181317 client_id = client_id ,
12191318 compression = compression ,
12201319 convert_format = convert_format ,
1320+ graph_name = graph_name ,
1321+ base_uri = base_uri ,
12211322 validate_checksum = validate_checksum ,
12221323 )
12231324 elif group is not None and group != "collections" :
@@ -1234,6 +1335,8 @@ def download(
12341335 client_id = client_id ,
12351336 compression = compression ,
12361337 convert_format = convert_format ,
1338+ graph_name = graph_name ,
1339+ base_uri = base_uri ,
12371340 validate_checksum = validate_checksum ,
12381341 )
12391342 elif account is not None :
@@ -1272,6 +1375,8 @@ def download(
12721375 client_id = client_id ,
12731376 compression = compression ,
12741377 convert_format = convert_format ,
1378+ graph_name = graph_name ,
1379+ base_uri = base_uri ,
12751380 validate_checksum = validate_checksum ,
12761381 checksums = checksums if checksums else None ,
12771382 )
0 commit comments