55import os
66import warnings
77from pathlib import Path
8- from typing import Optional , Union , Callable , Any
8+ from typing import Optional , Union , Callable , Any , overload
99import time
1010from .lib import dynamically_load_library
1111import mimetypes
@@ -578,7 +578,7 @@ def read_file(path: Union[str, Path],
578578 C2paError: If there was an error reading the file
579579 """
580580 warnings .warn (
581- "The read_file function is deprecated and will be removed in a future version. "
581+ "The read_file function is deprecated and will be removed in a future version."
582582 "Please use the Reader class for reading C2PA metadata instead." ,
583583 DeprecationWarning ,
584584 stacklevel = 2 )
@@ -592,26 +592,50 @@ def read_file(path: Union[str, Path],
592592 return _parse_operation_result_for_error (result )
593593
594594
595+ @overload
595596def sign_file (
596597 source_path : Union [str , Path ],
597598 dest_path : Union [str , Path ],
598599 manifest : str ,
599- signer_info : C2paSignerInfo ,
600- data_dir : Optional [Union [str , Path ]] = None
600+ signer_info : C2paSignerInfo
601601) -> str :
602- """Sign a file with a C2PA manifest.
603- For now, this function is left here to provide a backwards-compatible API.
602+ """Sign a file with a C2PA manifest using signer info.
603+
604+ .. deprecated:: 0.10.0
605+ This function is deprecated and will be removed in a future version.
606+ Please use the Builder class for signing and the Reader class for reading signed data instead.
607+ """
608+ ...
609+
610+ @overload
611+ def sign_file (
612+ source_path : Union [str , Path ],
613+ dest_path : Union [str , Path ],
614+ manifest : str ,
615+ signer : 'Signer'
616+ ) -> str :
617+ """Sign a file with a C2PA manifest using a signer.
604618
605619 .. deprecated:: 0.10.0
606620 This function is deprecated and will be removed in a future version.
607621 Please use the Builder class for signing and the Reader class for reading signed data instead.
622+ """
623+ ...
624+
625+ def sign_file (
626+ source_path : Union [str , Path ],
627+ dest_path : Union [str , Path ],
628+ manifest : str ,
629+ signer_or_info : Union [C2paSignerInfo , 'Signer' ]
630+ ) -> str :
631+ """Sign a file with a C2PA manifest.
632+ For now, this function is left here to provide a backwards-compatible API.
608633
609634 Args:
610635 source_path: Path to the source file
611636 dest_path: Path to write the signed file to
612637 manifest: The manifest JSON string
613- signer_info: Signing configuration
614- data_dir: Optional directory to write binary resources to
638+ signer_or_info: Either a signer configuration or a signer object
615639
616640 Returns:
617641 The signed manifest as a JSON string
@@ -621,15 +645,15 @@ def sign_file(
621645 C2paError.Encoding: If any of the string inputs contain invalid UTF-8 characters
622646 C2paError.NotSupported: If the file type cannot be determined
623647 """
624- warnings .warn (
625- "The sign_file function is deprecated and will be removed in a future version. "
626- "Please use the Builder class for signing and the Reader class for reading signed data instead." ,
627- DeprecationWarning ,
628- stacklevel = 2 )
629648
630649 try :
631- # Create a signer from the signer info
632- signer = Signer .from_info (signer_info )
650+ # Determine if we have a signer or signer info
651+ if isinstance (signer_or_info , C2paSignerInfo ):
652+ signer = Signer .from_info (signer_or_info )
653+ own_signer = True
654+ else :
655+ signer = signer_or_info
656+ own_signer = False
633657
634658 # Create a builder from the manifest
635659 builder = Builder (manifest )
@@ -643,19 +667,13 @@ def sign_file(
643667 f"Could not determine MIME type for file: { source_path } " )
644668
645669 # Sign the file using the builder
646- manifest_bytes = builder .sign (
670+ builder .sign (
647671 signer = signer ,
648672 format = mime_type ,
649673 source = source_file ,
650674 dest = dest_file
651675 )
652676
653- # If we have manifest bytes and a data directory, write them
654- if manifest_bytes and data_dir :
655- manifest_path = os .path .join (str (data_dir ), 'manifest.json' )
656- with open (manifest_path , 'wb' ) as f :
657- f .write (manifest_bytes )
658-
659677 # Read the signed manifest from the destination file
660678 with Reader (dest_path ) as reader :
661679 return reader .json ()
@@ -674,73 +692,10 @@ def sign_file(
674692 # Ensure resources are cleaned up
675693 if 'builder' in locals ():
676694 builder .close ()
677- if 'signer' in locals ():
695+ if 'signer' in locals () and own_signer :
678696 signer .close ()
679697
680698
681- def sign_file_using_callback_signer (
682- source_path : Union [str , Path ],
683- dest_path : Union [str , Path ],
684- manifest : str ,
685- signer : 'Signer'
686- ) -> bytes :
687- """Sign a file with a C2PA manifest using a signer.
688-
689- This function provides a shortcut to sign files using a signer
690- and returns the raw manifest bytes.
691-
692- Args:
693- source_path: Path to the source file
694- dest_path: Path to write the signed file to
695- manifest: The manifest JSON string
696- signer: The signer to use
697-
698- Returns:
699- The manifest bytes (binary data)
700-
701- Raises:
702- C2paError: If there was an error signing the file
703- C2paError.Encoding: If any of the string inputs contain invalid UTF-8 characters
704- C2paError.NotSupported: If the file type cannot be determined
705- """
706- try :
707- # Create a builder from the manifest
708- builder = Builder (manifest )
709-
710- # Open source and destination files
711- with open (source_path , 'rb' ) as source_file , open (dest_path , 'wb' ) as dest_file :
712- # Get the MIME type from the file extension
713- mime_type = mimetypes .guess_type (str (source_path ))[0 ]
714- if not mime_type :
715- raise C2paError .NotSupported (
716- f"Could not determine MIME type for file: { source_path } " )
717-
718- # Convert Python streams to Stream objects
719- source_stream = Stream (source_file )
720- dest_stream = Stream (dest_file )
721-
722- # Use the builder's internal signing logic
723- result , manifest_bytes = builder ._sign_internal (
724- signer , mime_type , source_stream , dest_stream )
725-
726- return manifest_bytes
727-
728- except Exception as e :
729- # Clean up destination file if it exists and there was an error
730- if os .path .exists (dest_path ):
731- try :
732- os .remove (dest_path )
733- except OSError :
734- pass # Ignore cleanup errors
735-
736- # Re-raise the error
737- raise C2paError (f"Error signing file: { str (e )} " )
738- finally :
739- # Ensure resources are cleaned up
740- if 'builder' in locals ():
741- builder .close ()
742-
743-
744699class Stream :
745700 # Class-level counter for generating unique stream IDs
746701 # (useful for tracing streams usage in debug)
@@ -2093,12 +2048,11 @@ def ed25519_sign(data: bytes, private_key: str) -> bytes:
20932048 'Reader' ,
20942049 'Builder' ,
20952050 'Signer' ,
2096- 'version' ,
20972051 'load_settings' ,
20982052 'read_file' ,
20992053 'read_ingredient_file' ,
21002054 'sign_file' ,
2101- 'sign_file_using_callback_signer' ,
21022055 'format_embeddable' ,
2056+ 'version' ,
21032057 'sdk_version'
21042058]
0 commit comments