B ㊇cÏ&ã@snddlZddlZddlZddlZddlZddlZdd„Zdd„Zdd„Z dd d „Z d d „Z d d„Z dd„Z dS)éNc Gstg}g}xN|D]F}y t|ƒ}Wntjjk r8wYnX| | d¡¡| |¡qWt|ƒ}t|ƒ}||d<|S)a Load and combine multiple INI configs with profiles. This function will take a list of filesnames and return a single dictionary that represents the merging of the loaded config files. If any of the provided filenames does not exist, then that file is ignored. It is therefore ok to provide a list of filenames, some of which may not exist. Configuration files are **not** deep merged, only the top level keys are merged. The filenames should be passed in order of precedence. The first config file has precedence over the second config file, which has precedence over the third config file, etc. The only exception to this is that the "profiles" key is merged to combine profiles from multiple config files into a single profiles mapping. However, if a profile is defined in multiple config files, then the config file with the highest precedence is used. Profile values themselves are not merged. For example:: FileA FileB FileC [foo] [foo] [bar] a=1 a=2 a=3 b=2 [bar] [baz] [profile a] a=2 a=3 region=e [profile a] [profile b] [profile c] region=c region=d region=f The final result of ``multi_file_load_config(FileA, FileB, FileC)`` would be:: {"foo": {"a": 1}, "bar": {"a": 2}, "baz": {"a": 3}, "profiles": {"a": {"region": "c"}}, {"b": {"region": d"}}, {"c": {"region": "f"}}} Note that the "foo" key comes from A, even though it's defined in both FileA and FileB. Because "foo" was defined in FileA first, then the values for "foo" from FileA are used and the values for "foo" from FileB are ignored. Also note where the profiles originate from. Profile "a" comes FileA, profile "b" comes from FileB, and profile "c" comes from FileC. Úprofiles)Ú load_configÚbotocoreÚ exceptionsÚConfigNotFoundÚappendÚpopÚ_merge_list_of_dicts)Ú filenamesZconfigsrÚfilenameZloadedZ merged_configZmerged_profiles©r úp/private/var/folders/8c/hx9_v10d5x38qmnzt13b7b8j1k3n5b/T/pip-target-x6xd5gna/lib/python/botocore/configloader.pyÚmulti_file_load_configs0  rcCs<i}x2|D]*}x$| ¡D]\}}||kr|||<qWq W|S)N)Úitems)Z list_of_dictsZ merged_dictsZ single_dictÚkeyÚvaluer r r r Vs  r cCst|ƒ}t|ƒS)aParse a INI config with profiles. This will parse an INI config file and map top level profiles into a top level "profile" key. If you want to parse an INI file and map all section names to top level keys, use ``raw_config_parse`` instead. )Úraw_config_parseÚbuild_profile_map)Úconfig_filenameÚparsedr r r r_s rTc CsDi}|}|dk r@tj |¡}tj |¡}tj |¡sHtjjt|ƒd‚t   ¡}y|  |g¡Wn>t j t fk rž}ztjjt|ƒ|dd‚Wdd}~XYn¢Xxž| ¡D]’}i||<x„| |¡D]v}| ||¡}|r,| d¡r,y t|ƒ}Wn:tk r*}ztjjt|ƒ|dd‚Wdd}~XYnX||||<qÂWqªW|S)aÕReturns the parsed INI config contents. Each section name is a top level key. :param config_filename: The name of the INI file to parse :param parse_subsections: If True, parse indented blocks as subsections that represent their own configuration dictionary. For example, if the config file had the contents:: s3 = signature_version = s3v4 addressing_style = path The resulting ``raw_config_parse`` would be:: {'s3': {'signature_version': 's3v4', 'addressing_style': 'path'}} If False, do not try to parse subsections and return the indented block as its literal value:: {'s3': ' signature_version = s3v4 addressing_style = path'} :returns: A dict with keys for each profile found in the config file and the value of each key being a dict containing name value pairs found in that profile. :raises: ConfigNotFound, ConfigParseError N)Úpath)rÚerrorÚ )ÚosrÚ expandvarsÚ expanduserÚisfilerrrÚ _unicode_pathÚ configparserÚRawConfigParserÚreadÚErrorÚUnicodeDecodeErrorZConfigParseErrorÚsectionsÚoptionsÚgetÚ startswithÚ _parse_nestedÚ ValueError) rZparse_subsectionsÚconfigrÚcpÚeÚsectionÚoptionÚ config_valuer r r rms6        rcCs2t|tƒr|St ¡}|dkr&t ¡}| |d¡S)NÚreplace)Ú isinstanceÚstrÚsysÚgetfilesystemencodingÚgetdefaultencodingÚdecode)rZfilesystem_encodingr r r r¬s  rcCsHi}x>| ¡D]2}| ¡}|s q| dd¡\}}| ¡|| ¡<qW|S)Nú=é)Ú splitlinesÚstripÚsplit)r.rÚlinerrr r r r'·sr'c Csît |¡}i}i}i}xÂ| ¡D]¶\}}| d¡rryt |¡}Wntk rVw YnXt|ƒdkrÖ|||d<q | d¡r¼yt |¡}Wntk r w YnXt|ƒdkrÖ|||d<q |dkrÎ|||<q |||<q W||d<||d<|S)a÷Convert the parsed INI config into a profile map. The config file format requires that every profile except the default to be prepended with "profile", e.g.:: [profile test] aws_... = foo aws_... = bar [profile bar] aws_... = foo aws_... = bar # This is *not* a profile [preview] otherstuff = 1 # Neither is this [foobar] morestuff = 2 The build_profile_map will take a parsed INI config file where each top level key represents a section name, and convert into a format where all the profiles are under a single top level "profiles" key, and each key in the sub dictionary is a profile name. For example, the above config file would be converted from:: {"profile test": {"aws_...": "foo", "aws...": "bar"}, "profile bar": {"aws...": "foo", "aws...": "bar"}, "preview": {"otherstuff": ...}, "foobar": {"morestuff": ...}, } into:: {"profiles": {"test": {"aws_...": "foo", "aws...": "bar"}, "bar": {"aws...": "foo", "aws...": "bar"}, "preview": {"otherstuff": ...}, "foobar": {"morestuff": ...}, } If there are no profiles in the provided parsed INI contents, then an empty dict will be the value associated with the ``profiles`` key. .. note:: This will not mutate the passed in parsed_ini_config. Instead it will make a deepcopy and return that value. Zprofileér7z sso-sessionÚdefaultrÚ sso_sessions)ÚcopyÚdeepcopyrr&Úshlexr:r(Úlen)Zparsed_ini_configZ parsed_configrr>Z final_configrÚvaluesÚpartsr r r rËs23       r)T)rr?rrAr2Zbotocore.exceptionsrrr rrrr'rr r r r Ús?  ?