2020import shlex
2121import subprocess
2222from os .path import expanduser , expandvars
23+ from pathlib import Path
2324from typing import List , Optional , Union
2425
25- from gitlab .const import USER_AGENT
26+ from gitlab .const import DEFAULT_URL , USER_AGENT
2627
27-
28- def _env_config () -> List [str ]:
29- if "PYTHON_GITLAB_CFG" in os .environ :
30- return [os .environ ["PYTHON_GITLAB_CFG" ]]
31- return []
32-
33-
34- _DEFAULT_FILES : List [str ] = _env_config () + [
28+ _DEFAULT_FILES : List [str ] = [
3529 "/etc/python-gitlab.cfg" ,
36- os . path . expanduser ( "~/ .python-gitlab.cfg" ),
30+ str ( Path . home () / " .python-gitlab.cfg" ),
3731]
3832
3933HELPER_PREFIX = "helper:"
4034
4135HELPER_ATTRIBUTES = ["job_token" , "http_password" , "private_token" , "oauth_token" ]
4236
4337
38+ def _resolve_file (filepath : Union [Path , str ]) -> str :
39+ resolved = Path (filepath ).resolve (strict = True )
40+ return str (resolved )
41+
42+
43+ def _get_config_files (
44+ config_files : Optional [List [str ]] = None ,
45+ ) -> Union [str , List [str ]]:
46+ """
47+ Return resolved path(s) to config files if they exist, with precedence:
48+ 1. Files passed in config_files
49+ 2. File defined in PYTHON_GITLAB_CFG
50+ 3. User- and system-wide config files
51+ """
52+ resolved_files = []
53+
54+ if config_files :
55+ for config_file in config_files :
56+ try :
57+ resolved = _resolve_file (config_file )
58+ except OSError as e :
59+ raise GitlabConfigMissingError (f"Cannot read config from file: { e } " )
60+ resolved_files .append (resolved )
61+
62+ return resolved_files
63+
64+ try :
65+ env_config = os .environ ["PYTHON_GITLAB_CFG" ]
66+ return _resolve_file (env_config )
67+ except KeyError :
68+ pass
69+ except OSError as e :
70+ raise GitlabConfigMissingError (
71+ f"Cannot read config from PYTHON_GITLAB_CFG: { e } "
72+ )
73+
74+ for config_file in _DEFAULT_FILES :
75+ try :
76+ resolved = _resolve_file (config_file )
77+ except OSError :
78+ continue
79+ resolved_files .append (resolved )
80+
81+ return resolved_files
82+
83+
4484class ConfigError (Exception ):
4585 pass
4686
@@ -66,155 +106,149 @@ def __init__(
66106 self , gitlab_id : Optional [str ] = None , config_files : Optional [List [str ]] = None
67107 ) -> None :
68108 self .gitlab_id = gitlab_id
69- _files = config_files or _DEFAULT_FILES
70- file_exist = False
71- for file in _files :
72- if os .path .exists (file ):
73- file_exist = True
74- if not file_exist :
75- raise GitlabConfigMissingError (
76- "Config file not found. \n Please create one in "
77- "one of the following locations: {} \n or "
78- "specify a config file using the '-c' parameter." .format (
79- ", " .join (_DEFAULT_FILES )
80- )
81- )
109+ self .http_username : Optional [str ] = None
110+ self .http_password : Optional [str ] = None
111+ self .job_token : Optional [str ] = None
112+ self .oauth_token : Optional [str ] = None
113+ self .private_token : Optional [str ] = None
114+
115+ self .api_version : str = "4"
116+ self .order_by : Optional [str ] = None
117+ self .pagination : Optional [str ] = None
118+ self .per_page : Optional [int ] = None
119+ self .retry_transient_errors : bool = False
120+ self .ssl_verify : Union [bool , str ] = True
121+ self .timeout : int = 60
122+ self .url : str = DEFAULT_URL
123+ self .user_agent : str = USER_AGENT
82124
83- self ._config = configparser .ConfigParser ()
84- self ._config .read (_files )
125+ self ._files = _get_config_files (config_files )
126+ if self ._files :
127+ self ._parse_config ()
128+
129+ def _parse_config (self ) -> None :
130+ _config = configparser .ConfigParser ()
131+ _config .read (self ._files )
85132
86133 if self .gitlab_id is None :
87134 try :
88- self .gitlab_id = self . _config .get ("global" , "default" )
135+ self .gitlab_id = _config .get ("global" , "default" )
89136 except Exception as e :
90137 raise GitlabIDError (
91138 "Impossible to get the gitlab id (not specified in config file)"
92139 ) from e
93140
94141 try :
95- self .url = self . _config .get (self .gitlab_id , "url" )
142+ self .url = _config .get (self .gitlab_id , "url" )
96143 except Exception as e :
97144 raise GitlabDataError (
98145 "Impossible to get gitlab details from "
99146 f"configuration ({ self .gitlab_id } )"
100147 ) from e
101148
102- self .ssl_verify : Union [bool , str ] = True
103149 try :
104- self .ssl_verify = self . _config .getboolean ("global" , "ssl_verify" )
150+ self .ssl_verify = _config .getboolean ("global" , "ssl_verify" )
105151 except ValueError :
106152 # Value Error means the option exists but isn't a boolean.
107153 # Get as a string instead as it should then be a local path to a
108154 # CA bundle.
109155 try :
110- self .ssl_verify = self . _config .get ("global" , "ssl_verify" )
156+ self .ssl_verify = _config .get ("global" , "ssl_verify" )
111157 except Exception :
112158 pass
113159 except Exception :
114160 pass
115161 try :
116- self .ssl_verify = self . _config .getboolean (self .gitlab_id , "ssl_verify" )
162+ self .ssl_verify = _config .getboolean (self .gitlab_id , "ssl_verify" )
117163 except ValueError :
118164 # Value Error means the option exists but isn't a boolean.
119165 # Get as a string instead as it should then be a local path to a
120166 # CA bundle.
121167 try :
122- self .ssl_verify = self . _config .get (self .gitlab_id , "ssl_verify" )
168+ self .ssl_verify = _config .get (self .gitlab_id , "ssl_verify" )
123169 except Exception :
124170 pass
125171 except Exception :
126172 pass
127173
128- self .timeout = 60
129174 try :
130- self .timeout = self . _config .getint ("global" , "timeout" )
175+ self .timeout = _config .getint ("global" , "timeout" )
131176 except Exception :
132177 pass
133178 try :
134- self .timeout = self . _config .getint (self .gitlab_id , "timeout" )
179+ self .timeout = _config .getint (self .gitlab_id , "timeout" )
135180 except Exception :
136181 pass
137182
138- self .private_token = None
139183 try :
140- self .private_token = self . _config .get (self .gitlab_id , "private_token" )
184+ self .private_token = _config .get (self .gitlab_id , "private_token" )
141185 except Exception :
142186 pass
143187
144- self .oauth_token = None
145188 try :
146- self .oauth_token = self . _config .get (self .gitlab_id , "oauth_token" )
189+ self .oauth_token = _config .get (self .gitlab_id , "oauth_token" )
147190 except Exception :
148191 pass
149192
150- self .job_token = None
151193 try :
152- self .job_token = self . _config .get (self .gitlab_id , "job_token" )
194+ self .job_token = _config .get (self .gitlab_id , "job_token" )
153195 except Exception :
154196 pass
155197
156- self .http_username = None
157- self .http_password = None
158198 try :
159- self .http_username = self . _config .get (self .gitlab_id , "http_username" )
160- self .http_password = self . _config .get (self .gitlab_id , "http_password" )
199+ self .http_username = _config .get (self .gitlab_id , "http_username" )
200+ self .http_password = _config .get (self .gitlab_id , "http_password" )
161201 except Exception :
162202 pass
163203
164204 self ._get_values_from_helper ()
165205
166- self .api_version = "4"
167206 try :
168- self .api_version = self . _config .get ("global" , "api_version" )
207+ self .api_version = _config .get ("global" , "api_version" )
169208 except Exception :
170209 pass
171210 try :
172- self .api_version = self . _config .get (self .gitlab_id , "api_version" )
211+ self .api_version = _config .get (self .gitlab_id , "api_version" )
173212 except Exception :
174213 pass
175214 if self .api_version not in ("4" ,):
176215 raise GitlabDataError (f"Unsupported API version: { self .api_version } " )
177216
178- self .per_page = None
179217 for section in ["global" , self .gitlab_id ]:
180218 try :
181- self .per_page = self . _config .getint (section , "per_page" )
219+ self .per_page = _config .getint (section , "per_page" )
182220 except Exception :
183221 pass
184222 if self .per_page is not None and not 0 <= self .per_page <= 100 :
185223 raise GitlabDataError (f"Unsupported per_page number: { self .per_page } " )
186224
187- self .pagination = None
188225 try :
189- self .pagination = self . _config .get (self .gitlab_id , "pagination" )
226+ self .pagination = _config .get (self .gitlab_id , "pagination" )
190227 except Exception :
191228 pass
192229
193- self .order_by = None
194230 try :
195- self .order_by = self . _config .get (self .gitlab_id , "order_by" )
231+ self .order_by = _config .get (self .gitlab_id , "order_by" )
196232 except Exception :
197233 pass
198234
199- self .user_agent = USER_AGENT
200235 try :
201- self .user_agent = self . _config .get ("global" , "user_agent" )
236+ self .user_agent = _config .get ("global" , "user_agent" )
202237 except Exception :
203238 pass
204239 try :
205- self .user_agent = self . _config .get (self .gitlab_id , "user_agent" )
240+ self .user_agent = _config .get (self .gitlab_id , "user_agent" )
206241 except Exception :
207242 pass
208243
209- self .retry_transient_errors = False
210244 try :
211- self .retry_transient_errors = self . _config .getboolean (
245+ self .retry_transient_errors = _config .getboolean (
212246 "global" , "retry_transient_errors"
213247 )
214248 except Exception :
215249 pass
216250 try :
217- self .retry_transient_errors = self . _config .getboolean (
251+ self .retry_transient_errors = _config .getboolean (
218252 self .gitlab_id , "retry_transient_errors"
219253 )
220254 except Exception :
0 commit comments