Coverage for pydaconf/utils/file.py: 71.68%

77 statements  

« prev     ^ index     » next       coverage.py v7.6.11, created at 2025-02-16 17:46 +0000

1import os 

2import sys 

3 

4from pydaconf.utils.exceptions import UnknownFormat 

5 

6 

7def guess_content_format(content: str) -> str | None: 

8 """Guess file format based on the first line. This is much faster for big config files than using the parsers.""" 

9 

10 first_line = next(iter(content.splitlines()), None) 

11 if first_line is None: 11 ↛ 12line 11 didn't jump to line 12 because the condition on line 11 was never true

12 raise UnknownFormat("Config file first line is empty. Unable to identify the format") 

13 

14 if first_line.startswith("{") or (first_line.startswith("[") and "]" in first_line and "=" not in first_line): 

15 return 'json' 

16 

17 elif ":" in first_line and not first_line.startswith("["): 

18 return 'yaml' 

19 

20 elif first_line.startswith("[") and "=" not in first_line: 20 ↛ 21line 20 didn't jump to line 21 because the condition on line 20 was never true

21 return 'toml' 

22 

23 elif "=" in first_line: 23 ↛ 27line 23 didn't jump to line 27 because the condition on line 23 was always true

24 return 'toml' 

25 

26 else: 

27 return None 

28 

29def load_yaml_content(content: str) -> dict: 

30 try: 

31 import yaml 

32 except ImportError as e: 

33 raise ImportError('PyYAML is not installed, run `pip install pydaconf[yaml]`') from e 

34 

35 result: dict | None = yaml.load(content, Loader=yaml.FullLoader) 

36 if result is None: 36 ↛ 37line 36 didn't jump to line 37 because the condition on line 36 was never true

37 raise ValueError("Empty yaml content") 

38 

39 return result 

40 

41 

42def load_json_content(content: str) -> dict: 

43 import json 

44 result: dict | None = json.loads(content) 

45 if result is None: 45 ↛ 46line 45 didn't jump to line 46 because the condition on line 45 was never true

46 raise ValueError("Empty Json content") 

47 

48 return result 

49 

50 

51def load_toml_content(content: str) -> dict: 

52 if sys.version_info < (3, 11): 52 ↛ 53line 52 didn't jump to line 53 because the condition on line 52 was never true

53 try: 

54 import tomli 

55 toml_module = tomli 

56 except ImportError as e: 

57 raise ImportError('Toml is not installed, run `pip install pydaconf[toml]`') from e 

58 else: 

59 import tomllib 

60 toml_module = tomllib 

61 

62 return toml_module.loads(content) 

63 

64def load_config_file(file_path: str) -> dict: 

65 if not os.path.exists(file_path): 65 ↛ 66line 65 didn't jump to line 66 because the condition on line 65 was never true

66 raise FileNotFoundError(f"Configuration file '{file_path}' doesn't exist") 

67 

68 with open(file_path) as f: 

69 content = f.read() 

70 

71 # Guess the file based on extension 

72 _, extension = os.path.splitext(file_path) 

73 if extension.lower() in {'.yaml', '.yml'}: 

74 return load_yaml_content(content) 

75 

76 elif extension.lower() == '.json': 

77 return load_json_content(content) 

78 

79 elif extension.lower() == '.toml': 

80 return load_toml_content(content) 

81 else: 

82 discovered_format = guess_content_format(content) 

83 if discovered_format == 'json': 

84 return load_json_content(content) 

85 elif discovered_format == 'yaml': 

86 return load_yaml_content(content) 

87 elif discovered_format == 'toml': 87 ↛ 90line 87 didn't jump to line 90 because the condition on line 87 was always true

88 return load_toml_content(content) 

89 else: 

90 raise UnknownFormat("Unknown config file format. Valid formats are json, yaml and toml.") 

91 

92 

93def load_from_url(url: str, headers: dict | None = None) -> dict: 

94 try: 

95 import requests 

96 except ImportError as e: 

97 raise ImportError('requests is not installed, run `pip install pydaconf[requests]`') from e 

98 

99 response = requests.get(url, headers=headers) 

100 response.raise_for_status() 

101 content = response.text 

102 discovered_format = guess_content_format(content) 

103 if discovered_format == 'json': 103 ↛ 104line 103 didn't jump to line 104 because the condition on line 103 was never true

104 return load_json_content(content) 

105 elif discovered_format == 'yaml': 105 ↛ 107line 105 didn't jump to line 107 because the condition on line 105 was always true

106 return load_yaml_content(content) 

107 elif discovered_format == 'toml': 

108 return load_toml_content(content) 

109 else: 

110 raise UnknownFormat("Unknown config file format") 

111 

112