Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

pie_slice.py 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. """pie_slice/overrides.py.
  2. Overrides Python syntax to conform to the Python3 version as much as possible using a '*' import
  3. Copyright (C) 2013 Timothy Edmund Crosley
  4. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
  5. documentation files (the "Software"), to deal in the Software without restriction, including without limitation
  6. the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
  7. to permit persons to whom the Software is furnished to do so, subject to the following conditions:
  8. The above copyright notice and this permission notice shall be included in all copies or
  9. substantial portions of the Software.
  10. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  11. TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  12. THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  13. CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  14. OTHER DEALINGS IN THE SOFTWARE.
  15. """
  16. from __future__ import absolute_import
  17. import collections
  18. import sys
  19. __version__ = "1.1.0"
  20. PY2 = sys.version_info[0] == 2
  21. PY3 = sys.version_info[0] == 3
  22. VERSION = sys.version_info
  23. native_dict = dict
  24. native_round = round
  25. native_filter = filter
  26. native_map = map
  27. native_zip = zip
  28. native_range = range
  29. native_str = str
  30. native_chr = chr
  31. native_input = input
  32. native_next = next
  33. native_object = object
  34. common = ['native_dict', 'native_round', 'native_filter', 'native_map', 'native_range', 'native_str', 'native_chr',
  35. 'native_input', 'PY2', 'PY3', 'u', 'itemsview', 'valuesview', 'keysview', 'execute', 'integer_types',
  36. 'native_next', 'native_object', 'with_metaclass', 'lru_cache']
  37. def with_metaclass(meta, *bases):
  38. """Enables use of meta classes across Python Versions. taken from jinja2/_compat.py.
  39. Use it like this::
  40. class BaseForm(object):
  41. pass
  42. class FormType(type):
  43. pass
  44. class Form(with_metaclass(FormType, BaseForm)):
  45. pass
  46. """
  47. class metaclass(meta):
  48. __call__ = type.__call__
  49. __init__ = type.__init__
  50. def __new__(cls, name, this_bases, d):
  51. if this_bases is None:
  52. return type.__new__(cls, name, (), d)
  53. return meta(name, bases, d)
  54. return metaclass('temporary_class', None, {})
  55. def unmodified_isinstance(*bases):
  56. """When called in the form
  57. MyOverrideClass(unmodified_isinstance(BuiltInClass))
  58. it allows calls against passed in built in instances to pass even if there not a subclass
  59. """
  60. class UnmodifiedIsInstance(type):
  61. @classmethod
  62. def __instancecheck__(cls, instance):
  63. if cls.__name__ in (str(base.__name__) for base in bases):
  64. return isinstance(instance, bases)
  65. return type.__instancecheck__(cls, instance)
  66. return with_metaclass(UnmodifiedIsInstance, *bases)
  67. if PY3:
  68. import urllib
  69. import builtins
  70. from urllib import parse
  71. input = input
  72. integer_types = (int, )
  73. def u(string):
  74. return string
  75. def itemsview(collection):
  76. return collection.items()
  77. def valuesview(collection):
  78. return collection.values()
  79. def keysview(collection):
  80. return collection.keys()
  81. urllib.quote = parse.quote
  82. urllib.quote_plus = parse.quote_plus
  83. urllib.unquote = parse.unquote
  84. urllib.unquote_plus = parse.unquote_plus
  85. urllib.urlencode = parse.urlencode
  86. execute = getattr(builtins, 'exec')
  87. if VERSION[1] < 2:
  88. def callable(entity):
  89. return hasattr(entity, '__call__')
  90. common.append('callable')
  91. __all__ = common + ['urllib']
  92. else:
  93. from itertools import ifilter as filter # noqa: F401
  94. from itertools import imap as map # noqa: F401
  95. from itertools import izip as zip # noqa: F401
  96. from decimal import Decimal, ROUND_HALF_EVEN
  97. str = unicode
  98. chr = unichr
  99. input = raw_input
  100. range = xrange
  101. integer_types = (int, long)
  102. import sys
  103. stdout = sys.stdout
  104. stderr = sys.stderr
  105. reload(sys)
  106. sys.stdout = stdout
  107. sys.stderr = stderr
  108. sys.setdefaultencoding('utf-8')
  109. def _create_not_allowed(name):
  110. def _not_allow(*args, **kwargs):
  111. raise NameError("name '{0}' is not defined".format(name))
  112. _not_allow.__name__ = name
  113. return _not_allow
  114. for removed in ('apply', 'cmp', 'coerce', 'execfile', 'raw_input', 'unpacks'):
  115. globals()[removed] = _create_not_allowed(removed)
  116. def u(s):
  117. if isinstance(s, unicode):
  118. return s
  119. else:
  120. return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape")
  121. def execute(_code_, _globs_=None, _locs_=None):
  122. """Execute code in a namespace."""
  123. if _globs_ is None:
  124. frame = sys._getframe(1)
  125. _globs_ = frame.f_globals
  126. if _locs_ is None:
  127. _locs_ = frame.f_locals
  128. del frame
  129. elif _locs_ is None:
  130. _locs_ = _globs_
  131. exec("""exec _code_ in _globs_, _locs_""")
  132. class _dict_view_base(object):
  133. __slots__ = ('_dictionary', )
  134. def __init__(self, dictionary):
  135. self._dictionary = dictionary
  136. def __repr__(self):
  137. return "{0}({1})".format(self.__class__.__name__, str(list(self.__iter__())))
  138. def __unicode__(self):
  139. return str(self.__repr__())
  140. def __str__(self):
  141. return str(self.__unicode__())
  142. class dict_keys(_dict_view_base):
  143. __slots__ = ()
  144. def __iter__(self):
  145. return self._dictionary.iterkeys()
  146. class dict_values(_dict_view_base):
  147. __slots__ = ()
  148. def __iter__(self):
  149. return self._dictionary.itervalues()
  150. class dict_items(_dict_view_base):
  151. __slots__ = ()
  152. def __iter__(self):
  153. return self._dictionary.iteritems()
  154. def itemsview(collection):
  155. return dict_items(collection)
  156. def valuesview(collection):
  157. return dict_values(collection)
  158. def keysview(collection):
  159. return dict_keys(collection)
  160. class dict(unmodified_isinstance(native_dict)):
  161. def has_key(self, *args, **kwargs):
  162. return AttributeError("'dict' object has no attribute 'has_key'")
  163. def items(self):
  164. return dict_items(self)
  165. def keys(self):
  166. return dict_keys(self)
  167. def values(self):
  168. return dict_values(self)
  169. def round(number, ndigits=None):
  170. return_int = False
  171. if ndigits is None:
  172. return_int = True
  173. ndigits = 0
  174. if hasattr(number, '__round__'):
  175. return number.__round__(ndigits)
  176. if ndigits < 0:
  177. raise NotImplementedError('negative ndigits not supported yet')
  178. exponent = Decimal('10') ** (-ndigits)
  179. d = Decimal.from_float(number).quantize(exponent,
  180. rounding=ROUND_HALF_EVEN)
  181. if return_int:
  182. return int(d)
  183. else:
  184. return float(d)
  185. def next(iterator):
  186. try:
  187. iterator.__next__()
  188. except Exception:
  189. native_next(iterator)
  190. class FixStr(type):
  191. def __new__(cls, name, bases, dct):
  192. if '__str__' in dct:
  193. dct['__unicode__'] = dct['__str__']
  194. dct['__str__'] = lambda self: self.__unicode__().encode('utf-8')
  195. return type.__new__(cls, name, bases, dct)
  196. def __instancecheck__(cls, instance):
  197. if cls.__name__ == "object":
  198. return isinstance(instance, native_object)
  199. return type.__instancecheck__(cls, instance)
  200. class object(with_metaclass(FixStr, object)):
  201. pass
  202. __all__ = common + ['round', 'dict', 'apply', 'cmp', 'coerce', 'execfile', 'raw_input', 'unpacks', 'str', 'chr',
  203. 'input', 'range', 'filter', 'map', 'zip', 'object']
  204. if sys.version_info < (3, 2):
  205. try:
  206. from threading import Lock
  207. except ImportError:
  208. from dummy_threading import Lock
  209. from functools import wraps
  210. _CacheInfo = collections.namedtuple("CacheInfo", "hits misses maxsize currsize")
  211. def lru_cache(maxsize=100):
  212. """Least-recently-used cache decorator.
  213. Taking from: https://github.com/MiCHiLU/python-functools32/blob/master/functools32/functools32.py
  214. with slight modifications.
  215. If *maxsize* is set to None, the LRU features are disabled and the cache
  216. can grow without bound.
  217. Arguments to the cached function must be hashable.
  218. View the cache statistics named tuple (hits, misses, maxsize, currsize) with
  219. f.cache_info(). Clear the cache and statistics with f.cache_clear().
  220. Access the underlying function with f.__wrapped__.
  221. See: https://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used
  222. """
  223. def decorating_function(user_function, tuple=tuple, sorted=sorted, len=len, KeyError=KeyError):
  224. hits, misses = [0], [0]
  225. kwd_mark = (object(),) # separates positional and keyword args
  226. lock = Lock()
  227. if maxsize is None:
  228. CACHE = {}
  229. @wraps(user_function)
  230. def wrapper(*args, **kwds):
  231. key = args
  232. if kwds:
  233. key += kwd_mark + tuple(sorted(kwds.items()))
  234. try:
  235. result = CACHE[key]
  236. hits[0] += 1
  237. return result
  238. except KeyError:
  239. pass
  240. result = user_function(*args, **kwds)
  241. CACHE[key] = result
  242. misses[0] += 1
  243. return result
  244. else:
  245. CACHE = collections.OrderedDict()
  246. @wraps(user_function)
  247. def wrapper(*args, **kwds):
  248. key = args
  249. if kwds:
  250. key += kwd_mark + tuple(sorted(kwds.items()))
  251. with lock:
  252. cached = CACHE.get(key, None)
  253. if cached:
  254. del CACHE[key]
  255. CACHE[key] = cached
  256. hits[0] += 1
  257. return cached
  258. result = user_function(*args, **kwds)
  259. with lock:
  260. CACHE[key] = result # record recent use of this key
  261. misses[0] += 1
  262. while len(CACHE) > maxsize:
  263. CACHE.popitem(last=False)
  264. return result
  265. def cache_info():
  266. """Report CACHE statistics."""
  267. with lock:
  268. return _CacheInfo(hits[0], misses[0], maxsize, len(CACHE))
  269. def cache_clear():
  270. """Clear the CACHE and CACHE statistics."""
  271. with lock:
  272. CACHE.clear()
  273. hits[0] = misses[0] = 0
  274. wrapper.cache_info = cache_info
  275. wrapper.cache_clear = cache_clear
  276. return wrapper
  277. return decorating_function
  278. else:
  279. from functools import lru_cache # noqa: F401
  280. class OrderedSet(collections.MutableSet):
  281. def __init__(self, iterable=None):
  282. self.end = end = []
  283. end += [None, end, end]
  284. self.map = {}
  285. if iterable is not None:
  286. self |= iterable
  287. def __len__(self):
  288. return len(self.map)
  289. def __contains__(self, key):
  290. return key in self.map
  291. def add(self, key):
  292. if key not in self.map:
  293. end = self.end
  294. curr = end[1]
  295. curr[2] = end[1] = self.map[key] = [key, curr, end]
  296. def discard(self, key):
  297. if key in self.map:
  298. key, prev, next = self.map.pop(key)
  299. prev[2] = next
  300. next[1] = prev
  301. def __iter__(self):
  302. end = self.end
  303. curr = end[2]
  304. while curr is not end:
  305. yield curr[0]
  306. curr = curr[2]
  307. def __reversed__(self):
  308. end = self.end
  309. curr = end[1]
  310. while curr is not end:
  311. yield curr[0]
  312. curr = curr[1]
  313. def pop(self, last=True):
  314. if not self:
  315. raise KeyError('set is empty')
  316. key = self.end[1][0] if last else self.end[2][0]
  317. self.discard(key)
  318. return key
  319. def __repr__(self):
  320. if not self:
  321. return '%s()' % (self.__class__.__name__,)
  322. return '%s(%r)' % (self.__class__.__name__, list(self))
  323. def __eq__(self, other):
  324. if isinstance(other, OrderedSet):
  325. return len(self) == len(other) and list(self) == list(other)
  326. return set(self) == set(other)
  327. def update(self, other):
  328. for item in other:
  329. self.add(item)