4
4
5
5
This module returns the installation location of cacert.pem or its contents.
6
6
"""
7
- import os
8
- import types
9
- from typing import Union
7
+ import sys
10
8
11
- try :
12
- from importlib .resources import path as get_path , read_text
9
+
10
+ if sys .version_info >= (3 , 9 ):
11
+
12
+ from importlib .resources import as_file , files
13
13
14
14
_CACERT_CTX = None
15
15
_CACERT_PATH = None
@@ -33,36 +33,45 @@ def where() -> str:
33
33
# We also have to hold onto the actual context manager, because
34
34
# it will do the cleanup whenever it gets garbage collected, so
35
35
# we will also store that at the global level as well.
36
- _CACERT_CTX = get_path ( "certifi" , "cacert.pem" )
36
+ _CACERT_CTX = as_file ( files ( "certifi" ). joinpath ( "cacert.pem" ) )
37
37
_CACERT_PATH = str (_CACERT_CTX .__enter__ ())
38
38
39
39
return _CACERT_PATH
40
40
41
+ def contents () -> str :
42
+ return files ("certifi" ).joinpath ("cacert.pem" ).read_text (encoding = "ascii" )
43
+
44
+ else :
41
45
42
- except ImportError :
43
- Package = Union [types .ModuleType , str ]
44
- Resource = Union [str , "os.PathLike" ]
46
+ from importlib .resources import path as get_path , read_text
45
47
46
- # This fallback will work for Python versions prior to 3.7 that lack the
47
- # importlib.resources module but relies on the existing `where` function
48
- # so won't address issues with environments like PyOxidizer that don't set
49
- # __file__ on modules.
50
- def read_text (
51
- package : Package ,
52
- resource : Resource ,
53
- encoding : str = 'utf-8' ,
54
- errors : str = 'strict'
55
- ) -> str :
56
- with open (where (), encoding = encoding ) as data :
57
- return data .read ()
48
+ _CACERT_CTX = None
49
+ _CACERT_PATH = None
58
50
59
- # If we don't have importlib.resources, then we will just do the old logic
60
- # of assuming we're on the filesystem and munge the path directly.
61
51
def where () -> str :
62
- f = os .path .dirname (__file__ )
63
-
64
- return os .path .join (f , "cacert.pem" )
52
+ # This is slightly terrible, but we want to delay extracting the
53
+ # file in cases where we're inside of a zipimport situation until
54
+ # someone actually calls where(), but we don't want to re-extract
55
+ # the file on every call of where(), so we'll do it once then store
56
+ # it in a global variable.
57
+ global _CACERT_CTX
58
+ global _CACERT_PATH
59
+ if _CACERT_PATH is None :
60
+ # This is slightly janky, the importlib.resources API wants you
61
+ # to manage the cleanup of this file, so it doesn't actually
62
+ # return a path, it returns a context manager that will give
63
+ # you the path when you enter it and will do any cleanup when
64
+ # you leave it. In the common case of not needing a temporary
65
+ # file, it will just return the file system location and the
66
+ # __exit__() is a no-op.
67
+ #
68
+ # We also have to hold onto the actual context manager, because
69
+ # it will do the cleanup whenever it gets garbage collected, so
70
+ # we will also store that at the global level as well.
71
+ _CACERT_CTX = get_path ("certifi" , "cacert.pem" )
72
+ _CACERT_PATH = str (_CACERT_CTX .__enter__ ())
65
73
74
+ return _CACERT_PATH
66
75
67
- def contents () -> str :
68
- return read_text ("certifi" , "cacert.pem" , encoding = "ascii" )
76
+ def contents () -> str :
77
+ return read_text ("certifi" , "cacert.pem" , encoding = "ascii" )
0 commit comments