From f600c4e080c848cff5b8b3644e7326d276a67dfb Mon Sep 17 00:00:00 2001 From: tmathern <60901087+tmathern@users.noreply.github.com> Date: Thu, 25 Jun 2026 19:36:05 -0700 Subject: [PATCH 1/5] fix: Initial commit --- src/c2pa/c2pa.py | 61 ++++++++++++-------- tests/test_unit_tests.py | 119 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 149 insertions(+), 31 deletions(-) diff --git a/src/c2pa/c2pa.py b/src/c2pa/c2pa.py index 07f12ed4..e3387d4e 100644 --- a/src/c2pa/c2pa.py +++ b/src/c2pa/c2pa.py @@ -1194,16 +1194,20 @@ def load_settings(settings: Union[str, dict], format: str = "json") -> None: def _get_mime_type_from_path(path: Union[str, Path]) -> str: - """Attempt to guess the MIME type from a file path (with extension). + """Attempt to guess the MIME type from a file path's extension. + + When the extension is missing or unrecognized, this returns an empty + string so the caller can hand it to the native layer for auto-detection + from the asset's magic bytes (see Reader). A recognized-but-wrong + extension still returns its MIME type; the native layer corrects it from + the bytes when reading. Args: path: File path as string or Path object Returns: - MIME type string - - Raises: - C2paError.NotSupported: If MIME type cannot be determined + MIME type string, or an empty string when it cannot be determined + from the extension (signals native auto-detection). """ path_obj = Path(path) file_extension = path_obj.suffix.lower() if path_obj.suffix else "" @@ -1213,11 +1217,9 @@ def _get_mime_type_from_path(path: Union[str, Path]) -> str: # so we bypass it and set the correct type return "image/dng" else: - mime_type = mimetypes.guess_type(str(path))[0] - if not mime_type: - raise C2paError.NotSupported( - f"Could not determine MIME type for file: {path}") - return mime_type + # Fall back to an empty string for extensionless or unknown files so + # the native layer can detect the format from the asset's bytes. + return mimetypes.guess_type(str(path))[0] or "" class ContextProvider(ABC): @@ -1971,19 +1973,25 @@ def _validate_and_encode_format( ) -> bytes: """Validate a MIME type / format string and encode it to UTF-8 bytes. + An empty string is treated as a request for native format auto-detection: + it skips the supported-types check and encodes to empty bytes, letting the + native library infer the format from the asset's magic bytes. A non-empty + format is still validated against the supported list. + Args: - format_str: The MIME type or format string to validate + format_str: The MIME type or format string to validate. Pass an empty + string to request auto-detection from the asset's bytes. supported_types: List of supported MIME types class_name: Name of the calling class (for error messages) Returns: - UTF-8 encoded format bytes + UTF-8 encoded format bytes (empty bytes for auto-detection) Raises: - C2paError.NotSupported: If the format is not supported + C2paError.NotSupported: If a non-empty format is not supported C2paError.Encoding: If the string contains invalid UTF-8 characters """ - if format_str.lower() not in supported_types: + if format_str and format_str.lower() not in supported_types: raise C2paError.NotSupported( f"{class_name} does not support {format_str}") try: @@ -2134,14 +2142,22 @@ def __init__( ): """Create a new Reader. + The format is optional: pass an empty string (or read an extensionless + file by path) to let the native library detect the format from the + asset's magic bytes. A recognized but wrong format/extension is also + corrected from the bytes when reading. If the bytes are not a + recognized asset, a C2paError is raised. + Args: - format_or_path: The format or path to read from + format_or_path: The format (MIME type) or path to read from. An + empty string requests auto-detection from the asset's bytes. stream: Optional stream to read from (Python stream-like object) manifest_data: Optional manifest data in bytes context: Optional context implementing ContextProvider with settings Raises: - C2paError: If there was an error creating the reader + C2paError: If there was an error creating the reader, including + when the format cannot be detected from an unrecognized asset C2paError.Encoding: If any of the string inputs contain invalid UTF-8 characters """ @@ -2173,14 +2189,12 @@ def __init__( supported = Reader.get_supported_mime_types() if stream is None: - # Create a stream from the file path in format_or_path + # Create a stream from the file path in format_or_path. + # An empty MIME type (extensionless/unknown file) is passed + # through so the native layer attempts auto-detect from the bytes. path = str(format_or_path) mime_type = _get_mime_type_from_path(path) - if not mime_type: - raise C2paError.NotSupported( - f"Could not determine MIME type for file: {path}") - format_bytes = _validate_and_encode_format( mime_type, supported, "Reader") self._init_from_file(path, format_bytes) @@ -2270,11 +2284,10 @@ def _init_from_context(self, context, format_or_path, supported = Reader.get_supported_mime_types() if stream is None: + # An empty MIME type (extensionless / unknown file) is passed + # through so the native layer auto-detects from the bytes. path = str(format_or_path) mime_type = _get_mime_type_from_path(path) - if not mime_type: - raise C2paError.NotSupported( - f"Could not determine MIME type for file: {path}") format_bytes = _validate_and_encode_format( mime_type, supported, "Reader") self._backing_file = open(path, 'rb') diff --git a/tests/test_unit_tests.py b/tests/test_unit_tests.py index e0b3289c..ea9309f6 100644 --- a/tests/test_unit_tests.py +++ b/tests/test_unit_tests.py @@ -309,13 +309,22 @@ def test_try_create_raises_mimetype_not_supported(self): # as mimetype chemical/x-xyz, but we don't support it Reader.try_create(os.path.join(FIXTURES_DIR, "C.xyz")) - def test_stream_read_string_stream_mimetype_not_recognized(self): - with self.assertRaises(Error.NotSupported): - Reader(os.path.join(FIXTURES_DIR, "C.test")) - - def test_try_create_raises_mimetype_not_recognized(self): - with self.assertRaises(Error.NotSupported): - Reader.try_create(os.path.join(FIXTURES_DIR, "C.test")) + def test_unrecognized_extension_defers_to_detection(self): + with tempfile.TemporaryDirectory() as tmp: + asset = os.path.join(tmp, "C.test") + shutil.copyfile(self.testPath, asset) + with Reader(asset) as reader: + self.assertIn(DEFAULT_TEST_FILE_NAME, reader.json()) + + def test_try_create_unrecognized_extension_defers_to_detection(self): + with tempfile.TemporaryDirectory() as tmp: + asset = os.path.join(tmp, "C.test") + shutil.copyfile(self.testPath, asset) + reader = Reader.try_create(asset) + self.assertIsNotNone(reader) + if reader is not None: + with reader: + self.assertIn(DEFAULT_TEST_FILE_NAME, reader.json()) def test_stream_read_string_stream(self): with Reader("image/jpeg", self.testPath) as reader: @@ -326,6 +335,102 @@ def test_reader_detects_unsupported_mimetype_on_file(self): with self.assertRaises(Error.NotSupported): Reader("mimetype/does-not-exist", self.testPath) + def test_read_extensionless_file_path(self): + # A good file with no extension is read by detecting the format. + with tempfile.TemporaryDirectory() as tmp: + no_ext = os.path.join(tmp, "C") + shutil.copyfile(self.testPath, no_ext) + with Reader(no_ext) as reader: + self.assertIn(DEFAULT_TEST_FILE_NAME, reader.json()) + + def test_read_extensionless_stream_empty_format(self): + # An empty format string on a stream triggers auto-detection. + with open(self.testPath, "rb") as file: + with Reader("", file) as reader: + self.assertIn(DEFAULT_TEST_FILE_NAME, reader.json()) + + def test_read_wrong_extension_corrected(self): + # A JPEG saved with a .png extension is corrected from the bytes. + with tempfile.TemporaryDirectory() as tmp: + wrong = os.path.join(tmp, "C.png") + shutil.copyfile(self.testPath, wrong) + with Reader(wrong) as reader: + self.assertIn(DEFAULT_TEST_FILE_NAME, reader.json()) + + def test_read_wrong_mime_corrected_on_stream(self): + # A wrong MIME hint on a stream is corrected from the bytes. + with open(self.testPath, "rb") as file: + with Reader("image/png", file) as reader: + self.assertIn(DEFAULT_TEST_FILE_NAME, reader.json()) + + def test_explicit_empty_format_forces_detection(self): + # Passing "" works even when the correct format is known. + with open(self.testPath, "rb") as file: + with Reader("", file) as reader: + manifest_store = json.loads(reader.json()) + self.assertIn("active_manifest", manifest_store) + + def test_autodetect_multiformat(self): + # Detection works across container families, not just JPEG. + fixtures = [ + os.path.join(FIXTURES_DIR, "files-for-reading-tests", "CA.jpg"), + os.path.join(FIXTURES_DIR, "video1.mp4"), + os.path.join(FIXTURES_DIR, "files-for-reading-tests", "pdf-file.pdf"), + os.path.join(FIXTURES_DIR, "files-for-reading-tests", "sample1_signed.wav"), + ] + for path in fixtures: + with self.subTest(path=path): + with open(path, "rb") as file: + with Reader("", file) as reader: + self.assertIn("active_manifest", json.loads(reader.json())) + + def test_dng_extension_still_special_cased(self): + # The .dng path keeps its special-case MIME and still reads. + dng_path = os.path.join(FIXTURES_DIR, "C.dng") + with Reader(dng_path) as reader: + self.assertIn("active_manifest", json.loads(reader.json())) + + def test_garbage_stream_empty_format_raises(self): + # Unrecognized bytes with auto-detection raise rather than crash. + with self.assertRaises(Error): + Reader("", io.BytesIO(b"not an asset at all")) + + def test_empty_stream_raises(self): + # A zero-byte stream cannot be detected and raises cleanly. + with self.assertRaises(Error): + Reader("", io.BytesIO(b"")) + + def test_truncated_corrupt_jpeg_raises(self): + with open(self.testPath, "rb") as file: + data = bytearray(file.read()) + # Corrupt the body while keeping the leading JPEG magic intact. + for i in range(64, min(len(data), 4096)): + data[i] ^= 0xFF + with self.assertRaises(Error): + Reader("", io.BytesIO(bytes(data))) + + def test_garbage_extensionless_file_raises(self): + # Random bytes in an extensionless file raise cleanly. + with tempfile.TemporaryDirectory() as tmp: + garbage = os.path.join(tmp, "garbage") + with open(garbage, "wb") as f: + f.write(b"this is not a media asset") + with self.assertRaises(Error): + Reader(garbage) + + def test_try_create_garbage_stream_raises(self): + with self.assertRaises(Error) as context: + Reader.try_create("", io.BytesIO(b"not an asset at all")) + self.assertNotIn("ManifestNotFound", str(context.exception)) + + def test_try_create_extensionless_no_manifest_returns_none(self): + unsigned = os.path.join( + FIXTURES_DIR, "files-for-signing-tests", "earth_apollo17.jpg") + with tempfile.TemporaryDirectory() as tmp: + no_ext = os.path.join(tmp, "unsigned") + shutil.copyfile(unsigned, no_ext) + self.assertIsNone(Reader.try_create(no_ext)) + def test_stream_read_filepath_as_stream_and_parse(self): with Reader("image/jpeg", self.testPath) as reader: manifest_store = json.loads(reader.json()) From 00d2248e6fd649e0313bd7d219a0ee6513e74d27 Mon Sep 17 00:00:00 2001 From: tmathern <60901087+tmathern@users.noreply.github.com> Date: Thu, 25 Jun 2026 20:43:31 -0700 Subject: [PATCH 2/5] fix: Loosen check --- src/c2pa/c2pa.py | 16 ++++++++++------ tests/test_unit_tests.py | 21 +++++++++++++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/c2pa/c2pa.py b/src/c2pa/c2pa.py index e3387d4e..bc0998ff 100644 --- a/src/c2pa/c2pa.py +++ b/src/c2pa/c2pa.py @@ -1973,14 +1973,16 @@ def _validate_and_encode_format( ) -> bytes: """Validate a MIME type / format string and encode it to UTF-8 bytes. - An empty string is treated as a request for native format auto-detection: - it skips the supported-types check and encodes to empty bytes, letting the - native library infer the format from the asset's magic bytes. A non-empty - format is still validated against the supported list. + A blank format (empty or whitespace-only) is treated as a request for + native format auto-detection: it skips the supported-types check and + encodes to empty bytes, letting the native library infer the format from + the asset's magic bytes. A non-empty format is still validated against the + supported list. Args: format_str: The MIME type or format string to validate. Pass an empty - string to request auto-detection from the asset's bytes. + or whitespace-only string to request auto-detection from the + asset's bytes. supported_types: List of supported MIME types class_name: Name of the calling class (for error messages) @@ -1991,7 +1993,9 @@ def _validate_and_encode_format( C2paError.NotSupported: If a non-empty format is not supported C2paError.Encoding: If the string contains invalid UTF-8 characters """ - if format_str and format_str.lower() not in supported_types: + if not format_str.strip(): + return b"" + if format_str.lower() not in supported_types: raise C2paError.NotSupported( f"{class_name} does not support {format_str}") try: diff --git a/tests/test_unit_tests.py b/tests/test_unit_tests.py index ea9309f6..ddcf764d 100644 --- a/tests/test_unit_tests.py +++ b/tests/test_unit_tests.py @@ -431,6 +431,27 @@ def test_try_create_extensionless_no_manifest_returns_none(self): shutil.copyfile(unsigned, no_ext) self.assertIsNone(Reader.try_create(no_ext)) + def test_sub_magic_length_stream_raises(self): + # Fewer bytes than a full magic signature cannot be detected. + with self.assertRaises(Error): + Reader("", io.BytesIO(b"\xff\xd8\xff")) + + def test_preseeked_stream_is_rewound(self): + # Detection rewinds the stream + with open(self.testPath, "rb") as file: + data = file.read() + stream = io.BytesIO(data) + stream.seek(len(data) // 2) + with Reader("", stream) as reader: + self.assertIn(DEFAULT_TEST_FILE_NAME, reader.json()) + + def test_dng_extension_with_jpeg_bytes_corrected(self): + with tempfile.TemporaryDirectory() as tmp: + fake_dng = os.path.join(tmp, "fake.dng") + shutil.copyfile(self.testPath, fake_dng) + with Reader(fake_dng) as reader: + self.assertIn(DEFAULT_TEST_FILE_NAME, reader.json()) + def test_stream_read_filepath_as_stream_and_parse(self): with Reader("image/jpeg", self.testPath) as reader: manifest_store = json.loads(reader.json()) From 0ad83798b8779e6ed4b02d785bf4b38a13cdc789 Mon Sep 17 00:00:00 2001 From: Tania Mathern Date: Wed, 22 Jul 2026 10:29:34 -0700 Subject: [PATCH 3/5] fix: Fix test on Windows... hopefully --- tests/test_unit_tests.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/test_unit_tests.py b/tests/test_unit_tests.py index ddcf764d..dbc50d14 100644 --- a/tests/test_unit_tests.py +++ b/tests/test_unit_tests.py @@ -299,15 +299,15 @@ def test_try_create_from_path(self): def test_stream_read_string_stream_mimetype_not_supported(self): with self.assertRaises(Error.NotSupported): - # xyz is actually an extension that is recognized - # as mimetype chemical/x-xyz - Reader(os.path.join(FIXTURES_DIR, "C.xyz")) + # txt maps to text/plain in Python's built-in mimetypes + # default map, and text/plain isn't a supported mimetype now + Reader(os.path.join(FIXTURES_DIR, "C.txt")) def test_try_create_raises_mimetype_not_supported(self): with self.assertRaises(Error.NotSupported): - # xyz is actually an extension that is recognized - # as mimetype chemical/x-xyz, but we don't support it - Reader.try_create(os.path.join(FIXTURES_DIR, "C.xyz")) + # txt maps to text/plain in Python's built-in mimetypes + # default map, and text/plain isn't a supported mimetype now + Reader.try_create(os.path.join(FIXTURES_DIR, "C.txt")) def test_unrecognized_extension_defers_to_detection(self): with tempfile.TemporaryDirectory() as tmp: From 77bfe3248b95d7b6cfc25fe27705851a12a2ab4a Mon Sep 17 00:00:00 2001 From: Tania Mathern Date: Wed, 22 Jul 2026 14:03:41 -0700 Subject: [PATCH 4/5] fix: Update the code --- src/c2pa/c2pa.py | 50 +++++++++++++++++++--------------------- tests/test_unit_tests.py | 14 +++++------ 2 files changed, 31 insertions(+), 33 deletions(-) diff --git a/src/c2pa/c2pa.py b/src/c2pa/c2pa.py index 60f3bd98..9a7dff08 100644 --- a/src/c2pa/c2pa.py +++ b/src/c2pa/c2pa.py @@ -1197,19 +1197,18 @@ def load_settings(settings: Union[str, dict], format: str = "json") -> None: def _get_mime_type_from_path(path: Union[str, Path]) -> str: """Attempt to guess the MIME type from a file path's extension. - When the extension is missing or unrecognized, this returns an empty - string so the caller can hand it to the native layer for auto-detection - from the asset's magic bytes (see Reader). A recognized-but-wrong - extension still returns its MIME type; the native layer corrects it from - the bytes when reading. + string so the caller hands it to the lib for auto-detection (guess 1). + A recognized-but-wrong extension still returns its MIME type; the native + layer attempts to correct it from the bytes when reading (guess 2). Args: path: File path as string or Path object Returns: MIME type string, or an empty string when it cannot be determined - from the extension (signals native auto-detection). + from the extension. + An empty string here means the native lib should attempt auto-detect. """ path_obj = Path(path) file_extension = path_obj.suffix.lower() if path_obj.suffix else "" @@ -1219,8 +1218,8 @@ def _get_mime_type_from_path(path: Union[str, Path]) -> str: # so we bypass it and set the correct type return "image/dng" else: - # Fall back to an empty string for extensionless or unknown files so - # the native layer can detect the format from the asset's bytes. + # Fall back to an empty string for extensionless or unknown files. + # Empty string flags this as a guess-type attempt. return mimetypes.guess_type(str(path))[0] or "" @@ -1973,13 +1972,12 @@ def _get_supported_mime_types(ffi_func, cache): def _validate_and_encode_format( format_str: str, supported_types: list[str], class_name: str ) -> bytes: - """Validate a MIME type / format string and encode it to UTF-8 bytes. + """Validate a MIME type/format string and encode it to UTF-8 bytes. - A blank format (empty or whitespace-only) is treated as a request for - native format auto-detection: it skips the supported-types check and - encodes to empty bytes, letting the native library infer the format from - the asset's magic bytes. A non-empty format is still validated against the - supported list. + A blank format (e.g. empty) is treated as a request for format auto-detect: + it skips the supported-types check and encodes to empty bytes, + letting the native library guess the format. + A non-empty format is still validated against the supported list. Args: format_str: The MIME type or format string to validate. Pass an empty @@ -1992,8 +1990,10 @@ def _validate_and_encode_format( UTF-8 encoded format bytes (empty bytes for auto-detection) Raises: - C2paError.NotSupported: If a non-empty format is not supported - C2paError.Encoding: If the string contains invalid UTF-8 characters + C2paError.NotSupported: If format non-empty and + non-empty format unsupported. + C2paError.Encoding: If the non-empty string contains + invalid UTF-8 characters """ if not format_str.strip(): return b"" @@ -2149,14 +2149,14 @@ def __init__( """Create a new Reader. The format is optional: pass an empty string (or read an extensionless - file by path) to let the native library detect the format from the - asset's magic bytes. A recognized but wrong format/extension is also - corrected from the bytes when reading. If the bytes are not a - recognized asset, a C2paError is raised. + file by path) to let the native library detect the format. + A recognized but wrong format/extension is also corrected from the bytes + when reading (so reading doesn't fail on wrong file extension). + If the bytes are not a recognized asset, a C2paError is raised. Args: - format_or_path: The format (MIME type) or path to read from. An - empty string requests auto-detection from the asset's bytes. + format_or_path: The format (MIME type) or path to read from. + An empty string is an auto-detection request. stream: Optional stream to read from (Python stream-like object) manifest_data: Optional manifest data in bytes context: Optional context implementing ContextProvider with settings @@ -2196,8 +2196,7 @@ def __init__( if stream is None: # Create a stream from the file path in format_or_path. - # An empty MIME type (extensionless/unknown file) is passed - # through so the native layer attempts auto-detect from the bytes. + # Empty format = native lib will try to guess format. path = str(format_or_path) mime_type = _get_mime_type_from_path(path) @@ -2290,8 +2289,7 @@ def _init_from_context(self, context, format_or_path, supported = Reader.get_supported_mime_types() if stream is None: - # An empty MIME type (extensionless / unknown file) is passed - # through so the native layer auto-detects from the bytes. + # Empty format = native lib will try to guess format. path = str(format_or_path) mime_type = _get_mime_type_from_path(path) format_bytes = _validate_and_encode_format( diff --git a/tests/test_unit_tests.py b/tests/test_unit_tests.py index 7f8b6e33..d4f212d1 100644 --- a/tests/test_unit_tests.py +++ b/tests/test_unit_tests.py @@ -336,7 +336,7 @@ def test_reader_detects_unsupported_mimetype_on_file(self): Reader("mimetype/does-not-exist", self.testPath) def test_read_extensionless_file_path(self): - # A good file with no extension is read by detecting the format. + # Extensionless file triggers type auto-detection. with tempfile.TemporaryDirectory() as tmp: no_ext = os.path.join(tmp, "C") shutil.copyfile(self.testPath, no_ext) @@ -351,6 +351,7 @@ def test_read_extensionless_stream_empty_format(self): def test_read_wrong_extension_corrected(self): # A JPEG saved with a .png extension is corrected from the bytes. + # (Read is possible and does not fail due to wrong type). with tempfile.TemporaryDirectory() as tmp: wrong = os.path.join(tmp, "C.png") shutil.copyfile(self.testPath, wrong) @@ -364,14 +365,13 @@ def test_read_wrong_mime_corrected_on_stream(self): self.assertIn(DEFAULT_TEST_FILE_NAME, reader.json()) def test_explicit_empty_format_forces_detection(self): - # Passing "" works even when the correct format is known. + # Passing "" works even when the correct format is supported. with open(self.testPath, "rb") as file: with Reader("", file) as reader: manifest_store = json.loads(reader.json()) self.assertIn("active_manifest", manifest_store) def test_autodetect_multiformat(self): - # Detection works across container families, not just JPEG. fixtures = [ os.path.join(FIXTURES_DIR, "files-for-reading-tests", "CA.jpg"), os.path.join(FIXTURES_DIR, "video1.mp4"), @@ -385,7 +385,6 @@ def test_autodetect_multiformat(self): self.assertIn("active_manifest", json.loads(reader.json())) def test_dng_extension_still_special_cased(self): - # The .dng path keeps its special-case MIME and still reads. dng_path = os.path.join(FIXTURES_DIR, "C.dng") with Reader(dng_path) as reader: self.assertIn("active_manifest", json.loads(reader.json())) @@ -396,7 +395,7 @@ def test_garbage_stream_empty_format_raises(self): Reader("", io.BytesIO(b"not an asset at all")) def test_empty_stream_raises(self): - # A zero-byte stream cannot be detected and raises cleanly. + # A zero-byte stream cannot be detected and raises. with self.assertRaises(Error): Reader("", io.BytesIO(b"")) @@ -404,13 +403,14 @@ def test_truncated_corrupt_jpeg_raises(self): with open(self.testPath, "rb") as file: data = bytearray(file.read()) # Corrupt the body while keeping the leading JPEG magic intact. + # This will still raise errors. for i in range(64, min(len(data), 4096)): data[i] ^= 0xFF with self.assertRaises(Error): Reader("", io.BytesIO(bytes(data))) def test_garbage_extensionless_file_raises(self): - # Random bytes in an extensionless file raise cleanly. + # Random bytes in an extensionless file raise. with tempfile.TemporaryDirectory() as tmp: garbage = os.path.join(tmp, "garbage") with open(garbage, "wb") as f: @@ -433,11 +433,11 @@ def test_try_create_extensionless_no_manifest_returns_none(self): def test_sub_magic_length_stream_raises(self): # Fewer bytes than a full magic signature cannot be detected. + # This will raise too. with self.assertRaises(Error): Reader("", io.BytesIO(b"\xff\xd8\xff")) def test_preseeked_stream_is_rewound(self): - # Detection rewinds the stream with open(self.testPath, "rb") as file: data = file.read() stream = io.BytesIO(data) From 613383ba710ab8ba88cc1c1fec45ffc8b625db20 Mon Sep 17 00:00:00 2001 From: Tania Mathern Date: Wed, 22 Jul 2026 14:06:13 -0700 Subject: [PATCH 5/5] fix: Update the code 2 --- src/c2pa/c2pa.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/c2pa/c2pa.py b/src/c2pa/c2pa.py index 9a7dff08..9ca6f957 100644 --- a/src/c2pa/c2pa.py +++ b/src/c2pa/c2pa.py @@ -1198,16 +1198,17 @@ def load_settings(settings: Union[str, dict], format: str = "json") -> None: def _get_mime_type_from_path(path: Union[str, Path]) -> str: """Attempt to guess the MIME type from a file path's extension. When the extension is missing or unrecognized, this returns an empty - string so the caller hands it to the lib for auto-detection (guess 1). - A recognized-but-wrong extension still returns its MIME type; the native - layer attempts to correct it from the bytes when reading (guess 2). + string so the caller hands it to the lib for auto-detection. + A recognized-but-wrong extension still returns a mimetype: + the native layer will attempt to correct it from the bytes when + reading (the real type still needs to be supported by the lib). Args: path: File path as string or Path object Returns: - MIME type string, or an empty string when it cannot be determined - from the extension. + MIME type string, or an empty string + (when it cannot be determined from the extension). An empty string here means the native lib should attempt auto-detect. """ path_obj = Path(path)