Coverage for gpkit/globals.py: 100%
51 statements
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-05 22:09 -0500
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-05 22:09 -0500
1"global mutable variables"
2import os
3from collections import defaultdict
4from . import build
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.
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.
42 Thanks! :)
43""")
44 settings_["default_solver"] = settings_["installed_solvers"][0]
45 return settings_
48settings = load_settings()
51class SignomialsEnabledMeta(type):
52 "Metaclass to implement falsiness for SignomialsEnabled"
53 def __bool__(cls):
54 return cls._true
56class SignomialsEnabled(metaclass=SignomialsEnabledMeta):
57 """Class to put up and tear down signomial support in an instance of GPkit.
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
75class Vectorize:
76 """Creates an environment in which all variables are
77 exended in an additional dimension.
78 """
79 vectorization = () # the current vectorization shape
81 def __init__(self, dimension_length):
82 self.dimension_length = dimension_length
84 def __enter__(self):
85 "Enters a vectorized environment."
86 Vectorize.vectorization = (self.dimension_length,) + self.vectorization
88 def __exit__(self, type_, val, traceback):
89 "Leaves a vectorized environment."
90 Vectorize.vectorization = self.vectorization[1:]
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
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]
107 def __init__(self, name):
108 self.name = name
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]
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