Coverage for gpkit/globals.py: 100%

51 statements  

« prev     ^ index     » next       coverage.py v7.4.0, created at 2024-01-07 22:56 -0500

1"global mutable variables" 

2import os 

3from collections import defaultdict 

4from . import build 

5 

6 

7def load_settings(path=None, trybuild=True): 

8 "Load the settings file at SETTINGS_PATH; return settings dict" 

9 if path is None: 

10 path = os.sep.join([os.path.dirname(__file__), "env", "settings"]) 

11 try: # if the settings file already exists, read it 

12 with open(path, encoding="UTF-8") as settingsfile: 

13 lines = [line[:-1].split(" : ") for line in settingsfile 

14 if len(line.split(" : ")) == 2] 

15 settings_ = {name: value.split(", ") for name, value in lines} 

16 for name, value in settings_.items(): 

17 # flatten 1-element lists unless they're the solver list 

18 if len(value) == 1 and name != "installed_solvers": 

19 settings_[name], = value 

20 except IOError: # pragma: no cover 

21 settings_ = {"installed_solvers": [""]} 

22 if settings_["installed_solvers"] == [""] and trybuild: # pragma: no cover 

23 print("Found no installed solvers, beginning a build.") 

24 build() 

25 settings_ = load_settings(path, trybuild=False) 

26 if settings_["installed_solvers"] != [""]: 

27 settings_["just built!"] = True 

28 else: 

29 print(""" 

30============= 

31Build failed! :( 

32============= 

33You may need to install a solver and then `import gpkit` again; 

34see https://gpkit.readthedocs.io/en/latest/installation.html 

35for troubleshooting details. 

36 

37But before you go, please post the output above 

38(starting from "Found no installed solvers, beginning a build.") 

39to gpkit@mit.edu or https://github.com/convexengineering/gpkit/issues/new 

40so we can prevent others from having to see this message. 

41 

42 Thanks! :) 

43""") 

44 settings_["default_solver"] = settings_["installed_solvers"][0] 

45 return settings_ 

46 

47 

48settings = load_settings() 

49 

50 

51class SignomialsEnabledMeta(type): 

52 "Metaclass to implement falsiness for SignomialsEnabled" 

53 def __bool__(cls): 

54 return cls._true 

55 

56class SignomialsEnabled(metaclass=SignomialsEnabledMeta): 

57 """Class to put up and tear down signomial support in an instance of GPkit. 

58 

59 Example 

60 ------- 

61 >>> import gpkit 

62 >>> x = gpkit.Variable("x") 

63 >>> y = gpkit.Variable("y", 0.1) 

64 >>> with SignomialsEnabled(): 

65 >>> constraints = [x >= 1-y] 

66 >>> gpkit.Model(x, constraints).localsolve() 

67 """ 

68 _true = False # default signomial permissions 

69 def __enter__(self): 

70 SignomialsEnabled._true = True 

71 def __exit__(self, type_, val, traceback): 

72 SignomialsEnabled._true = False 

73 

74 

75class Vectorize: 

76 """Creates an environment in which all variables are 

77 exended in an additional dimension. 

78 """ 

79 vectorization = () # the current vectorization shape 

80 

81 def __init__(self, dimension_length): 

82 self.dimension_length = dimension_length 

83 

84 def __enter__(self): 

85 "Enters a vectorized environment." 

86 Vectorize.vectorization = (self.dimension_length,) + self.vectorization 

87 

88 def __exit__(self, type_, val, traceback): 

89 "Leaves a vectorized environment." 

90 Vectorize.vectorization = self.vectorization[1:] 

91 

92 

93class NamedVariables: 

94 """Creates an environment in which all variables have 

95 a model name and num appended to their varkeys. 

96 """ 

97 lineage = () # the current model nesting 

98 modelnums = defaultdict(int) # the number of models of each lineage 

99 namedvars = defaultdict(list) # variables created in the current nesting 

100 

101 @classmethod 

102 def reset_modelnumbers(cls): 

103 "Clear all model number counters" 

104 for key in list(cls.modelnums): 

105 del cls.modelnums[key] 

106 

107 def __init__(self, name): 

108 self.name = name 

109 

110 def __enter__(self): 

111 "Enters a named environment." 

112 num = self.modelnums[(self.lineage, self.name)] 

113 self.modelnums[(self.lineage, self.name)] += 1 

114 NamedVariables.lineage += ((self.name, num),) # NOTE: Side effects 

115 return self.lineage, self.namedvars[self.lineage] 

116 

117 def __exit__(self, type_, val, traceback): 

118 "Leaves a named environment." 

119 del self.namedvars[self.lineage] 

120 NamedVariables.lineage = self.lineage[:-1] # NOTE: Side effects