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