Advertisement
Tyler_Elric

Untitled

Nov 14th, 2012
124
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.81 KB | None | 0 0
  1. # ===========================================================#
  2. # Project Management System. #
  3. # Written by Tyler Beaver, 2012. #
  4. # Feel free to use, but don't remove my name please? :) #
  5. # ===========================================================#
  6.  
  7. import os,json,copy
  8. from time import time # For unix time-stamp. Potential problem for threading?
  9.  
  10. class Cache:
  11. objects = {}#Share objects!
  12. def __init__(self,load): self.loader = load
  13. @staticmethod
  14. def needsUpdate(fn):
  15. if fn not in Cache.objects:
  16. return True
  17. if os.path.getmtime(fn) > Cache.objects[fn][1]:
  18. return True
  19. return False
  20. @staticmethod
  21. def update(fn,ent):
  22. if fn in Cache.objects:
  23. Cache.objects[fn][0] = ent
  24. Cache.objects[fn][1] = time()
  25. def load(self,fn):
  26. if Cache.needsUpdate(fn):
  27. o,m = self.loader(fn),os.path.getmtime(fn)
  28. Cache.objects[fn] = (o,m)
  29. return o
  30. return Cache.objects[fn][0]
  31.  
  32. class JSONAdapter:
  33. extension=".json"
  34. @staticmethod
  35. def save(dat,fn):json.dump(dat,open(fn,'w'))
  36. @staticmethod
  37. def load(fn):return json.load(open(fn))
  38.  
  39. class DataStore:
  40. @staticmethod
  41. def base(et):
  42. return os.path.join(os.environ.get("FMDataStore",os.getcwd()),et.__name__)
  43. @staticmethod
  44. def getKeys(et):
  45. for fn in os.listdir(DataStore.base(et)):
  46. yield DataStore.getKey(fn)
  47. @staticmethod
  48. def store(adapter,entity):
  49. fn = os.path.join(DataStore.base(type(entity)),entity.key+adapter.extension)
  50. Cache.update(fn,entity)
  51. adapter.save(entity.dat,fn)
  52. @staticmethod
  53. def connect(et,*a,**b):
  54. c = DataStore.activeConnections.get(et,None)
  55. if c is None:
  56. c = DataStore.Connection(et,*a,**b)
  57. DataStore.activeConnections[et] = c
  58. return c
  59. @staticmethod
  60. def getKey(fn):
  61. s,e=os.path.sep,os.extsep
  62. a,b=fn.rfind(s),fn.rfind(e)
  63. if a<0 and b<0:return fn[:]
  64. elif a<0:return fn[:b]
  65. elif b<0:return fn[a+len(s):]
  66. else:return fn[a+len(s):b]
  67.  
  68. class MetaEntity(type):
  69. def __init__(self,*args):
  70. self.cache = Cache(self.fromData)
  71. d=DataStore.base(self)
  72. if not os.path.exists(d):
  73. os.makedirs(d)
  74. print("Constructing type:",self.__name__)
  75. return super(MetaEntity,self).__init__(*args)
  76. def __iter__(self):
  77. for key in DataStore.getKeys(self):
  78. yield self.fetch(key)
  79. def fromData(self,fn):
  80. return self(key=DataStore.getKey(fn),data=self.adapter.load(fn))
  81. def fetch(self,key):
  82. return self.cache.load(os.path.join(DataStore.base(self),key+self.adapter.extension))
  83. def load(self,k):return self.fetch(k)
  84.  
  85. class ReferenceListInterface(list):
  86. def __init__(self,original,rType):
  87. self.o,self.et = original,rType
  88. list.__init__(self,original)
  89. def __getitem__(self,k):
  90. if isinstance(k,slice):
  91. return [self.et.load(ent) for ent in self.o[k]]
  92. return self.et.load(self.o[k])
  93. def __setitem__(self,k,val):
  94. if isinstance(k,slice):
  95. for i in range(0,len(val)):
  96. val[i] = val[i].key if isinstance(val[i],Entity) else val[i]
  97. else:val = val.key if isinstance(val,Entity) else val
  98. self.o.__setitem__(k,val)
  99. def __iter__(self):
  100. for k in self.o:yield self.et.load(k)
  101.  
  102. class Entity(metaclass=MetaEntity):
  103. foreignKeys = {}
  104. foreignLists = {}
  105. template = {}
  106. adapter = JSONAdapter
  107. def __init__(self,key=int(time()),data=None):
  108. self.key = str(key)
  109. self.dat = copy.copy(self.template)
  110. if data:self.update(data)
  111. def save(self):DataStore.store(self.adapter,self)
  112. def update(self,o):
  113. if o:
  114. self.dat.update(o)
  115. self.save()
  116. def delete(self):DataStore.delete(self)
  117. def __getattr__(self,attr):
  118. if attr in self.dat:
  119. v=self.dat[attr]
  120. if attr in self.foreignKeys:
  121. if v is not None:
  122. return self.foreignKeys[attr].load(v)
  123. elif attr in self.foreignLists:
  124. if v is not None:
  125. return ReferenceListInterface(v,self.foreignLists[attr])
  126. return v
  127. t="{} entity has no attribute '{}'"
  128. raise AttributeError(t.format(type(self).__name__, attr))
  129.  
  130. class Query:
  131.  
  132. def __init__(self,et,*filters):
  133. self.entities = et
  134. self.filters = list(filters)
  135.  
  136. def fetchAll(self):return [r for r in self]
  137.  
  138. def __iter__(self):
  139. for entity in self.entities:
  140. if all(filter(entity) for filter in self.filters):
  141. yield entity
  142.  
  143. if __name__ == "__main__":
  144.  
  145. import difflib
  146.  
  147. class Location(Entity):
  148. template={'name':"Red Robins"}
  149.  
  150. class Person(Entity):
  151. foreignLists = {
  152. 'location':Location
  153. }
  154. template={
  155. 'name':"",
  156. 'age':0,
  157. 'location':[]
  158. }
  159.  
  160. while "yes" in input("Create a new person? >"):
  161. name = input("Name> ")
  162. age = input("Age> ")
  163. location = input("Location [ or 'no']> ")
  164. location = location if location.lower()!='no' else None
  165. if location:
  166. nameCompare = difflib.SequenceMatcher(b=location)
  167. def similarLocation(loc):
  168. if loc.key==location:return True
  169. nameCompare.set_seq1(loc.name or "???")
  170. return nameCompare.ratio() >= .8#Require a 80% match.
  171. results = Query(Location,similarLocation).fetchAll()
  172. def makeNewLocation(locName):
  173. newLocation = Location(data={"name":locName})
  174. newLocation.save()
  175. return newLocation.key
  176. if len(results)>0:
  177. print("We've found some similar locations that we might think you're referring to.")
  178. for i in range(0,len(results)):
  179. print(i+1,results[i].name)
  180. print("Are you talking about one of these places? Enter the corresponding number, or 0 if your place isn't here.")
  181. i = int(input("> "))
  182. if i<1:location = makeNewLocation(location) if i < 1 else results[i-1].key
  183. else:location=makeNewLocation(location)
  184. Person(data={"name":name,"age":age,"location":[location] if location else []}).save()
  185.  
  186. for person in Person:
  187. name = person.name
  188. age = person.age
  189. location = person.location
  190. intro = "This is {}.".format(name)
  191. b = "He is {}.".format(age) if age else "We don't know how old he is."
  192. c = "He would rather you didn't know where he lives."
  193. if location:
  194. c="He's known to live in "+ str(len(location)) + " places."
  195. for area in location:
  196. c+="\nHe lives in: "+area.name or "???"
  197. print(intro,b,c)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement