66import email .policy
77import keyword
88import pathlib
9- import sys
109import typing
1110from typing import (
1211 Any ,
1918
2019from . import licenses , requirements , specifiers , utils
2120from . import version as version_module
21+ from .errors import ExceptionGroup , _ErrorCollector
2222
2323if typing .TYPE_CHECKING :
2424 from .licenses import NormalizedLicenseExpression
2525
2626T = typing .TypeVar ("T" )
2727
2828
29- if sys .version_info >= (3 , 11 ): # pragma: no cover
30- ExceptionGroup = ExceptionGroup # noqa: F821
31- else : # pragma: no cover
32-
33- class ExceptionGroup (Exception ):
34- """A minimal implementation of :external:exc:`ExceptionGroup` from Python 3.11.
35-
36- If :external:exc:`ExceptionGroup` is already defined by Python itself,
37- that version is used instead.
38- """
39-
40- message : str
41- exceptions : list [Exception ]
42-
43- def __init__ (self , message : str , exceptions : list [Exception ]) -> None :
44- self .message = message
45- self .exceptions = exceptions
46-
47- def __repr__ (self ) -> str :
48- return f"{ self .__class__ .__name__ } ({ self .message !r} , { self .exceptions !r} )"
49-
50-
5129__all__ = [
5230 "InvalidMetadata" ,
5331 "Metadata" ,
@@ -797,13 +775,11 @@ def from_raw(cls, data: RawMetadata, *, validate: bool = True) -> Metadata:
797775 ins ._raw = data .copy () # Mutations occur due to caching enriched values.
798776
799777 if validate :
800- exceptions : list [Exception ] = []
801- try :
778+ collector = _ErrorCollector ()
779+ metadata_version = None
780+ with collector .collect (InvalidMetadata ):
802781 metadata_version = ins .metadata_version
803782 metadata_age = _VALID_METADATA_VERSIONS .index (metadata_version )
804- except InvalidMetadata as metadata_version_exc :
805- exceptions .append (metadata_version_exc )
806- metadata_version = None
807783
808784 # Make sure to check for the fields that are present, the required
809785 # fields (so their absence can be reported).
@@ -820,7 +796,7 @@ def from_raw(cls, data: RawMetadata, *, validate: bool = True) -> Metadata:
820796 field_metadata_version = cls .__dict__ [key ].added
821797 except KeyError :
822798 exc = InvalidMetadata (key , f"unrecognized field: { key !r} " )
823- exceptions . append (exc )
799+ collector . error (exc )
824800 continue
825801 field_age = _VALID_METADATA_VERSIONS .index (
826802 field_metadata_version
@@ -832,14 +808,13 @@ def from_raw(cls, data: RawMetadata, *, validate: bool = True) -> Metadata:
832808 f"{ field } introduced in metadata version "
833809 f"{ field_metadata_version } , not { metadata_version } " ,
834810 )
835- exceptions . append (exc )
811+ collector . error (exc )
836812 continue
837813 getattr (ins , key )
838814 except InvalidMetadata as exc :
839- exceptions . append (exc )
815+ collector . error (exc )
840816
841- if exceptions :
842- raise ExceptionGroup ("invalid metadata" , exceptions )
817+ collector .finalize ("invalid metadata" )
843818
844819 return ins
845820
@@ -853,16 +828,13 @@ def from_email(cls, data: bytes | str, *, validate: bool = True) -> Metadata:
853828 raw , unparsed = parse_email (data )
854829
855830 if validate :
856- exceptions : list [Exception ] = []
857- for unparsed_key in unparsed :
858- if unparsed_key in _EMAIL_TO_RAW_MAPPING :
859- message = f"{ unparsed_key !r} has invalid data"
860- else :
861- message = f"unrecognized field: { unparsed_key !r} "
862- exceptions .append (InvalidMetadata (unparsed_key , message ))
863-
864- if exceptions :
865- raise ExceptionGroup ("unparsed" , exceptions )
831+ with _ErrorCollector ().on_exit ("unparsed" ) as collector :
832+ for unparsed_key in unparsed :
833+ if unparsed_key in _EMAIL_TO_RAW_MAPPING :
834+ message = f"{ unparsed_key !r} has invalid data"
835+ else :
836+ message = f"unrecognized field: { unparsed_key !r} "
837+ collector .error (InvalidMetadata (unparsed_key , message ))
866838
867839 try :
868840 return cls .from_raw (raw , validate = validate )
0 commit comments