1+ import logging
12import os
3+ import ssl
24import typing as T
35
46import requests
7+ from requests .adapters import HTTPAdapter
58
9+ LOG = logging .getLogger (__name__ )
610MAPILLARY_CLIENT_TOKEN = os .getenv (
711 "MAPILLARY_CLIENT_TOKEN" , "MLY|5675152195860640|6b02c72e6e3c801e5603ab0495623282"
812)
913MAPILLARY_GRAPH_API_ENDPOINT = os .getenv (
1014 "MAPILLARY_GRAPH_API_ENDPOINT" , "https://graph.mapillary.com"
1115)
1216REQUESTS_TIMEOUT = 60 # 1 minutes
17+ USE_SYSTEM_CERTS : bool = False
18+
19+
20+ class HTTPSystemCertsAdapter (HTTPAdapter ):
21+ """
22+ This adapter uses the system's certificate store instead of the certifi module.
23+
24+ The implementation is based on the project https://pypi.org/project/pip-system-certs/,
25+ which has a system-wide effect.
26+ """
27+
28+ def init_poolmanager (self , * args , ** kwargs ):
29+ ssl_context = ssl .create_default_context ()
30+ ssl_context .load_default_certs ()
31+ kwargs ["ssl_context" ] = ssl_context
32+
33+ super ().init_poolmanager (* args , ** kwargs )
34+
35+ def cert_verify (self , * args , ** kwargs ):
36+ super ().cert_verify (* args , ** kwargs )
37+
38+ # By default Python requests uses the ca_certs from the certifi module
39+ # But we want to use the certificate store instead.
40+ # By clearing the ca_certs variable we force it to fall back on that behaviour (handled in urllib3)
41+ if "conn" in kwargs :
42+ conn = kwargs ["conn" ]
43+ else :
44+ conn = args [0 ]
45+
46+ conn .ca_certs = None
47+
48+
49+ def request_post (
50+ url : str ,
51+ data : T .Optional [T .Any ] = None ,
52+ json : T .Optional [dict ] = None ,
53+ ** kwargs ,
54+ ) -> requests .Response :
55+ global USE_SYSTEM_CERTS
56+
57+ if USE_SYSTEM_CERTS :
58+ with requests .Session () as session :
59+ session .mount ("https://" , HTTPSystemCertsAdapter ())
60+ return session .post (url , data = data , json = json , ** kwargs )
61+
62+ else :
63+ try :
64+ return requests .post (url , data = data , json = json , ** kwargs )
65+ except requests .exceptions .SSLError as ex :
66+ if "SSLCertVerificationError" not in str (ex ):
67+ raise ex
68+ USE_SYSTEM_CERTS = True
69+ # HTTPSConnectionPool(host='graph.mapillary.com', port=443): Max retries exceeded with url: /login (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1018)')))
70+ LOG .warning (
71+ "SSL error occurred, falling back to system SSL certificates: %s" , ex
72+ )
73+ with requests .Session () as session :
74+ session .mount ("https://" , HTTPSystemCertsAdapter ())
75+ return session .post (url , data = data , json = json , ** kwargs )
76+
77+
78+ def request_get (
79+ url : str ,
80+ params : T .Optional [dict ] = None ,
81+ ** kwargs ,
82+ ) -> requests .Response :
83+ global USE_SYSTEM_CERTS
84+
85+ if USE_SYSTEM_CERTS :
86+ with requests .Session () as session :
87+ session .mount ("https://" , HTTPSystemCertsAdapter ())
88+ return session .get (url , params = params , ** kwargs )
89+ else :
90+ try :
91+ return requests .get (url , params = params , ** kwargs )
92+ except requests .exceptions .SSLError as ex :
93+ if "SSLCertVerificationError" not in str (ex ):
94+ raise ex
95+ USE_SYSTEM_CERTS = True
96+ # HTTPSConnectionPool(host='graph.mapillary.com', port=443): Max retries exceeded with url: /login (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1018)')))
97+ LOG .warning (
98+ "SSL error occurred, falling back to system SSL certificates: %s" , ex
99+ )
100+ with requests .Session () as session :
101+ session .mount ("https://" , HTTPSystemCertsAdapter ())
102+ return session .get (url , params = params , ** kwargs )
13103
14104
15105def get_upload_token (email : str , password : str ) -> requests .Response :
16- resp = requests . post (
106+ resp = request_post (
17107 f"{ MAPILLARY_GRAPH_API_ENDPOINT } /login" ,
18108 params = {"access_token" : MAPILLARY_CLIENT_TOKEN },
19109 json = {"email" : email , "password" : password , "locale" : "en_US" },
@@ -26,7 +116,7 @@ def get_upload_token(email: str, password: str) -> requests.Response:
26116def fetch_organization (
27117 user_access_token : str , organization_id : T .Union [int , str ]
28118) -> requests .Response :
29- resp = requests . get (
119+ resp = request_get (
30120 f"{ MAPILLARY_GRAPH_API_ENDPOINT } /{ organization_id } " ,
31121 params = {
32122 "fields" : "," .join (["slug" , "description" , "name" ]),
@@ -45,8 +135,8 @@ def fetch_organization(
45135]
46136
47137
48- def logging (action_type : ActionType , properties : T .Dict ) -> requests .Response :
49- resp = requests . post (
138+ def log_event (action_type : ActionType , properties : T .Dict ) -> requests .Response :
139+ resp = request_post (
50140 f"{ MAPILLARY_GRAPH_API_ENDPOINT } /logging" ,
51141 json = {
52142 "action_type" : action_type ,
0 commit comments