1# coding=utf-8
2# -------------------------------------------------------------------------
3# Copyright (c) Microsoft Corporation. All rights reserved.
4# Licensed under the MIT License. See License.txt in the project root for
5# license information.
6# --------------------------------------------------------------------------
7from typing import Mapping
8
9
10def parse_connection_string(conn_str: str, case_sensitive_keys: bool = False) -> Mapping[str, str]:
11 """Parses the connection string into a dict of its component parts, with the option of preserving case
12 of keys, and validates that each key in the connection string has a provided value. If case of keys
13 is not preserved (ie. `case_sensitive_keys=False`), then a dict with LOWERCASE KEYS will be returned.
14
15 :param str conn_str: String with connection details provided by Azure services.
16 :param bool case_sensitive_keys: Indicates whether the casing of the keys will be preserved. When `False`(the
17 default), all keys will be lower-cased. If set to `True`, the original casing of the keys will be preserved.
18 :rtype: Mapping
19 :returns: Dict of connection string key/value pairs.
20 :raises ValueError: if each key in conn_str does not have a corresponding value and
21 for other bad formatting of connection strings - including duplicate
22 args, bad syntax, etc.
23 """
24
25 cs_args = [s.split("=", 1) for s in conn_str.strip().rstrip(";").split(";")]
26 if any(len(tup) != 2 or not all(tup) for tup in cs_args):
27 raise ValueError("Connection string is either blank or malformed.")
28 args_dict = dict(cs_args)
29
30 if len(cs_args) != len(args_dict):
31 raise ValueError("Connection string is either blank or malformed.")
32
33 if not case_sensitive_keys:
34 # if duplicate case insensitive keys are passed in, raise error
35 new_args_dict = {}
36 for key in args_dict.keys(): # pylint: disable=consider-using-dict-items
37 new_key = key.lower()
38 if new_key in new_args_dict:
39 raise ValueError("Duplicate key in connection string: {}".format(new_key))
40 new_args_dict[new_key] = args_dict[key]
41 return new_args_dict
42
43 return args_dict