123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- # -*- coding: utf-8 -*-
- #!/usr/bin/env python
- import types
- class Node:
- pass
- from redis import Redis
- class NodeVisitor:
- def visit(self, node):
- stack = [ node ]
- last_result = None
- while stack:
- try:
- last = stack[-1]
- if isinstance(last, types.GeneratorType):
- stack.append(last.send(last_result))
- last_result = None
- elif isinstance(last, Node):
- stack.append(self._visit(stack.pop()))
- else:
- last_result = stack.pop()
- except StopIteration:
- stack.pop()
- return last_result
- def _visit(self, node):
- methname = 'visit_' + type(node).__name__
- meth = getattr(self, methname, None)
- if meth is None:
- meth = self.generic_visit
- return meth(node)
- def generic_visit(self, node):
- raise RuntimeError('No {} method'.format('visit_' + type(node).__name__))
- # Base class. Uses a descriptor to set a value
- class Descriptor(object):
- def __init__(self, name=None, **options):
- self.name = name
- for key, value in options.items():
- setattr(self, key, value)
- def __set__(self, instance, value):
- instance.__dict__[self.name] = value
- # Descriptor for enforcing types
- class Typed(Descriptor):
- expected_type = type(None)
- def __set__(self, instance, value):
- if not isinstance(value, self.expected_type):
- raise TypeError('expected ' + str(self.expected_type))
- super(Typed, self).__set__(instance, value)
- # Descriptor for enforcing values
- class Unsigned(Descriptor):
- def __set__(self, instance, value):
- if value < 0:
- raise ValueError('Expected >= 0')
- super(Unsigned, self).__set__(instance, value)
- class MaxSized(Descriptor):
- def __init__(self, name=None, **options):
- if 'size' not in options:
- raise TypeError('missing size option')
- super(MaxSized, self).__init__(name, **options)
- # noinspection PyUnresolvedReferences
- def __set__(self, instance, value):
- if len(value) >= self.size:
- raise ValueError('size must be < ' + str(self.size))
- super(MaxSized, self).__set__(instance, value)
- # Class decorator to apply constraints
- def check_attributes(**kwargs):
- def decorate(cls):
- for key, value in kwargs.items():
- if isinstance(value, Descriptor):
- value.name = key
- setattr(cls, key, value)
- else:
- setattr(cls, key, value(key))
- return cls
- return decorate
- class LazyRedisConnection:
- builder = Redis
- def __init__(self, host, port, db=0):
- self.host = host
- self.port = port
- self.db = db
- self.client = None
- def __enter__(self):
- self.client = self.builder(host=self.host, port=self.port, db=self.db)
- return self.client
- def __exit__(self, exc_ty, exc_val, tb):
- self.client.close()
- class BaseVisitor(object):
- def entry(self, node):
- return type(node).__name__
- def visit(self, node):
- methname = 'visit_' + self.entry(node)
- meth = getattr(self, methname, None)
- if meth is None:
- meth = self.generic_visit
- return meth(node)
- def generic_visit(self, node):
- raise RuntimeError('No {} method'.format('visit_' + type(node).__name__))
|