Coverage for gpkit\varkey.py: 0%

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

87 statements  

1"""Defines the VarKey class""" 

2from .small_classes import Count, qty 

3from .repr_conventions import ReprMixin 

4 

5 

6class VarKey(ReprMixin): # pylint:disable=too-many-instance-attributes 

7 """An object to correspond to each 'variable name'. 

8 

9 Arguments 

10 --------- 

11 name : str, VarKey, or Monomial 

12 Name of this Variable, or object to derive this Variable from. 

13 

14 **descr : 

15 Any additional attributes, which become the descr attribute (a dict). 

16 

17 Returns 

18 ------- 

19 VarKey with the given name and descr. 

20 """ 

21 unique_id = Count().next 

22 subscripts = ("lineage", "idx") 

23 

24 def __init__(self, name=None, **descr): 

25 # NOTE: Python arg handling guarantees 'name' won't appear in descr 

26 self.descr = descr 

27 self.descr["name"] = name or "\\fbox{%s}" % VarKey.unique_id() 

28 unitrepr = self.unitrepr or self.units 

29 if unitrepr in ["", "-", None]: # dimensionless 

30 self.descr["units"] = None 

31 self.descr["unitrepr"] = "-" 

32 else: 

33 self.descr["units"] = qty(unitrepr) 

34 self.descr["unitrepr"] = unitrepr 

35 

36 self.key = self 

37 fullstr = self.str_without({"hiddenlineage", "modelnums", "vec"}) 

38 self.eqstr = fullstr + str(self.lineage) + self.unitrepr 

39 self.hashvalue = hash(self.eqstr) 

40 self.keys = set((self.name, fullstr)) 

41 

42 if "idx" in self.descr: 

43 if "veckey" not in self.descr: 

44 vecdescr = self.descr.copy() 

45 del vecdescr["idx"] 

46 self.veckey = VarKey(**vecdescr) 

47 else: 

48 self.keys.add(self.veckey) 

49 self.keys.add(self.str_without({"idx", "modelnums"})) 

50 

51 def __getstate__(self): 

52 "Stores varkey as its metadata dictionary, removing functions" 

53 state = self.descr.copy() 

54 for key, value in state.items(): 

55 if getattr(value, "__call__", None): 

56 state[key] = "unpickleable function %s" % value 

57 return state 

58 

59 def __setstate__(self, state): 

60 "Restores varkey from its metadata dictionary" 

61 self.__init__(**state) 

62 

63 def str_without(self, excluded=()): # pylint:disable=too-many-branches 

64 "Returns string without certain fields (such as 'lineage')." 

65 name = self.name 

66 if "lineage" not in excluded and self.lineage: 

67 namespace = self.lineagestr("modelnums" not in excluded).split(".") 

68 for ex in excluded: 

69 if ex[0:7] == ":MAGIC:": 

70 to_replace = ex[7:] 

71 if not to_replace: 

72 continue 

73 to_replace = to_replace.split(".") 

74 replaced = 0 

75 for modelname in to_replace: 

76 if not namespace or namespace[0] != modelname: 

77 break 

78 replaced += 1 

79 namespace = namespace[1:] 

80 if len(to_replace) > replaced: 

81 namespace.insert(0, "."*(len(to_replace)-replaced)) 

82 if "hiddenlineage" not in excluded: 

83 necessarylineage = self.necessarylineage 

84 if necessarylineage is None and self.veckey: 

85 necessarylineage = self.veckey.necessarylineage 

86 if necessarylineage is not None: 

87 if necessarylineage > 0: 

88 namespace = namespace[-necessarylineage:] 

89 else: 

90 namespace = None 

91 if namespace: 

92 name = ".".join(namespace) + "." + name 

93 if "idx" not in excluded: 

94 if self.idx: 

95 name += "[%s]" % ",".join(map(str, self.idx)) 

96 elif "vec" not in excluded and self.shape: 

97 name += "[:]" 

98 return name 

99 

100 __repr__ = str_without 

101 

102 # pylint: disable=multiple-statements 

103 def __hash__(self): return self.hashvalue 

104 def __getattr__(self, attr): return self.descr.get(attr, None) 

105 

106 @property 

107 def models(self): 

108 "Returns a tuple of just the names of models in self.lineage" 

109 return list(zip(*self.lineage))[0] 

110 

111 def latex(self, excluded=()): 

112 "Returns latex representation." 

113 name = self.name 

114 if "vec" not in excluded and "idx" not in excluded and self.shape: 

115 name = "\\vec{%s}" % name 

116 if "idx" not in excluded and self.idx: 

117 name = "{%s}_{%s}" % (name, ",".join(map(str, self.idx))) 

118 if "lineage" not in excluded and self.lineage: 

119 name = "{%s}_{%s}" % (name, 

120 self.lineagestr("modelnums" not in excluded)) 

121 return name 

122 

123 def __eq__(self, other): 

124 if not hasattr(other, "descr"): 

125 return False 

126 return self.eqstr == other.eqstr