@@ -77,6 +77,7 @@ class ConfigReader(ConfigFileReader):
7777 config_name = "standard"
7878 config_searchpath = list (_CFG_SEARCH_PATHS )
7979 config_section_schemas = [ConfigSchema .Default , ConfigSchema .Profile ]
80+ config_warning_issued = False
8081
8182 @classmethod
8283 def select_config_schema_for (cls , section_name ):
@@ -148,7 +149,20 @@ def has_default_file(cls):
148149 return False
149150
150151 @classmethod
151- def load_config (cls , opts , path = None , profile = None ):
152+ def config_already_warned (cls ):
153+ """
154+ Check if a configuration file warning has been issued.
155+ This is required as configs are gathered at the root of the
156+ command chain as well as for command verbs
157+ """
158+ if cls .config_warning_issued :
159+ return True
160+
161+ cls .config_warning_issued = True
162+ return False
163+
164+ @classmethod
165+ def load_config (cls , opts , path = None , profile = None , no_warn = False ):
152166 """Load a configuration file into an options object."""
153167 if path and os .path .exists (path ):
154168 if os .path .isdir (path ):
@@ -160,9 +174,36 @@ def load_config(cls, opts, path=None, profile=None):
160174 values = config .get ("default" , {})
161175 cls ._load_values_into_opts (opts , values )
162176
163- if profile and profile != "default" :
164- values = config .get ("profile:%s" % profile , {})
165- cls ._load_values_into_opts (opts , values )
177+ warn = not no_warn and not cls .config_already_warned ()
178+
179+ if profile and profile != "default" and warn :
180+ try :
181+ values = config ["profile:%s" % profile ]
182+ cls ._load_values_into_opts (opts , values )
183+ except KeyError :
184+ if warn :
185+ click .secho (
186+ f"Warning: profile { profile } not found in config files { cls .config_files } " ,
187+ fg = "yellow" ,
188+ )
189+
190+ existing_config_paths = {
191+ path : os .path .exists (path ) for path in cls .config_files
192+ }
193+ if not any (existing_config_paths .values ()) and warn :
194+ click .secho (
195+ "Warning: No config files found in search paths. Tried the following:" ,
196+ fg = "yellow" ,
197+ )
198+ for tested_path , exists in existing_config_paths .items ():
199+ if exists :
200+ click .secho (f"{ tested_path } - file exists" , fg = "green" )
201+ else :
202+ click .secho (f"{ tested_path } - file does not exist" , fg = "yellow" )
203+ click .secho (
204+ "You may need to run `cloudsmith login` to authenticate and create a config file." ,
205+ fg = "yellow" ,
206+ )
166207
167208 return values
168209
@@ -206,7 +247,31 @@ class CredentialsReader(ConfigReader):
206247 config_searchpath = list (_CFG_SEARCH_PATHS )
207248 config_section_schemas = [CredentialsSchema .Default , CredentialsSchema .Profile ]
208249
250+ @classmethod
251+ def load_config (cls , opts , path = None , profile = None , no_warn = False ):
252+ """
253+ Load a credentials configuration file into an options object.
254+ We overload the load_config command in CredentialsReader as
255+ credentials files have their own specific default functionality.
256+ """
257+ if path and os .path .exists (path ):
258+ if os .path .isdir (path ):
259+ cls .config_searchpath .insert (0 , path )
260+ else :
261+ cls .config_files .insert (0 , path )
262+
263+ config = cls .read_config ()
264+ values = config .get ("default" , {})
265+ cls ._load_values_into_opts (opts , values )
266+
267+ if profile and profile != "default" :
268+ values = config .get ("profile:%s" % profile , {})
269+ cls ._load_values_into_opts (opts , values )
270+
271+ return values
272+
209273
274+ # pylint: disable=too-many-public-methods
210275class Options :
211276 """Options object that holds config for the application."""
212277
@@ -227,15 +292,15 @@ def get_creds_reader():
227292 """Get the credentials config reader class."""
228293 return CredentialsReader
229294
230- def load_config_file (self , path , profile = None ):
295+ def load_config_file (self , path , profile = None , no_warn = False ):
231296 """Load the standard config file."""
232297 config_cls = self .get_config_reader ()
233- return config_cls .load_config (self , path , profile = profile )
298+ return config_cls .load_config (self , path , profile = profile , no_warn = no_warn )
234299
235- def load_creds_file (self , path , profile = None ):
300+ def load_creds_file (self , path , profile = None , no_warn = False ):
236301 """Load the credentials config file."""
237302 config_cls = self .get_creds_reader ()
238- return config_cls .load_config (self , path , profile = profile )
303+ return config_cls .load_config (self , path , profile = profile , no_warn = no_warn )
239304
240305 @property
241306 def api_config (self ):
@@ -268,6 +333,16 @@ def api_host(self, value):
268333 """Set value for API host."""
269334 self ._set_option ("api_host" , value )
270335
336+ @property
337+ def no_warn (self ):
338+ """Get value for API host."""
339+ return self ._get_option ("no_warn" )
340+
341+ @no_warn .setter
342+ def no_warn (self , value ):
343+ """Set value for API host."""
344+ self ._set_option ("no_warn" , value )
345+
271346 @property
272347 def api_key (self ):
273348 """Get value for API key."""
0 commit comments