This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
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.

290 lines
7.4 KiB

  1. import sys
  2. from functools import reduce
  3. from ast import literal_eval
  4. from collections import deque
  5. class fzset(frozenset):
  6. def __repr__(self):
  7. return '{%s}' % ', '.join(map(repr, self))
  8. def classify_bool(seq, pred):
  9. true_elems = []
  10. false_elems = []
  11. for elem in seq:
  12. if pred(elem):
  13. true_elems.append(elem)
  14. else:
  15. false_elems.append(elem)
  16. return true_elems, false_elems
  17. def bfs(initial, expand):
  18. open_q = deque(list(initial))
  19. visited = set(open_q)
  20. while open_q:
  21. node = open_q.popleft()
  22. yield node
  23. for next_node in expand(node):
  24. if next_node not in visited:
  25. visited.add(next_node)
  26. open_q.append(next_node)
  27. def _serialize(value, memo):
  28. # if memo and memo.in_types(value):
  29. # return {'__memo__': memo.memoized.get(value)}
  30. if isinstance(value, Serialize):
  31. return value.serialize(memo)
  32. elif isinstance(value, list):
  33. return [_serialize(elem, memo) for elem in value]
  34. elif isinstance(value, frozenset):
  35. return list(value) # TODO reversible?
  36. elif isinstance(value, dict):
  37. return {key:_serialize(elem, memo) for key, elem in value.items()}
  38. return value
  39. ###{standalone
  40. def classify(seq, key=None, value=None):
  41. d = {}
  42. for item in seq:
  43. k = key(item) if (key is not None) else item
  44. v = value(item) if (value is not None) else item
  45. if k in d:
  46. d[k].append(v)
  47. else:
  48. d[k] = [v]
  49. return d
  50. def _deserialize(data, namespace, memo):
  51. if isinstance(data, dict):
  52. if '__type__' in data: # Object
  53. class_ = namespace[data['__type__']]
  54. return class_.deserialize(data, memo)
  55. elif '@' in data:
  56. return memo[data['@']]
  57. return {key:_deserialize(value, namespace, memo) for key, value in data.items()}
  58. elif isinstance(data, list):
  59. return [_deserialize(value, namespace, memo) for value in data]
  60. return data
  61. class Serialize(object):
  62. def memo_serialize(self, types_to_memoize):
  63. memo = SerializeMemoizer(types_to_memoize)
  64. return self.serialize(memo), memo.serialize()
  65. def serialize(self, memo=None):
  66. if memo and memo.in_types(self):
  67. return {'@': memo.memoized.get(self)}
  68. fields = getattr(self, '__serialize_fields__')
  69. res = {f: _serialize(getattr(self, f), memo) for f in fields}
  70. res['__type__'] = type(self).__name__
  71. postprocess = getattr(self, '_serialize', None)
  72. if postprocess:
  73. postprocess(res, memo)
  74. return res
  75. @classmethod
  76. def deserialize(cls, data, memo):
  77. namespace = getattr(cls, '__serialize_namespace__', {})
  78. namespace = {c.__name__:c for c in namespace}
  79. fields = getattr(cls, '__serialize_fields__')
  80. if '@' in data:
  81. return memo[data['@']]
  82. inst = cls.__new__(cls)
  83. for f in fields:
  84. try:
  85. setattr(inst, f, _deserialize(data[f], namespace, memo))
  86. except KeyError as e:
  87. raise KeyError("Cannot find key for class", cls, e)
  88. postprocess = getattr(inst, '_deserialize', None)
  89. if postprocess:
  90. postprocess()
  91. return inst
  92. class SerializeMemoizer(Serialize):
  93. __serialize_fields__ = 'memoized',
  94. def __init__(self, types_to_memoize):
  95. self.types_to_memoize = tuple(types_to_memoize)
  96. self.memoized = Enumerator()
  97. def in_types(self, value):
  98. return isinstance(value, self.types_to_memoize)
  99. def serialize(self):
  100. return _serialize(self.memoized.reversed(), None)
  101. @classmethod
  102. def deserialize(cls, data, namespace, memo):
  103. return _deserialize(data, namespace, memo)
  104. try:
  105. STRING_TYPE = basestring
  106. except NameError: # Python 3
  107. STRING_TYPE = str
  108. import types
  109. from functools import wraps, partial
  110. from contextlib import contextmanager
  111. Str = type(u'')
  112. try:
  113. classtype = types.ClassType # Python2
  114. except AttributeError:
  115. classtype = type # Python3
  116. def smart_decorator(f, create_decorator):
  117. if isinstance(f, types.FunctionType):
  118. return wraps(f)(create_decorator(f, True))
  119. elif isinstance(f, (classtype, type, types.BuiltinFunctionType)):
  120. return wraps(f)(create_decorator(f, False))
  121. elif isinstance(f, types.MethodType):
  122. return wraps(f)(create_decorator(f.__func__, True))
  123. elif isinstance(f, partial):
  124. # wraps does not work for partials in 2.7: https://bugs.python.org/issue3445
  125. return wraps(f.func)(create_decorator(lambda *args, **kw: f(*args[1:], **kw), True))
  126. else:
  127. return create_decorator(f.__func__.__call__, True)
  128. import sys, re
  129. Py36 = (sys.version_info[:2] >= (3, 6))
  130. import sre_parse
  131. import sre_constants
  132. def get_regexp_width(regexp):
  133. try:
  134. return [int(x) for x in sre_parse.parse(regexp).getwidth()]
  135. except sre_constants.error:
  136. raise ValueError(regexp)
  137. ###}
  138. def dedup_list(l):
  139. """Given a list (l) will removing duplicates from the list,
  140. preserving the original order of the list. Assumes that
  141. the list entrie are hashable."""
  142. dedup = set()
  143. return [ x for x in l if not (x in dedup or dedup.add(x))]
  144. try:
  145. from contextlib import suppress # Python 3
  146. except ImportError:
  147. @contextmanager
  148. def suppress(*excs):
  149. '''Catch and dismiss the provided exception
  150. >>> x = 'hello'
  151. >>> with suppress(IndexError):
  152. ... x = x[10]
  153. >>> x
  154. 'hello'
  155. '''
  156. try:
  157. yield
  158. except excs:
  159. pass
  160. try:
  161. compare = cmp
  162. except NameError:
  163. def compare(a, b):
  164. if a == b:
  165. return 0
  166. elif a > b:
  167. return 1
  168. return -1
  169. class Enumerator(Serialize):
  170. def __init__(self):
  171. self.enums = {}
  172. def get(self, item):
  173. if item not in self.enums:
  174. self.enums[item] = len(self.enums)
  175. return self.enums[item]
  176. def __len__(self):
  177. return len(self.enums)
  178. def reversed(self):
  179. r = {v: k for k, v in self.enums.items()}
  180. assert len(r) == len(self.enums)
  181. return r
  182. def eval_escaping(s):
  183. w = ''
  184. i = iter(s)
  185. for n in i:
  186. w += n
  187. if n == '\\':
  188. try:
  189. n2 = next(i)
  190. except StopIteration:
  191. raise ValueError("Literal ended unexpectedly (bad escaping): `%r`" % s)
  192. if n2 == '\\':
  193. w += '\\\\'
  194. elif n2 not in 'uxnftr':
  195. w += '\\'
  196. w += n2
  197. w = w.replace('\\"', '"').replace("'", "\\'")
  198. to_eval = "u'''%s'''" % w
  199. try:
  200. s = literal_eval(to_eval)
  201. except SyntaxError as e:
  202. raise ValueError(s, e)
  203. return s
  204. def combine_alternatives(lists):
  205. """
  206. Accepts a list of alternatives, and enumerates all their possible concatinations.
  207. Examples:
  208. >>> combine_alternatives([range(2), [4,5]])
  209. [[0, 4], [0, 5], [1, 4], [1, 5]]
  210. >>> combine_alternatives(["abc", "xy", '$'])
  211. [['a', 'x', '$'], ['a', 'y', '$'], ['b', 'x', '$'], ['b', 'y', '$'], ['c', 'x', '$'], ['c', 'y', '$']]
  212. >>> combine_alternatives([])
  213. [[]]
  214. """
  215. if not lists:
  216. return [[]]
  217. assert all(l for l in lists), lists
  218. init = [[x] for x in lists[0]]
  219. return reduce(lambda a,b: [i+[j] for i in a for j in b], lists[1:], init)