4
4
# The following comment should be removed at some point in the future.
5
5
# mypy: strict-optional=False
6
6
7
- import email .errors
8
7
import gzip
9
8
import json
10
9
import mimetypes
20
19
from pip ._internal .cache import LinkMetadataCache , should_cache
21
20
from pip ._internal .distributions import make_distribution_for_install_requirement
22
21
from pip ._internal .exceptions import (
22
+ CacheMetadataError ,
23
23
DirectoryUrlHashUnsupported ,
24
24
HashMismatch ,
25
25
HashUnpinned ,
32
32
from pip ._internal .metadata import (
33
33
BaseDistribution ,
34
34
get_metadata_distribution ,
35
+ serialize_metadata ,
35
36
)
36
37
from pip ._internal .models .direct_url import ArchiveInfo
37
38
from pip ._internal .models .link import Link
@@ -230,7 +231,7 @@ class CacheableDist:
230
231
def from_dist (cls , link : Link , dist : BaseDistribution ) -> "CacheableDist" :
231
232
"""Extract the serializable data necessary to generate a metadata-only dist."""
232
233
return cls (
233
- metadata = str (dist .metadata ),
234
+ metadata = serialize_metadata (dist .metadata ),
234
235
filename = Path (link .filename ),
235
236
canonical_name = dist .canonical_name ,
236
237
)
@@ -251,7 +252,7 @@ def to_json(self) -> Dict[str, Any]:
251
252
}
252
253
253
254
@classmethod
254
- def from_json (cls , args : Dict [str , Any ]) -> "CacheableDist" :
255
+ def from_json (cls , args : Dict [str , str ]) -> "CacheableDist" :
255
256
return cls (
256
257
metadata = args ["metadata" ],
257
258
filename = Path (args ["filename" ]),
@@ -458,17 +459,10 @@ def _fetch_cached_metadata(
458
459
"found cached metadata for link %s at %s" , req .link , f .name
459
460
)
460
461
args = json .load (f )
461
- cached_dist = CacheableDist .from_json (args )
462
- return cached_dist .to_dist ()
463
- except (OSError , json .JSONDecodeError , KeyError ) as e :
464
- logger .exception (
465
- "error reading cached metadata for link %s at %s %s(%s)" ,
466
- req .link ,
467
- cached_path ,
468
- e .__class__ .__name__ ,
469
- str (e ),
470
- )
471
- raise
462
+ cached_dist = CacheableDist .from_json (args )
463
+ return cached_dist .to_dist ()
464
+ except Exception :
465
+ raise CacheMetadataError (req , "error reading cached metadata" )
472
466
473
467
def _cache_metadata (
474
468
self ,
@@ -490,23 +484,13 @@ def _cache_metadata(
490
484
# containing directory for the cache file exists before writing.
491
485
os .makedirs (str (cached_path .parent ), exist_ok = True )
492
486
try :
487
+ cacheable_dist = CacheableDist .from_dist (req .link , metadata_dist )
488
+ args = cacheable_dist .to_json ()
489
+ logger .debug ("caching metadata for link %s at %s" , req .link , cached_path )
493
490
with gzip .open (cached_path , mode = "wt" , encoding = "utf-8" ) as f :
494
- cacheable_dist = CacheableDist .from_dist (req .link , metadata_dist )
495
- args = cacheable_dist .to_json ()
496
- logger .debug ("caching metadata for link %s at %s" , req .link , f .name )
497
491
json .dump (args , f )
498
- except (OSError , email .errors .HeaderParseError ) as e :
499
- # TODO: Some dists raise email.errors.HeaderParseError when calling str() or
500
- # bytes() on the metadata, which is an email.Message. This is probably a bug
501
- # in email parsing.
502
- logger .exception (
503
- "error caching metadata for dist %s from %s: %s(%s)" ,
504
- metadata_dist ,
505
- req .link ,
506
- e .__class__ .__name__ ,
507
- str (e ),
508
- )
509
- raise
492
+ except Exception :
493
+ raise CacheMetadataError (req , "failed to serialize metadata" )
510
494
511
495
def _fetch_metadata_using_link_data_attr (
512
496
self ,
0 commit comments