Coverage for sacred/sacred/settings.py: 97%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

36 statements  

1#!/usr/bin/env python 

2# coding=utf-8 

3 

4import platform 

5from sacred.utils import SacredError 

6import sacred.optional as opt 

7from munch import Munch 

8from packaging import version 

9 

10__all__ = ("SETTINGS", "SettingError") 

11 

12 

13class SettingError(SacredError): 

14 """Error for invalid settings.""" 

15 

16 

17class FrozenKeyMunch(Munch): 

18 __frozen_keys = False 

19 

20 def freeze_keys(self): 

21 if self.__frozen_keys: 

22 return 

23 self.__frozen_keys = True 

24 for v in self.values(): 

25 if isinstance(v, FrozenKeyMunch): 

26 v.freeze_keys() 

27 

28 def _check_can_set(self, key, value): 

29 if not self.__frozen_keys: 

30 return 

31 

32 # Don't allow unknown keys 

33 if key not in self: 

34 raise SettingError( 

35 f"Unknown setting: {key}. Possible keys are: " f"{list(self.keys())}" 

36 ) 

37 

38 # Don't allow setting keys that represent nested settings 

39 if isinstance(self[key], Munch) and not isinstance(value, Munch): 

40 # We don't want to overwrite a munch mapping. This is the easiest 

41 # solution and closest to the original implementation where setting 

42 # a setting with a dict would likely at some point cause an 

43 # exception 

44 raise SettingError( 

45 f"Can't set this setting ({key}) to a non-munch value " 

46 f"{value}, it is a nested setting!" 

47 ) 

48 

49 def __setitem__(self, key, value): 

50 self._check_can_set(key, value) 

51 super().__setitem__(key, value) 

52 

53 def __setattr__(self, key, value): 

54 self._check_can_set(key, value) 

55 super().__setattr__(key, value) 

56 

57 def __deepcopy__(self, memodict=None): 

58 obj = self.__class__.fromDict(self.toDict()) 

59 if self.__frozen_keys: 

60 obj.freeze_keys() 

61 return obj 

62 

63 

64SETTINGS = FrozenKeyMunch.fromDict( 

65 { 

66 "CONFIG": { 

67 # make sure all config keys are compatible with MongoDB 

68 "ENFORCE_KEYS_MONGO_COMPATIBLE": True, 

69 # make sure all config keys are serializable with jsonpickle 

70 # THIS IS IMPORTANT. Only deactivate if you know what you're doing. 

71 "ENFORCE_KEYS_JSONPICKLE_COMPATIBLE": True, 

72 # make sure all config keys are valid python identifiers 

73 "ENFORCE_VALID_PYTHON_IDENTIFIER_KEYS": False, 

74 # make sure all config keys are strings 

75 "ENFORCE_STRING_KEYS": False, 

76 # make sure no config key contains an equals sign 

77 "ENFORCE_KEYS_NO_EQUALS": True, 

78 # if true, all dicts and lists in the configuration of a captured 

79 # function are replaced with a read-only container that raises an 

80 # Exception if it is attempted to write to those containers 

81 "READ_ONLY_CONFIG": True, 

82 # regex patterns to filter out certain IDE or linter directives 

83 # from inline comments in the documentation 

84 "IGNORED_COMMENTS": ["^pylint:", "^noinspection"], 

85 # if true uses the numpy legacy API, i.e. _rnd in captured functions is 

86 # a numpy.random.RandomState rather than numpy.random.Generator. 

87 # numpy.random.RandomState became legacy with numpy v1.19. 

88 "NUMPY_RANDOM_LEGACY_API": version.parse(opt.np.__version__) 

89 < version.parse("1.19") 

90 if opt.has_numpy 

91 else False, 

92 }, 

93 "HOST_INFO": { 

94 # Collect information about GPUs using the nvidia-smi tool 

95 "INCLUDE_GPU_INFO": True, 

96 # List of ENVIRONMENT variables to store in host-info 

97 "CAPTURED_ENV": [], 

98 }, 

99 "COMMAND_LINE": { 

100 # disallow string fallback, if parsing a value from command-line 

101 # failed 

102 "STRICT_PARSING": False, 

103 # show command line options that are disabled (e.g. unmet 

104 # dependencies) 

105 "SHOW_DISABLED_OPTIONS": True, 

106 }, 

107 # configure how stdout/stderr are captured. ['no', 'sys', 'fd'] 

108 "CAPTURE_MODE": "sys" if platform.system() == "Windows" else "fd", 

109 # configure how dependencies are discovered. [none, imported, sys, pkg] 

110 "DISCOVER_DEPENDENCIES": "imported", 

111 # configure how source-files are discovered. [none, imported, sys, dir] 

112 "DISCOVER_SOURCES": "imported", 

113 }, 

114) 

115SETTINGS.freeze_keys()