Пример #1
0
class LRUCache(object):

    def __init__(self, capacity):
        """
        :type capacity: int
        """
        self.dictionary = OrderedDict()
        self.capacity = capacity

    def get(self, key):
        """
        :rtype: int
        """
        if key in self.dictionary:
            temp = self.dictionary.pop(key)
            self.dictionary[key] = temp
            return temp
        else: return -1

    def set(self, key, value):
        """
        :type key: int
        :type value: int
        :rtype: nothing
        """
        if key in self.dictionary:
            self.dictionary.pop(key)()
            self.dictionary[key] = value
        else:
            if len(self.dictionary) >= self.capacity:
                self.dictionary.popitem(last=False)
                self.dictionary[key] = value
            else:
                self.dictionary[key] = value
Пример #2
0
class MotionMonitor(object):

    def __init__(self):
        self.__logger = logging.getLogger("%s.%s" % (self.__class__.__module__, self.__class__.__name__))

        self.config = motionmonitor.config
        self.bus = EventBus(self)

        self._jobs = OrderedDict()

        self.bus.listen(EVENT_JOB, self.job_handler)

        self.__socket_listener = motionmonitor.socketlistener.SocketListener(self)
        self.__camera_monitor = motionmonitor.cameramonitor.CameraMonitor(self)
        self.__zabbixwriter = motionmonitor.extensions.zabbixwriter.ZabbixWriter(self)
        self.__sqlwriter = motionmonitor.sqlexchanger.SQLWriter(self)

        # This is the sweeper and auditor.
        self.__sweeper = motionmonitor.filemanager.Sweeper(self)
        self.__auditor = motionmonitor.filemanager.Auditor(self)

        self.__json_interface = motionmonitor.jsoninterface.JSONInterface(self, self.__camera_monitor)

        self.__logger.info("Initialised...")

    def job_handler(self, event):
        self.__logger.debug("Handling a job event: {}".format(event))
        job = event.data
        self._jobs[job.id] = job
        while (len(self._jobs) > MAX_JOBQ_SIZE):
            self.__logger.debug("Too many jobs in the queue, popping the oldest")
            self._jobs.popitem(False)
Пример #3
0
class MemoryRegion(CacheRegion):

    NO_VALUE = {}

    def __init__(self, max_keys):
        self.max_keys = max_keys
        self._cache = OrderedDict()

    def get(self, key):
        value = self._cache.get(key, self.NO_VALUE)
        if value is self.NO_VALUE:
            return False, None
        else:
            return True, value

    def set(self, key, value):
        if key in self._cache:
            getLogger('pymor.core.cache.MemoryRegion').warn('Key already present in cache region, ignoring.')
            return
        if len(self._cache) == self.max_keys:
            self._cache.popitem(last=False)
        self._cache[key] = value

    def clear(self):
        self._cache = OrderedDict()
Пример #4
0
class LRUCache(object):

    def __init__(self, capacity):
        """
        :type capacity: int
        """
        self.capacity = capacity
        self.cache = OrderedDict()

    def get(self, key):
        """
        :rtype: int
        """
        try:
            value = self.cache.pop(key)
            self.cache[key] = value
        except:
            value = -1
        return value

    def set(self, key, value):
        """
        :type key: int
        :type value: int
        :rtype: nothing
        """
        try:
            self.cache.pop(key)
        except:
            if len(self.cache) == self.capacity:
                self.cache.popitem(last=False)
        self.cache[key] = value
class _SlideCache(object):
    def __init__(self, cache_size, dz_opts):
        self.cache_size = cache_size
        self.dz_opts = dz_opts
        self._lock = Lock()
        self._cache = OrderedDict()

    def get(self, path):
        with self._lock:
            if path in self._cache:
                # Move to end of LRU
                slide = self._cache.pop(path)
                self._cache[path] = slide
                return slide

        osr = OpenSlide(path)
        slide = DeepZoomGenerator(osr, **self.dz_opts)
        try:
            mpp_x = osr.properties[openslide.PROPERTY_NAME_MPP_X]
            mpp_y = osr.properties[openslide.PROPERTY_NAME_MPP_Y]
            slide.mpp = (float(mpp_x) + float(mpp_y)) / 2
        except (KeyError, ValueError):
            slide.mpp = 0

        with self._lock:
            if path not in self._cache:
                if len(self._cache) == self.cache_size:
                    self._cache.popitem(last=False)
                self._cache[path] = slide
        return slide
Пример #6
0
class AliasGenerator(object):
    def __init__(self, size=200):
        self.MAX_CACHE = size  # TODO: Make configurable
        self.cache = OrderedDict()

    def generate_alias(self, str_value):
        """
        Generate an alias for the given string.
        :param str_value: the given string
        :return: a 24 character alias string
        """
        alias = self.get_alias(str_value)
        if not alias:
            h = hashlib.md5()
            h.update(str_value.encode('utf-8'))
            alias = h.hexdigest()
            self.cache[str_value] = alias
            if len(self.cache) > self.MAX_CACHE:
                self.cache.popitem(last=False)  # FIFO
        else:
            alias = alias
        return alias

    def needs_alias(self, str_value):
        return len(str_value) > MAX_NAME_LEN or len(RE_CLEANSE.findall(str_value)) > 0

    def get_alias(self, str_value):
        return self.cache.get(str_value)

    def clear_aliases(self):
        self.cache.clear()
Пример #7
0
class Cache(object):

    def __init__(self):
        self.reset_caches()

    def reset_caches(self):
        self._category_cache = OrderedDict()
        self._search_cache = OrderedDict()

    def search_cache(self, search):
        old = self._search_cache.pop(search, None)
        if old is None or old[0] <= self.db.last_modified():
            matches = self.search_for_books(search) or []
            self._search_cache[search] = (utcnow(), frozenset(matches))
            if len(self._search_cache) > 50:
                self._search_cache.popitem(last=False)
        else:
            self._search_cache[search] = old
        return self._search_cache[search][1]

    def categories_cache(self, restrict_to=frozenset([])):
        base_restriction = self.search_cache('')
        if restrict_to:
            restrict_to = frozenset(restrict_to).intersection(base_restriction)
        else:
            restrict_to = base_restriction
        old = self._category_cache.pop(frozenset(restrict_to), None)
        if old is None or old[0] <= self.db.last_modified():
            categories = self.db.get_categories(ids=restrict_to)
            self._category_cache[restrict_to] = (utcnow(), categories)
            if len(self._category_cache) > 20:
                self._category_cache.popitem(last=False)
        else:
            self._category_cache[frozenset(restrict_to)] = old
        return self._category_cache[restrict_to][1]
Пример #8
0
def convert_dn_to_cobra(dn):
    # Taken from https://gist.github.com/mtimm/7c238d1c682a684867fd
    from cobra.mit.naming import Dn
    cobra_dn = Dn.fromString(dn)
    parentMoOrDn = "''"
    dn_dict = OrderedDict()
    for rn in cobra_dn.rns:
        rn_str = str(rn)
        dn_dict[rn_str] = {}
        dn_dict[rn_str]['namingVals'] = tuple(rn.namingVals)
        dn_dict[rn_str]['moClassName'] = rn.meta.moClassName
        dn_dict[rn_str]['className'] = rn.meta.className
        dn_dict[rn_str]['parentMoOrDn'] = parentMoOrDn
        parentMoOrDn = rn.meta.moClassName
    code = []
    dn_dict.popitem()
    for arn in dn_dict.items():
        if len(arn[1]['namingVals']) > 0:
            nvals_str = ", '" + ", ".join(map(str, arn[1]['namingVals'])) + "'"
        else:
            nvals_str = ""
        code.append("{0} = {1}({2}{3})".format(arn[1]['moClassName'],
                                         arn[1]['className'],
                                         arn[1]['parentMoOrDn'],
                                         nvals_str))
    return arn[1]['moClassName'], '\n'.join(code)
Пример #9
0
class LRUCache:
    # @param capacity, an integer
    def __init__(self, capacity):
        self.capacity = capacity
        # use OrderedDict to simulate LRU cache
        self.cache = OrderedDict()

    def get(self, key):
        if key in self.cache:
            value = self.cache[key]
            # remove key then add it again
            del self.cache[key]
            self.cache[key] = value
            return value
        else:
            return ""

    def set(self, key, value):
        if key in self.cache:
            # remove key if already in cache
            del self.cache[key]
        self.cache[key] = value
        # pop an item (oldest) if cache is full
        if len(self.cache) > self.capacity:
            self.cache.popitem(False)
Пример #10
0
class Cache(object):
    def __init__(self, size_limit):
        super(Cache, self).__init__()
        self._c = OrderedDict()
        self._size_limit = size_limit

    def insert(self, k, v):
        """
        add a key and value to the front
        """
        self._c[k] = v
        if len(self._c) > self._size_limit:
            self._c.popitem(last=False)

    def exists(self, k):
        return k in self._c

    def touch(self, k):
        """
        bring a key to the front
        """
        v = self._c[k]
        del self._c[k]
        self._c[k] = v

    def get(self, k):
        return self._c[k]
Пример #11
0
class LRUCache(object):

    def __init__(self, capacity):
        """
        :type capacity: int
        """
        self.c = capacity
        self.mapi = OrderedDict()

    def get(self, key):
        """
        :rtype: int
        """
        if key in self.mapi:
            ret = self.mapi.pop(key)
            self.mapi[key] = ret
            return ret
        return -1

    def set(self, key, value):
        """
        :type key: int
        :type value: int
        :rtype: nothing
        """
        if key in self.mapi:
            self.mapi.pop(key)
        self.mapi[key] = value
        if len(self.mapi) > self.c:
            self.mapi.popitem(last=False)
Пример #12
0
class LRUCache:

    # @param capacity, an integer
    def __init__(self, capacity):
        self.capacity = capacity
        self.history = OrderedDict()

    # @return an integer
    def get(self, key):
        if key in self.history:
            self.set(key, self.history[key])
            return self.history[key]
        else:
            return -1

    # @param key, an integer
    # @param value, an integer
    # @return nothing
    def set(self, key, value):
        if key in self.history:
            del self.history[key]
            self.history[key] = value
        else:
            if len(self.history) == self.capacity:
                self.history.popitem(False)
            self.history[key] = value
    def findSubstring(self, s, words):
        sets = OrderedDict()
        dict = defaultdict(int)
        for i in words:
            dict[i] += 1
        width = len(words[0])
        start = 0
        res = []
        for i in range(width, len(s) + 1, width):
            # print i, sets
            tmp = s[i - width : i]
            if tmp in words:
                if tmp in sets:
                    if sets[tmp][1] > dict[tmp]:
                        sets[tmp] = (i, sets[tmp][1] + 1)
                        last = sets.popitem(last=False)
                        while last[0] != tmp:
                            last = sets.popitem(last=False)
                        start = last[1][0]

                else:
                    sets[tmp] = (i, 1)

                if len(sets) == len(words):
                    res.append(start)
                    sets.popitem(last=False)
            else:
                start = i
                sets = OrderedDict()
        return res
Пример #14
0
class LRUCache:

    # @param capacity, an integer
    def __init__(self, capacity):
        self.capacity = capacity
        self.cache = OrderedDict()

    # @return an integer
    def get(self, key):
        if key in self.cache:
            value = self.cache[key]
            del self.cache[key]
            self.cache[key] = value
            return value
        return -1

    # @param key, an integer
    # @param value, an integer
    # @return nothing
    def set(self, key, value):
        if key in self.cache:
            del self.cache[key]
        elif len(self.cache) >= self.capacity:
            self.cache.popitem(False)
        self.cache[key] = value
Пример #15
0
class SIMCache(object):
    def __init__(self, size, ttl):
        self.cache = OrderedDict()
        self.size = size
        self.ttl = ttl

    def set_key(self, key, value, ttl=None):
        """Set a key value in the cache with its expiration time.
        If no ttl (in seconds) is provided self.ttl is taken by default.
        If cache length exceeds CACHE_SIZE when adding a key, the oldest (first inserted) key is removed (FIFO)
        """
        self.cache[key] = (time.time() + (ttl or self.ttl), value)
        if len(self.cache) > self.size:
            self.cache.popitem(last=False)

    def get_key(self, key):
        """Retrieve a key value from the cache.
        Returns None if does not exist or the key expired.
        If the key expired it is removed from the cache.
        """
        content = self.cache.get(key, None)
        if content:
            if content[0] > time.time():
                return content[1]
            else:
                del self.cache[key]
        return None

    def clear_keys(self, ):
        """Remove all cache keys content
        """
        self.cache = OrderedDict()
Пример #16
0
class LRUCache(OrderedDict):
    """
    #实现一个LRU算法的dict,用于记录order_id
    #避免storm平台重发log记录,造成redis数据偏大!
    """
    def __init__(self, capacity):
        """
        @param capacity 字典长度
        """
        self.capacity = capacity
        self.cache = OrderedDict()
    
    def get(self,key):
        if self.cache.has_key(key):
            value = self.cache.pop(key)
            self.cache[key] = value
        else:
            value = None
        return value
    
    def set(self,key,value):
        if self.cache.has_key(key):
            value = self.cache.pop(key)
            self.cache[key] = value
        else:
            if len(self.cache) == self.capacity:
                 #pop出第一个item
                self.cache.popitem(last = False)
                self.cache[key] = value
            else:
                self.cache[key] = value
Пример #17
0
class LRUCache_146(object):
    def __init__(self, capacity):
        """
        :type capacity: int
        """
        self.capacity = capacity
        self.cache = OrderedDict()

    def get(self, key):
        """
        :rtype: int
        """
        if key in self.cache:
            value = self.cache[key]
            del self.cache[key]
            self.cache[key] = value
            return value
        return -1

    def set(self, key, value):
        """
        :type key: int
        :type value: int
        :rtype: nothing
        """
        if key in self.cache:
            del self.cache[key]
        self.cache[key] = value
        if len(self.cache) > self.capacity:
            self.cache.popitem(False)
Пример #18
0
    def dict_to_object(self, dd):
        ''' Instantiates the object using the encoded data
        
        :param dd: dictionary with all memberattributes necessary to construct the object
        :type obj:  OrderedDict
        :returns: encoded object
        :rtype: type of the object

        '''        
        #print("___ OrderedDecoder.dict_to_object(dd) ___")
        #print(dd) 
        d = OrderedDict(dd)
        class_name = d.popitem(last=False)[1]        
        module_name = d.popitem(last=False)[1]
        #print("--- class_name", class_name, "module_name", module_name)
        module = __import__(module_name)
        #print("--- module:", module)
        #class_ is of type 'type'
        class_type = getattr(module, class_name)
        #print("--- type(class_type):" , type(class_type))
        #print("--- class_type:", class_type)
        #print("--- d.items()", d.items())
        args = dict(d.items())
        #print("--- args:", args)
        inst = class_type(args)
        #print("==============\n")
        return inst
Пример #19
0
class BTB:

   def __init__(self,w,n,default):
      self.btb = OrderedDict()
      self.width = w
      self.num_entries = n
      self.default_pkt = default
      print "BTB   : %d entries" % self.num_entries

   def predict(self, pc):
#      print (("pred pc: 0x%x : " % pc) + self.__str__())
      if pc in self.btb:
         return (True, self.btb[pc])
      else:
         return (False, self.default_pkt)

   def update(self, pc, taken, target):
      if (not taken):
         return 
      self.btb[pc] = target
      if len(self.btb) > self.num_entries:
         self.btb.popitem(last=False)

   def __str__(self):
      string = "("
      for pc in self.btb:
         string += ("(0x%x,0x%x.." % (pc, self.btb[pc][0]))
      string += ")"
      return string
Пример #20
0
class LRUDict(MutableMapping):
  """
  A dictionary of limited size where items are evicted in LRU-order

  inspired by http://stackoverflow.com/a/2438926
  """
  def __init__(self, size, *args, **kwargs):
    self.size = size
    self.dict = OrderedDict(*args, **kwargs)
    while len(self) > self.size:
      self.dict.popitem(last=False)

  def __iter__(self):
    return iter(self.dict)

  def __len__(self):
    return len(self.dict)

  def __getitem__(self, key):
    return self.dict[key]

  def __setitem__(self, key, value):
    if key not in self and len(self) == self.size:
      self.dict.popitem(last=False)
    if key in self: # need to delete and reinsert to maintain order
      del self[key]
    self.dict[key] = value

  def __delitem__(self, key):
    del self.dict[key]
Пример #21
0
class LimitedMemoryBackend(BasicInterface, dc.api.CacheBackend):

    def __init__(self, argument_dict):
        '''If argument_dict contains a value for max_kbytes this the total memory limit in kByte that is enforced on the
        internal cache dictionary, otherwise it's set to sys.maxint.
        If argument_dict contains a value for max_keys this maximum amount of cache values kept in the
        internal cache dictionary, otherwise it's set to sys.maxlen.
        If necessary values are deleted from the cache in FIFO order.
        '''
        self.logger.debug('LimitedMemoryBackend args {}'.format(pformat(argument_dict)))
        self._max_keys = argument_dict.get('max_keys', sys.maxsize)
        self._max_bytes = argument_dict.get('max_kbytes', sys.maxint / 1024) * 1024
        self._cache = OrderedDict()

    def get(self, key):
        return self._cache.get(key, dc.api.NO_VALUE)

    def print_limit(self, additional_size=0):
        self.logger.info('LimitedMemoryBackend at {}({}) keys -- {}({}) Byte'
                         .format(len(self._cache), self._max_keys,
                                 memory.getsizeof(self._cache) / 8, self._max_bytes))

    def _enforce_limits(self, new_value):
        additional_size = memory.getsizeof(new_value) / 8
        while len(self._cache) > 0 and not (len(self._cache) <= self._max_keys and
                                            (memory.getsizeof(self._cache) + additional_size) / 8 <= self._max_bytes):
            self.logger.debug('shrinking limited memory cache')
            self._cache.popitem(last=False)

    def set(self, key, value):
        self._enforce_limits(value)
        self._cache[key] = value

    def delete(self, key):
        self._cache.pop(key)
Пример #22
0
def get_treasury_source():
    url = """\
http://data.treasury.gov/feed.svc/DailyTreasuryYieldCurveRateData\
"""
    res = requests.get(url, stream=True)
    stream = iter_to_stream(res.iter_lines())

    elements = ET.iterparse(stream, ("end", "start-ns", "end-ns"))

    namespaces = OrderedDict()
    properties_xpath = [""]

    def updated_namespaces():
        if "" in namespaces and "m" in namespaces:
            properties_xpath[0] = "{%s}content/{%s}properties" % (namespaces[""], namespaces["m"])
        else:
            properties_xpath[0] = ""

    for event, element in elements:
        if event == "end":
            tag = get_localname(element)
            if tag == "entry":
                properties = element.find(properties_xpath[0])
                datum = {get_localname(node): node.text for node in properties.getchildren() if ET.iselement(node)}
                # clear the element after we've dealt with it:
                element.clear()
                yield datum

        elif event == "start-ns":
            namespaces[element[0]] = element[1]
            updated_namespaces()

        elif event == "end-ns":
            namespaces.popitem()
            updated_namespaces()
Пример #23
0
def main():
    events = Queue.Queue(MAX_QUEUE)
    wifithread = wifisniffer.Sniffer(events)
    wifithread.daemon = True
    btthread = btsniffer.Sniffer(events)
    btthread.daemon = True
    webthread = web.HoneyServer()
    webthread.daemon = True

    macaddr.init_cache()
    wifithread.start()
    btthread.start()
    webthread.start()

    seen = OrderedDict()

    try:
        while True:
            interface, mac, when = events.get()
            name = '"%s"'%macaddr.identify(mac)
            notes = "Occurred %s" % time.ctime(when)
            if mac in seen:
                del seen[mac]
            else:
                push.note(interface, name, mac, notes)
            if len(seen) >= MAX_REMEMBER:
                seen.popitem()
            seen[mac] = when
    finally:
        macaddr.save_cache()
    def containsNearbyAlmostDuplicate(self, nums, k, t):
        """
        Two Intervals k & t:
        * Use OrderedDict to remember the index and n/t to shrink the interval to -1, 0, 1.
        * In terms of index difference, since there are i-k and i+k, when scanning from left to right, only consider i-k.

        Alternative algorithms:
        Window + TreeSet (Java) / SortedSet (C++)  # TODO

        :type nums: list[int]
        :rtype: bool
        """
        if k < 1 or t < 0:
            return False

        if t == 0:
            return self.containsNearByDuplicate(nums, k)

        od = OrderedDict()  # keep the window
        for n in nums:
            key = n/t
            for j in (-1, 0, 1):  # (n-t, n, n+t), shrink the interval
                m = od.get(key+j)
                if m is not None and abs(m-n) <= t:  # need to recheck, consider case {1, 7}, t=4
                    return True

            while len(od) >= k:
                od.popitem(False)  # not last, i.e. the first

            od[key] = n

        return False
def overwrite_asdc_authors(string_authors,  asdc_auth):
    """
    takes the authors string and update regarding what the admins decide
    param: take a long string of authors
           authors to underline
    return: string with updated information for asdc author
    """

    repls = {'<b>': '', '</b>': '', '...': ''}
    string_clean = reduce(lambda a, kv: a.replace(*kv), repls.iteritems(), string_authors)
    author_list = string_clean.split(";")
    asdc_auth = OrderedDict((auth.split("_")[0], auth.split("_")[1]) for auth in asdc_auth)
    auth_dict = OrderedDict((auth.split(",")[0].lower().strip().replace(" ", ""), auth) for auth in author_list)


    append_last_element = False
    if next(reversed(auth_dict)).strip() == 'et al.':
        auth_dict.popitem()
        append_last_element = True

    for auth in asdc_auth.keys():
        auth_dict[auth] = '<b> %s </b>' % (asdc_auth[auth].replace("%2C", ", ")).replace("+", " ")


    if append_last_element:
        auth_dict.update({'  et al.': '  et al.'})

    return ';'.join(auth_dict.itervalues())
Пример #26
0
class LastResourceUsed:
    """Class implementing LRU using OrderedDict as base.
    Know isssue: age update is O(n)
    """

    def __init__(self, max_size=100):
        self._max_size = max_size
        self._items = OrderedDict()

    def __setitem__(self, key, value):
        if len(self) == self._max_size:
            self._items.popitem(last=False)
        self._items[key] = value

    def __len__(self):
        return len(self._items)

    def __getitem__(self, key):
        try:
            value = self._items[key]
        except KeyError:
            raise LRUMiss(f'Item {key} no present on LRU') from KeyError
        else:
            # Updating age before returning value
            self._items.pop(key)
            self._items[key] = value
            return value
Пример #27
0
class Density(object):
    def __init__(self, params=None):
        self.params = params

        self.cache = OrderedDict()

        self.max_cache_size = 10000

    def log_p(self, data, params):
        '''
        Args:
            data : (nametuple) Data for density.

            params : (nametuple) Parameters in density.

        Kwargs:
            global_params: (namedtuple) Parameters which are shared across all atoms. If this is None it will use the
                                        current value.
        '''
        key = (data, params, self.params)

        if key not in self.cache:
            self.cache[key] = self._log_p(data, params)

            if len(self.cache) > self.max_cache_size:
                self.cache.popitem(last=False)

        return self.cache[key]

    def _log_p(self, data, params):
        raise NotImplemented
Пример #28
0
class _MultiCache(object):
    """
    A utility class for caching items in a of a dict-of-dicts
    """

    def __init__(self, first_uid, default_factory=lambda: None, maxcaches=None):
        self._maxcaches = maxcaches
        self.caches = OrderedDict()
        self.add(first_uid, default_factory=default_factory)

    def add(self, uid, default_factory=lambda: None):
        assert isinstance(uid[1], tuple)
        if uid not in self.caches:
            cache = defaultdict(default_factory)
            self.caches[uid] = cache
        else:
            raise Exception("MultiCache.add: uid %s is already in use" % str(uid))

        # remove oldest cache, if necessary
        old_uid = None
        if self._maxcaches and len(self.caches) > self._maxcaches:
            old_uid, v = self.caches.popitem(False)  # removes item in FIFO order
        return old_uid

    def touch(self, uid):
        c = self.caches[uid]
        del self.caches[uid]
        self.caches[uid] = c

    def set_maxcaches(self, newmax):
        self._maxcaches = newmax
        while len(self.caches) > self._maxcaches:
            old_uid, v = self.caches.popitem(False)  # removes item in FIFO order
Пример #29
0
def dict_OrderedDict():
    """
    字典是哈希表,默认迭代是无序的,如果希望按照元素添加顺序输出结果,可以用OrderedDict
    :return:
    """
    print ">>>>>dict_OrderedDict:"
    from collections import OrderedDict
    d = dict()
    d["a"] = 1
    d["b"] = 2
    d["c"] = 3

    print u"#非按添加序列输出"
    for k, v in d.items():print k,v
    #a 1
    #c 3
    #b 2
    od = OrderedDict()
    od["a"] = 1
    od["b"] = 2
    od["c"] = 3

    print u"#按添加序列输出"
    for k, v in od.items():print k, v
    #a 1
    #b 2
    #c 3
    print u"#按LIFO顺序弹出"
    print od.popitem() #('c', 3)
    print od.popitem() #('c', 3)
    print od.popitem() #('a', 1)
Пример #30
0
class LRUCache(object):

    def __init__(self, size=1024):
        self.size = size
        self.cache = OrderedDict()

    def add(self, key, value):
        if key in self.cache:
            return

        if len(self.cache) == self.size:
            self._remove_oldest_entry_and_add_new(key, value)
            return

        self._add_new_entry(key, value)

    def get(self, key):
        val = self.cache.get(key, None)
        if val is not None:
            self._update_key_access_time(key)
        return val


    def _remove_oldest_entry_and_add_new(self, key, value):
        self.cache.popitem(last=False)
        self.cache[key] = value

    def _add_new_entry(self, key, value):
        self.cache[key] = value

    def _update_key_access_time(self, key):
        val = self.cache.pop(key)
        self.cache[key] = val
Пример #31
0
class LRUDict(object):
    """A LRU dictionary is a dictionary with a fixed maximum number of keys"""
    def __init__(self, size):
        """Initialization

        In:
          -  ``size`` -- maximum number of keys
        """
        self.size = size
        self.items = OrderedDict()

    def __contains__(self, k):
        """Test if a key exists into this dictionary

        In:
          -  ``k`` -- the key

        Return:
          - a boolean
        """
        return k in self.items

    def __getitem__(self, k):
        """Return the value of a key.

        The key becomes the most recently used key.

        In:
          - ``k`` -- the key

        Return:
          - the value
        """
        v = self.items.pop(k)
        self.items[k] = v

        return v

    def __setitem__(self, k, v):
        """Insert a key as the last recently used

        In:
           - ``k`` -- the key
           - ``v`` -- the value
        """
        self.items.pop(k, None)
        self.items[k] = v

        if len(self.items) > self.size:
            self.items.popitem(False)

    def __delitem__(self, k):
        """Delete a key.

        In:
          - ``k`` -- the key
        """
        del self.items[k]

    def __repr__(self):
        return repr(self.items)
Пример #32
0
class StatsEntry(object):
    """
    Represents a single stats entry (name and method)
    """

    name = None
    """ Name (URL) of this stats entry """

    method = None
    """ Method (GET, POST, PUT, etc.) """

    num_requests = None
    """ The number of requests made """

    num_none_requests = None
    """ The number of requests made with a None response time (typically async requests) """

    num_failures = None
    """ Number of failed request """

    total_response_time = None
    """ Total sum of the response times """

    min_response_time = None
    """ Minimum response time """

    max_response_time = None
    """ Maximum response time """

    num_reqs_per_sec = None
    """ A {second => request_count} dict that holds the number of requests made per second """

    num_fail_per_sec = None
    """ A (second => failure_count) dict that hold the number of failures per second """

    response_times = None
    """
    A {response_time => count} dict that holds the response time distribution of all
    the requests.
    
    The keys (the response time in ms) are rounded to store 1, 2, ... 9, 10, 20. .. 90, 
    100, 200 .. 900, 1000, 2000 ... 9000, in order to save memory.
    
    This dict is used to calculate the median and percentile response times.
    """

    use_response_times_cache = False
    """
    If set to True, the copy of the response_time dict will be stored in response_times_cache 
    every second, and kept for 20 seconds (by default, will be CURRENT_RESPONSE_TIME_PERCENTILE_WINDOW + 10). 
    We can use this dict to calculate the *current*  median response time, as well as other response 
    time percentiles.
    """

    response_times_cache = None
    """
    If use_response_times_cache is set to True, this will be a {timestamp => CachedResponseTimes()} 
    OrderedDict that holds a copy of the response_times dict for each of the last 20 seconds.
    """

    total_content_length = None
    """ The sum of the content length of all the requests for this entry """

    start_time = None
    """ Time of the first request for this entry """

    last_request_timestamp = None
    """ Time of the last request for this entry """
    def __init__(self, stats, name, method, use_response_times_cache=False):
        self.stats = stats
        self.name = name
        self.method = method
        self.use_response_times_cache = use_response_times_cache
        self.reset()

    def reset(self):
        self.start_time = time.time()
        self.num_requests = 0
        self.num_none_requests = 0
        self.num_failures = 0
        self.total_response_time = 0
        self.response_times = {}
        self.min_response_time = None
        self.max_response_time = 0
        self.last_request_timestamp = None
        self.num_reqs_per_sec = {}
        self.num_fail_per_sec = {}
        self.total_content_length = 0
        if self.use_response_times_cache:
            self.response_times_cache = OrderedDict()
            self._cache_response_times(int(time.time()))

    def log(self, response_time, content_length):
        # get the time
        current_time = time.time()
        t = int(current_time)

        if self.use_response_times_cache and self.last_request_timestamp and t > int(
                self.last_request_timestamp):
            # see if we shall make a copy of the respone_times dict and store in the cache
            self._cache_response_times(t - 1)

        self.num_requests += 1
        self._log_time_of_request(current_time)
        self._log_response_time(response_time)

        # increase total content-length
        self.total_content_length += content_length

    def _log_time_of_request(self, current_time):
        t = int(current_time)
        self.num_reqs_per_sec[t] = self.num_reqs_per_sec.setdefault(t, 0) + 1
        self.last_request_timestamp = current_time

    def _log_response_time(self, response_time):
        if response_time is None:
            self.num_none_requests += 1
            return

        self.total_response_time += response_time

        if self.min_response_time is None:
            self.min_response_time = response_time

        self.min_response_time = min(self.min_response_time, response_time)
        self.max_response_time = max(self.max_response_time, response_time)

        # to avoid to much data that has to be transfered to the master node when
        # running in distributed mode, we save the response time rounded in a dict
        # so that 147 becomes 150, 3432 becomes 3400 and 58760 becomes 59000
        if response_time < 100:
            rounded_response_time = round(response_time)
        elif response_time < 1000:
            rounded_response_time = round(response_time, -1)
        elif response_time < 10000:
            rounded_response_time = round(response_time, -2)
        else:
            rounded_response_time = round(response_time, -3)

        # increase request count for the rounded key in response time dict
        self.response_times.setdefault(rounded_response_time, 0)
        self.response_times[rounded_response_time] += 1

    def log_error(self, error):
        self.num_failures += 1
        t = int(time.time())
        self.num_fail_per_sec[t] = self.num_fail_per_sec.setdefault(t, 0) + 1

    @property
    def fail_ratio(self):
        try:
            return float(self.num_failures) / self.num_requests
        except ZeroDivisionError:
            if self.num_failures > 0:
                return 1.0
            else:
                return 0.0

    @property
    def avg_response_time(self):
        try:
            return float(self.total_response_time) / (self.num_requests -
                                                      self.num_none_requests)
        except ZeroDivisionError:
            return 0

    @property
    def median_response_time(self):
        if not self.response_times:
            return 0
        median = median_from_dict(self.num_requests - self.num_none_requests,
                                  self.response_times) or 0

        # Since we only use two digits of precision when calculating the median response time
        # while still using the exact values for min and max response times, the following checks
        # makes sure that we don't report a median > max or median < min when a StatsEntry only
        # have one (or very few) really slow requests
        if median > self.max_response_time:
            median = self.max_response_time
        elif median < self.min_response_time:
            median = self.min_response_time

        return median

    @property
    def current_rps(self):
        if self.stats.last_request_timestamp is None:
            return 0
        slice_start_time = max(
            int(self.stats.last_request_timestamp) - 12,
            int(self.stats.start_time or 0))

        reqs = [
            self.num_reqs_per_sec.get(t, 0)
            for t in range(slice_start_time,
                           int(self.stats.last_request_timestamp) - 2)
        ]
        return avg(reqs)

    @property
    def current_fail_per_sec(self):
        if self.stats.last_request_timestamp is None:
            return 0
        slice_start_time = max(
            int(self.stats.last_request_timestamp) - 12,
            int(self.stats.start_time or 0))

        reqs = [
            self.num_fail_per_sec.get(t, 0)
            for t in range(slice_start_time,
                           int(self.stats.last_request_timestamp) - 2)
        ]
        return avg(reqs)

    @property
    def total_rps(self):
        if not self.stats.last_request_timestamp or not self.stats.start_time:
            return 0.0
        try:
            return self.num_requests / (self.stats.last_request_timestamp -
                                        self.stats.start_time)
        except ZeroDivisionError:
            return 0.0

    @property
    def total_fail_per_sec(self):
        if not self.stats.last_request_timestamp or not self.stats.start_time:
            return 0.0
        try:
            return self.num_failures / (self.stats.last_request_timestamp -
                                        self.stats.start_time)
        except ZeroDivisionError:
            return 0.0

    @property
    def avg_content_length(self):
        try:
            return self.total_content_length / self.num_requests
        except ZeroDivisionError:
            return 0

    def extend(self, other):
        """
        Extend the data from the current StatsEntry with the stats from another
        StatsEntry instance. 
        """
        if self.last_request_timestamp is not None and other.last_request_timestamp is not None:
            self.last_request_timestamp = max(self.last_request_timestamp,
                                              other.last_request_timestamp)
        elif other.last_request_timestamp is not None:
            self.last_request_timestamp = other.last_request_timestamp
        self.start_time = min(self.start_time, other.start_time)

        self.num_requests = self.num_requests + other.num_requests
        self.num_none_requests = self.num_none_requests + other.num_none_requests
        self.num_failures = self.num_failures + other.num_failures
        self.total_response_time = self.total_response_time + other.total_response_time
        self.max_response_time = max(self.max_response_time,
                                     other.max_response_time)
        if self.min_response_time is not None and other.min_response_time is not None:
            self.min_response_time = min(self.min_response_time,
                                         other.min_response_time)
        elif other.min_response_time is not None:
            # this means self.min_response_time is None, so we can safely replace it
            self.min_response_time = other.min_response_time
        self.total_content_length = self.total_content_length + other.total_content_length

        for key in other.response_times:
            self.response_times[key] = self.response_times.get(
                key, 0) + other.response_times[key]
        for key in other.num_reqs_per_sec:
            self.num_reqs_per_sec[key] = self.num_reqs_per_sec.get(
                key, 0) + other.num_reqs_per_sec[key]
        for key in other.num_fail_per_sec:
            self.num_fail_per_sec[key] = self.num_fail_per_sec.get(
                key, 0) + other.num_fail_per_sec[key]

    def serialize(self):
        return {
            "name": self.name,
            "method": self.method,
            "last_request_timestamp": self.last_request_timestamp,
            "start_time": self.start_time,
            "num_requests": self.num_requests,
            "num_none_requests": self.num_none_requests,
            "num_failures": self.num_failures,
            "total_response_time": self.total_response_time,
            "max_response_time": self.max_response_time,
            "min_response_time": self.min_response_time,
            "total_content_length": self.total_content_length,
            "response_times": self.response_times,
            "num_reqs_per_sec": self.num_reqs_per_sec,
            "num_fail_per_sec": self.num_fail_per_sec,
        }

    @classmethod
    def unserialize(cls, data):
        obj = cls(None, data["name"], data["method"])
        for key in [
                "last_request_timestamp",
                "start_time",
                "num_requests",
                "num_none_requests",
                "num_failures",
                "total_response_time",
                "max_response_time",
                "min_response_time",
                "total_content_length",
                "response_times",
                "num_reqs_per_sec",
                "num_fail_per_sec",
        ]:
            setattr(obj, key, data[key])
        return obj

    def get_stripped_report(self):
        """
        Return the serialized version of this StatsEntry, and then clear the current stats.
        """
        report = self.serialize()
        self.reset()
        return report

    def to_string(self, current=True):
        """
        Return the stats as a string suitable for console output. If current is True, it'll show 
        the RPS and failure rait for the last 10 seconds. If it's false, it'll show the total stats 
        for the whole run.
        """
        if current:
            rps = self.current_rps
            fail_per_sec = self.current_fail_per_sec
        else:
            rps = self.total_rps
            fail_per_sec = self.total_fail_per_sec
        return (" %-" + str(STATS_NAME_WIDTH) +
                "s %7d %12s %7d %7d %7d  | %7d %7.2f %7.2f") % (
                    (self.method and self.method + " " or "") + self.name,
                    self.num_requests,
                    "%d(%.2f%%)" % (self.num_failures, self.fail_ratio * 100),
                    self.avg_response_time,
                    self.min_response_time or 0,
                    self.max_response_time,
                    self.median_response_time or 0,
                    rps or 0,
                    fail_per_sec or 0,
                )

    def __str__(self):
        return self.to_string(current=True)

    def get_response_time_percentile(self, percent):
        """
        Get the response time that a certain number of percent of the requests
        finished within.
        
        Percent specified in range: 0.0 - 1.0
        """
        return calculate_response_time_percentile(self.response_times,
                                                  self.num_requests, percent)

    def get_current_response_time_percentile(self, percent):
        """
        Calculate the *current* response time for a certain percentile. We use a sliding 
        window of (approximately) the last 10 seconds (specified by CURRENT_RESPONSE_TIME_PERCENTILE_WINDOW) 
        when calculating this.
        """
        if not self.use_response_times_cache:
            raise ValueError(
                "StatsEntry.use_response_times_cache must be set to True if we should be able to calculate the _current_ response time percentile"
            )
        # First, we want to determine which of the cached response_times dicts we should
        # use to get response_times for approximately 10 seconds ago.
        t = int(time.time())
        # Since we can't be sure that the cache contains an entry for every second.
        # We'll construct a list of timestamps which we consider acceptable keys to be used
        # when trying to fetch the cached response_times. We construct this list in such a way
        # that it's ordered by preference by starting to add t-10, then t-11, t-9, t-12, t-8,
        # and so on
        acceptable_timestamps = []
        for i in range(9):
            acceptable_timestamps.append(
                t - CURRENT_RESPONSE_TIME_PERCENTILE_WINDOW - i)
            acceptable_timestamps.append(
                t - CURRENT_RESPONSE_TIME_PERCENTILE_WINDOW + i)

        cached = None
        for ts in acceptable_timestamps:
            if ts in self.response_times_cache:
                cached = self.response_times_cache[ts]
                break

        if cached:
            # If we fond an acceptable cached response times, we'll calculate a new response
            # times dict of the last 10 seconds (approximately) by diffing it with the current
            # total response times. Then we'll use that to calculate a response time percentile
            # for that timeframe
            return calculate_response_time_percentile(
                diff_response_time_dicts(self.response_times,
                                         cached.response_times),
                self.num_requests - cached.num_requests,
                percent,
            )

    def percentile(self,
                   tpl=" %-" + str(STATS_TYPE_WIDTH) + "s %-" +
                   str(STATS_NAME_WIDTH) +
                   "s %8d %6d %6d %6d %6d %6d %6d %6d %6d %6d %6d %6d"):
        if not self.num_requests:
            raise ValueError(
                "Can't calculate percentile on url with no successful requests"
            )

        return tpl % (self.method, self.name, self.num_requests,
                      self.get_response_time_percentile(0.5),
                      self.get_response_time_percentile(0.66),
                      self.get_response_time_percentile(0.75),
                      self.get_response_time_percentile(0.80),
                      self.get_response_time_percentile(0.90),
                      self.get_response_time_percentile(0.95),
                      self.get_response_time_percentile(0.98),
                      self.get_response_time_percentile(0.99),
                      self.get_response_time_percentile(0.999),
                      self.get_response_time_percentile(0.9999),
                      self.get_response_time_percentile(1.00))

    def _cache_response_times(self, t):
        self.response_times_cache[t] = CachedResponseTimes(
            response_times=copy(self.response_times),
            num_requests=self.num_requests,
        )

        # We'll use a cache size of CURRENT_RESPONSE_TIME_PERCENTILE_WINDOW + 10 since - in the extreme case -
        # we might still use response times (from the cache) for t-CURRENT_RESPONSE_TIME_PERCENTILE_WINDOW-10
        # to calculate the current response time percentile, if we're missing cached values for the subsequent
        # 20 seconds
        cache_size = CURRENT_RESPONSE_TIME_PERCENTILE_WINDOW + 10

        if len(self.response_times_cache) > cache_size:
            # only keep the latest 20 response_times dicts
            for i in range(len(self.response_times_cache) - cache_size):
                self.response_times_cache.popitem(last=False)
Пример #33
0
class LRU_cache:
    def __init__(self, size, time_limit):
        '''
        Initialize the LRU cache
        
        size: max number of elements allowed in cache
        time_limit: how long an item is allowed to stay in the cache

       '''
        # Use Ordered Dictionary for cache
        self.cache = OrderedDict()
        # Capacity of cache
        self.size = size
        self.time_limit = time_limit

    def get(self, key):
        '''
        Access item in cache and move it to the back and update the time 
        it was accessed at.
        
        key: key of item to be retrieved

        '''
        if key in self.cache.keys():
            value = self.cache.pop(key)[0]
            self.cache[key] = (value, time.time())
            return value
        else:
            return "Error: Item Not Found."

    def put(self, key, value):
        '''
        Add item to cache or update the value of an existing key. This operation
        clears all expired items
        
        key: key of item to be retrieved
        value: value of item

        '''
        if key in self.cache.keys():
            self.cache.pop(key)
            self.cache[key] = (value, time.time())
        else:
            if len(self.cache.keys()) >= self.size:
                self.cache.popitem(last=False)
            self.cache[key] = (value, time.time())
        self.clear_expired()

    def clear_expired(self):
        '''
        Clears all items in cache that have expired.

        '''
        expired = time.time() - self.time_limit
        ex_flag = True

        while ex_flag:
            first = next(iter(self.cache))
            if expired < self.cache[first][1]:
                ex_flag = False
            else:
                self.cache.popitem(last=False)

    def __str__(self):
        '''
        Prints all items in the cache as a dictionary.

        '''
        d = {}
        for key, (value, time) in self.cache.items():
            d[key] = value

        return str(d)
Пример #34
0
class YTActions():
    """
    Class responsible for searching in YouTube service and holding information about search results.

    Attributes
    ----------
    avail_files : OrderedDict
        Contains tuples of following format:

        avail_files = {
                        "token": (`adj_tokens`, `files`),
                        ...
                    }

        `adj_tokens` contains adjacent tokens, `files` contains files of given search.
        (just as described below).
    visible_files : dict
        Current search results. Key is a movie name, value is a ``YTStor`` object for given movie.
    adj_tokens : dict
        Dictionary of tokens for adjacent search pages. Under ``False`` key the previous page is kept, under ``True`` -
        the next. Other keys are not allowed.
    vf_iter : obj
        Here the ``YTActions`` obejct stores an iterator allowing for current directory content listing. Used by
        ``__iter__`` and ``__next__`` methods.
    search_params : dict
        Additional search params for __search.
    yts_opts : dict
        Custom options passed to YTStor objects created in this class.
    api_key : str
        YouTube API key.
    preferences : dict
        Current object preferences.

    Parameters
    ----------
    search_query : str
        Currently used search phrase.
    """

    api_key = "AIzaSyCPOg5HQfHayQH6mRu4m2PMGc3eHd5lllg"

    preferences = {"metadata": {"desc": False, "thumb": False}}

    def __init__(self, search_query):

        if not isinstance(search_query, str):
            raise ValueError("Expected str for 1st parameter (search_query).")

        self.avail_files = OrderedDict()
        self.visible_files = None
        self.adj_tokens = {False: None, True: None}

        self.vf_iter = None

        self.search_params = {
            "maxResults": 10,
            "order": self.preferences["order"]
        }  # relevance by default
        self.yts_opts = dict()

        parsed = self.__searchParser(search_query)

        # search params
        self.search_params.update(parsed[0])

        # YTa options
        _pref = deepcopy(
            self.preferences)  # new object, just to not affect other intances.
        if 'metadata' in parsed[1]:
            try:
                meta_list = parsed[1]['metadata'].split(',')
            except AttributeError:
                meta_list = []

            if 'desc' in meta_list: _pref['metadata']['desc'] = True
            else: _pref['metadata']['desc'] = False

            if 'thumb' in meta_list: _pref['metadata']['thumb'] = True
            else: _pref['metadata']['thumb'] = False

        self.preferences = _pref

        # YTs options
        self.yts_opts = parsed[1]

        if 'audio' in parsed[1] and 'video' not in parsed[1]:
            self.yts_opts['video'] = False
        if 'video' in parsed[1] and 'audio' not in parsed[1]:
            self.yts_opts['audio'] = False

        try:
            self.__getChannelId()
        except requests.exceptions.ConnectionError:
            raise ConnectionError

        if parsed[0].get("publishedBefore"):
            self.search_params["publishedBefore"] += "T00:00:00Z"
        if parsed[0].get("publishedAfter"):
            self.search_params["publishedAfter"] += "T00:00:00Z"

    def __getChannelId(self):
        """
        Obtain channel id for channel name, if present in ``self.search_params``.
        """

        if not self.search_params.get("channelId"):
            return

        api_fixed_url = "https://www.googleapis.com/youtube/v3/channels?part=id&maxResults=1&fields=items%2Fid&"
        url = api_fixed_url + urlencode(
            {
                "key": self.api_key,
                "forUsername": self.search_params["channelId"]
            })
        get = requests.get(url).json()

        try:
            self.search_params["channelId"] = get['items'][0]['id']
            return  # got it

        except IndexError:
            pass  # try searching now...

        api_fixed_url = "https://www.googleapis.com/youtube/v3/search?part=snippet&type=channel&fields=items%2Fid&"
        url = api_fixed_url + urlencode({
            "key": self.api_key,
            "q": self.search_params['channelId']
        })
        get = requests.get(url).json()

        try:
            self.search_params["channelId"] = get['items'][0]['id'][
                'channelId']

        except IndexError:
            del self.search_params["channelId"]  # channel not found

    def __searchParser(self, query):
        """
        Parse `query` for advanced search options.

        Parameters
        ----------
        query : str
            Search query to parse. Besides a search query, user can specify additional search parameters and YTFS
            specific options. Syntax:
            Additional search parameters: ``option:value``. if `value` contains spaces, then surround it with
            parentheses; available parameters: `channel`, `max`, `before`, `after`, `order`.
            YTFS options: specify options between ``[`` and ``]``; Available options: `a`, `v`, `f`, `P`, `s`, `m`.
            If an option takes a parameter, then specify it beetween parentheses.

            Examples: ``channel:foo search query``, ``my favourite music [a]``,
            ``channel:(the famous funny cats channel) [vf(240)P] funny cats max:20``.

            Invalid parameters/options are ignored.

        Returns
        -------
        params : tuple
            Tuple: 0 - dictionary of url GET parameters; 1 - dictionary of YTStor options.
        """

        ret = dict()

        parse_params = True

        buf = ""
        ptr = ""

        p_avail = ("channel", "max", "before", "after", "order")

        opts = dict()
        par_open = False

        translate = {
            'a': 'audio',
            'v': 'video',
            'f': 'format',
            's': 'stream',
            'P': 'stream',
            'm': 'metadata',
            'max': 'maxResults',
            'channel': 'channelId',
            'before': 'publishedBefore',
            'after': 'publishedAfter',
            'order': 'order',
            '': 'q'
        }

        for i in query + ' ':

            if parse_params:

                if not par_open:

                    if i == ' ':  # flush buf

                        try:
                            if ret.get(translate[ptr]):
                                ret[translate[ptr]] += ' '
                            else:
                                ret[translate[ptr]] = ''

                            ret[translate[ptr]] += buf

                        except KeyError:
                            pass

                        ptr = ""
                        buf = ""

                    elif i == ':' and buf in p_avail:

                        ptr = buf
                        buf = ""

                    elif not buf and i == '[':  # buf must be empty

                        parse_params = False
                        ptr = ""

                    elif i != '(':
                        buf += i

                elif not (par_open == 1 and i == ')'):
                    buf += i

                if i == '(': par_open += 1
                if par_open > 0 and i == ')': par_open -= 1

            else:

                if i == ']':

                    parse_params = True
                    par_open = False
                    ptr = ""
                    buf = ""

                elif ptr and not par_open and i == '(':
                    par_open = True

                elif par_open:

                    if i == ')':

                        try:
                            opts[translate[ptr]] = buf
                        except KeyError:
                            pass

                        par_open = False
                        buf = ""

                    else:
                        buf += i

                elif i.isalpha():

                    ptr = i

                    try:
                        opts[translate[ptr]] = not i.isupper()
                    except KeyError:
                        pass

        return (ret, opts)

    def __search(self, pt=""):
        """
        Method responsible for searching using YouTube API.

        Parameters
        ----------
        pt : str
            Token of search results page. If ``None``, then the first page is downloaded.

        Returns
        -------
        results : dict
            Parsed JSON returned by YouTube API.
        """

        if not self.search_params.get('q') and not self.search_params.get(
                'channelId'):
            return {'items': []}  # no valid query - no results.

        api_fixed_url = "https://www.googleapis.com/youtube/v3/search?part=snippet&type=video&fields=items(id%2Ckind%2Csnippet)%2CnextPageToken%2CprevPageToken&"

        d = {"key": self.api_key, "pageToken": pt}
        d.update(self.search_params)
        url = api_fixed_url + urlencode(d)

        try:
            get = requests.get(url)
        except requests.exceptions.ConnectionError:
            raise ConnectionError

        if get.status_code != 200:
            return {'items': []}  # no valid query - no results.

        return get.json()

    def __iter__(self):
        """
        Create an iterator. Method allows - in a simple manner - for obtaining a generator which contains filenames.
        The real generator is ``self.vf_iter``; YTActions object (used as iterator) is only a wrapper.

        Returns
        -------
        self : YTActions
            This very same object with ``self.vf_iter`` constructed and initialised.
        """

        ctrl = []

        if self.adj_tokens[False] is not None:
            ctrl += [" prev"]
        if self.adj_tokens[True] is not None:
            ctrl += [" next"]

        self.vf_iter = iter(
            ctrl +
            [e + self.visible_files[e].extension for e in self.visible_files])

        return self

    def __next__(self):
        """
        ``next()`` support. Returns next filename.

        Returns
        -------
        file_name : str
            Next filename from ``self.vf_iter.``
        """

        return next(self.vf_iter)  #easy, ain't it?

    def __getitem__(self, key):
        """
        Read elements from ``YTActions`` object by using `key`. One can use object like a dict (and like a boss, ofc).

        Parameters
        ----------
        key : str
            The key (e.g. ``YTActions['Rick Astley - Never Gonna Give You Up.mp4']``).

        Returns
        -------
        YTStor
            ``YTStor`` object associated with name `key`.
        """

        _k = os.path.splitext(key)

        if _k[1] not in ('.txt', '.jpg'):
            key = _k[0]

        return self.visible_files[key]

    def __in__(self, arg):
        """
        Check, if movie of name `arg` is present in the object.

        Parameters
        ----------
        arg : str
            Filename.
        """

        _a = os.path.splitext(arg)

        if _a[1] not in ('txt', 'jpg'):
            arg = _a[0]

        return arg in self.visible_files or (
            self.adj_tokens[0] is not None
            and arg == " prev") or (self.adj_tokens[0] is None
                                    and self.adj_tokens[1] is not None
                                    and arg == " next")

    def updateResults(self, forward=None):
        """
        Reload search results or load another "page".

        Parameters
        ----------
        forward : bool or None, optional
            Whether move forwards or backwards (``True`` or ``False``). If ``None``, then first page is loaded.
        """

        # this choses data we need.
        files = lambda x: {
            i['snippet']['title'].replace('/', '\\'): YTStor(
                {
                    'yid': i['id']['videoId'],
                    'pub_date': i['snippet']['publishedAt']
                },
                opts=self.yts_opts)
            for i in x['items']
        }
        descs = lambda x: {(i['snippet']['title'].replace('/', '\\') + '.txt'):
                           YTMetaStor(
                               {
                                   'title': i['snippet']['title'],
                                   'yid': i['id']['videoId'],
                                   'desc': i['snippet']['description'],
                                   'channel': i['snippet']['channelTitle'],
                                   'pub_date': i['snippet']['publishedAt']
                               },
                               opts=dict())
                           for i in x['items']}
        thumbs = lambda x: {
            (i['snippet']['title'].replace('/', '\\') + '.jpg'): YTMetaStor(
                {
                    'url': i['snippet']['thumbnails']['high']['url'],
                    'pub_date': i['snippet']['publishedAt']
                },
                opts=dict())
            for i in x['items']
        }

        try:
            if self.adj_tokens[
                    forward] is None:  # in case someone would somehow cross boundary.
                forward = None
        except KeyError:
            pass

        recv = None
        try:
            try:
                data = self.avail_files[self.adj_tokens[
                    forward]]  # maybe data is already available locally.
            except KeyError:
                recv = self.__search(
                    self.adj_tokens[forward])  # nope, we have to search.
        except KeyError:  # wrong index in adj_tokens

            if forward is None:
                recv = self.__search()
            else:
                raise ValueError(
                    "Valid values for forward are True, False or None (default)."
                )

        if recv is not None:

            _d = files(recv)
            if self.preferences['metadata']['desc']: _d.update(descs(recv))
            if self.preferences['metadata']['thumb']: _d.update(thumbs(recv))

            data = (None, _d)  # little format unification.

        if len(self.avail_files) > 4:

            pop = self.avail_files.popitem(
                False)  # get rid of the oldest data.
            for s in pop[1][1].values():
                s.clean()

        adj_t = deepcopy(
            self.adj_tokens
        )  # this will we write to avail_files, now we update self.adj_tokens.

        if data[0] is None:  # get tokens from obtained results.
            try:
                self.adj_tokens[False] = recv['prevPageToken']
            except KeyError:
                self.adj_tokens[False] = None

            try:
                self.adj_tokens[True] = recv['nextPageToken']
            except KeyError:
                self.adj_tokens[True] = None

        else:  # already in avail_files.
            self.adj_tokens = data[0]

        if forward is not None:
            # backup last results in avail_files:
            self.avail_files[self.adj_tokens[not forward]] = (
                adj_t, self.visible_files)

        self.visible_files = data[1]

    def clean(self):
        """Clear the data. For each ``YTStor`` object present in this object ``clean`` method is executed."""

        for s in self.visible_files.values():
            s.clean()
        for s in [
                sub[1][x] for sub in self.avail_files.values() for x in sub[1]
        ]:  # Double list comprehensions aren't very
            s.clean()  # readable...
Пример #35
0
class alg:
    def __repr__(self):
        return "LIRS"

    def __init__(self, c, **kwargs):
        # c is cache size
        self.c = c  # Max
        self.lirs = 0
        self.hirs = 0
        self.maxhirs = max(1, 0.01 * c)
        self.maxlirs = c - self.maxhirs
        self.S = OrderedDict(
        )  # Recently accessed pages (LIR pages and non-resident HIR pages), newest element is last
        self.Q = OrderedDict()  # Resident HIR pages
        self.hitcount = 0
        self.count = 0

    def setup(self, reqlist):
        # I'm an online algorithm :-)
        pass

    def get(self, key):
        #if self.count % 100 == 0:
        #       sys.stderr.write("S: %d\n" % len(self.S))
        self.countResident()
        self.count += 1
        if (key in self.S and self.S[key].resident) or key in self.Q:
            #print "HIT for %s" % key
            self.hitcount += 1
            return 1
        return 0
        #print "MISS for %s" % key

    def put(self, key, val=1):
        if key in self.S:
            e = self.S[key]
            del self.S[key]
            if e.flag == HIR:
                # A HIR block with lower reuse distance than the bottom LIR element
                if e.resident:
                    del self.Q[key]
                    self.hirs -= 1
                assert self.oldestS().flag == LIR
                assert self.hirs <= self.maxhirs
                self.swap()  # Change one LIR page to a HIR page
                self.evict(
                )  # Keep the number of resident HIR pages <= self.maxhirs
                self.lirs += 1
            e.resident = True
            e.flag = LIR
            self.S[key] = e
            self.prune()  #  If this was a LIR element at the bottom
        elif key in self.Q:
            # Resident HIR page which is not in S, reuse distance is large so we don't make it a LIR page
            e = self.Q[key]
            assert e.resident and e.flag == HIR
            del self.Q[key]
            self.Q[key] = e
            self.S[key] = e
        else:
            # not in cache
            # When a miss occurs and a free block is needed for replacement, we choose an HIR block that is resident in the cache
            e = entry(key)
            if self.lirs < self.maxlirs:
                e.flag = LIR  # Not using all the cache, make it a LIR page
                self.lirs += 1
            else:
                # NOTE: Not changing the number of LIR blocks!
                self.Q[key] = e
                self.hirs += 1
                self.evict()  # Evicting if we have max number of HIR blocks
            self.S[key] = e

        assert self.oldestS().flag == LIR
        self.countResident()

    def countResident(self):
        sm = 0
        for key, e in self.S.items():
            sm += 1 if e.resident else 0
        for key, e in self.Q.items():
            sm += 1 if key not in self.S else 0
        if sm != self.lirs + self.hirs:
            print "sm=%d, self.lirs=%d, self.hirs=%d" % (sm, self.lirs,
                                                         self.hirs)
        assert sm == self.lirs + self.hirs

    def evict(self):
        if self.hirs > self.maxhirs:  # Setting the size of Q
            k, e_hir = self.Q.popitem(last=False)
            assert e_hir.flag == HIR and e_hir.resident
            e_hir.resident = False  # It is maybe in S
            self.hirs -= 1
        if self.hirs > self.maxhirs:
            print "hirs: %d maxhirs: %d" % (self.hirs, self.maxhirs)
        assert self.hirs <= self.maxhirs
        # TODO: If there are many nonresident entries in S, should we delete this from S?

    def swap(self):
        key, e = self.S.popitem(last=False)
        assert e.flag == LIR and e.resident
        e.flag = HIR
        self.hirs += 1
        self.lirs -= 1
        self.Q[e.key] = e
        # Switched this LIR block to HIR and put it in Q
        # Important! We don't put it back in S

    def prune(self):
        while self.S:
            oldest = self.oldestS()
            if oldest.flag == LIR:
                break
            k, dele = self.S.popitem(last=False)
            assert dele.flag == HIR
            if dele.resident:
                assert k in self.Q
            else:
                assert k not in self.Q

    def oldestS(self):
        return self.S.itervalues().next()

    def oldestQ(self):
        return self.Q.itervalues().next()
Пример #36
0
class World:
    def __init__(self, server, name: str, path: str, chunk_cache_max: int) -> None:
        self.server = server

        self.name = name
        self.path = path  # should be "worlds/world_name_dim/" in production probably

        self.data = None

        self._chunk_cache_max = chunk_cache_max
        self._chunk_cache = OrderedDict()

        self._proper_name = None
        self._dimension = None

    @property
    def proper_name(self):
        if self._proper_name is None:
            self._proper_name = list(self.server.worlds.keys())[list(self.server.worlds.values()).index(self)]

        return self._proper_name

    @property
    def dimension(self):
        if self._dimension is None:
            self._dimension = "minecraft:" + self.proper_name.replace(self.name + "_", "")

        return self._dimension

    async def init(self):
        self.data = await self.load_level_data()
        return self  # for fluent style chaining

    async def load_level_data(self):
        file = os.path.join(self.path, "level.dat")

        if os.path.isfile(file):
            async with aiofile.async_open(file, "rb") as level_data_file:
                return nbt.TAG_Compound.unpack(Buffer(await level_data_file.read()))

        return new_level_nbt((2586, self.server.meta.version, 19133), self.name, (0, 100, 0), self.server.conf["seed"])["Data"]

    def cache_chunk(self, chunk: Chunk, key: tuple) -> Chunk:
        self._chunk_cache[key] = chunk

        if len(self.chunk_cache) > self._chunk_cache_max:
            self._chunk_cache.popitem(False)

        return chunk

    async def fetch_chunk(self, chunk_x: int, chunk_z: int) -> Chunk:
        key = (chunk_x, chunk_z)

        try:
            return self._chunk_cache[key]
        except KeyError:
            pass

        try:
            return self.cache_chunk(await self.server.chunkio.fetch_chunk_async(self.path, *key), key)
        except FileNotFoundError:
            chunk_data = self.server.generator.generate_chunk(self.data["RandomSeed"], self.dimension, chunk_x, chunk_z)
            return chunk_data
Пример #37
0
class EmptyFeature(Sequence):
    def __init__(self,
                 lookback,
                 raw_data_manager,
                 name="",
                 backfill=True,
                 history_lengh=None,
                 features=None):
        raw_data_length = raw_data_manager.get_history()

        # kind of spaghetti logic here to for feature history length but the gist is this:
        # one may specify history length when instantiating or we can produce the maximum
        # length given the data available
        feath = 0
        hh = raw_data_length

        if features is not None:
            feath = min([f.get_history_length() for f in features])
            hh = feath

        if history_lengh is None:
            self.history_lengh = hh - lookback + 1
        else:
            self.history_lengh = history_lengh

        self.lookback = lookback

        self.raw_data_manager = raw_data_manager

        # raw data must be able to fill history
        assert (self.history_lengh + lookback - 1) <= raw_data_length
        assert lookback <= raw_data_manager.get_lookback()

        self.feature = OrderedDict()

        self.feature_numpy = RingBuffer(capacity=self.history_lengh,
                                        dtype=np.float64)

        self.latest = {}

        # a feature may contain multiple features
        self.features = features

        self.feature_df = raw_data_manager.get_backfill_df()

        # trim df
        drop_i = self.lookback
        if self.features is not None:
            if len(self.features) > 0:
                drop_i = drop_i + max(
                    [f.get_lookback() for f in self.features]) - 1

        self.feature_df = self.feature_df.iloc[(drop_i - 1):]

        # must take into account history len;

        if backfill:
            self.backfill()

        self.live_save_path = 'data_test/live/features/' + type(
            self).__name__ + '.csv'

        self.backtest_path = 'data_test/features/' + self.__str__(
        ) + name + '.csv'

        # self.save_feature()

        self.test_rounded = []

        super().__init__()

    def get_feature(self):
        # assert len(self.feature) > 0
        return self.feature

    def get_history_length(self):
        return self.history_lengh

    # -> override this ...
    def compute(self, data_dict):
        return []

    def populate_feature(self):
        l = len(self.get_TS())
        c = 0
        for index, value in self.get_TS().items():
            self.feature_numpy.append(value)
            self.feature[index] = value
            if c == l - 1:
                self.latest = {'time': index, 'value': value}
            c += 1

    def update_feature(self, time, value):

        # we remove first item in dict, add the new one, FIFO style
        # maybe use hist length?
        if len(self.feature) > self.history_lengh:
            self.feature.popitem(last=False)

        self.feature[time] = value

        self.feature_numpy.append(value)

        # assert len(self.feature) == self.history_lengh

    # backfill history
    def backfill(self):

        data = self.raw_data_manager.get_backfill_data()
        ff = self.compute(data)[-self.history_lengh:]

        print(len(ff))
        print(self.history_lengh)

        assert len(ff) == self.history_lengh

        self.feature_df[str(self)] = ff

        self.populate_feature()

    # live update
    def update(self):
        candle = self.raw_data_manager.get_live_candle()
        time_stamp = candle.get('time')

        # update sub-features
        if self.features is not None:
            for f in self.features:
                f.update()

        # check as to not duplicate update
        if time_stamp in self.feature:
            return

        # print('Updating ... ' + type(self).__name__)

        data = self.raw_data_manager.get_live_data()

        new_val = self.compute(data)[-1]

        self.latest = {'time': time_stamp, 'value': new_val}

        self.update_feature(time_stamp, new_val)

        # self.save_feature_live()

    def __getitem__(self, i):

        rounded_ii = self.get_rounded_index(i)
        if rounded_ii in self.feature:
            return self.feature[rounded_ii]
        else:
            print("Feature is... ")
            print(type(self).__name__)
            print("Actual index ")
            print(i)
            print("Rounded ")
            print(rounded_ii)
            print("First keys")
            kk = list(self.feature.keys())
            print(kk[0:10])

        raise ValueError("Feature timestamp not found")

    def get_last_timestamp(self):
        return next(reversed(self.feature))

    def get_rounded_index(self, index):
        per_minutes = self.raw_data_manager.get_period_in_minutes()
        return index - (index // 60 % per_minutes) * 60

    def get_period(self):
        return self.raw_data_manager.get_period()

    def __len__(self):
        return len(self.feature)

    def __eq__(self, other_feature):
        return isinstance(other_feature, EmptyFeature) and type(self).__name__ == type(other_feature).__name__ \
               and self.raw_data_manager == other_feature.raw_data_manager

    def __hash__(self):
        return hash(str(self))

    def __str__(self):
        return type(self).__name__ + self.raw_data_manager.get_symbol(
        ) + self.get_period()

    def get_history_start_time(self):
        # return self.feature_df.index[0]
        return next(iter(self.feature))

    def get_DF(self):
        return self.feature_df

    def get_TS(self):
        return self.feature_df[str(self)]

    def get_numpy(self):
        return self.feature_numpy

    # Use this method especially ifm for example
    #  in an alpha that updates every 1 minute you need a feature that updates every 5m.
    # If not used, feature[ii] will give a value error in that instance
    def get_latest(self):
        return self.latest

    def get_lookback(self):
        return self.lookback

    def save_DF(self):
        name = type(self).__name__ + '.csv'
        self.feature_df.to_csv('data_test/features/' + name)

    def save_feature(self):
        if os.path.isfile(self.backtest_path):
            return

        feature_file = open(self.backtest_path, 'w+')

        writer = csv.DictWriter(feature_file, fieldnames=['time', 'value'])
        writer.writeheader()

        for ts, val in self.feature.items():
            writer.writerow({'time': ts, 'value': val})

    def save_feature_live(self):
        strategy_file = open(self.live_save_path, 'a')

        writer = csv.DictWriter(strategy_file, fieldnames=['time', 'value'])

        writer.writerow(self.latest)
Пример #38
0
for p in Point1(3, 25), Point1(7, 2):
    print(p)

#  making direct assignments
a = Point1.x.__doc__ = 15
b = Point1.y.__doc__ = 3
print(a * b)
print("\n")

#  OrderedDict same as dictionaries but they order the items.
ordered_dict = OrderedDict()
for i in range(6):
    ordered_dict[i] = i * 5
print(ordered_dict)
#  we can popitem as well. If Last = True, then LIFO returns. If false, FIFO returns
print(ordered_dict.popitem(last=True))
print(ordered_dict.popitem(last=False))
print(ordered_dict)
#  with this method, we can move a key and its pair to end. If last = False, then move it to the beginning
ordered_dict.move_to_end(1)
print(ordered_dict)
ordered_dict.move_to_end(1, last=False)
print(ordered_dict)

ordered_dict1 = {}
for i in range(6):
    ordered_dict1[i] = i * 5
print(ordered_dict1)
#  we cannot use this. Because popitem in dict has no arguments!
"""print(ordered_dict1.popitem(last=True))
print(ordered_dict1.popitem(last=False))"""
Пример #39
0
class _SlideCache(object):
    def __init__(self, cache_size, dz_opts):
        self.cache_size = cache_size
        self.dz_opts = dz_opts
        self._lock = Lock()
        self._cache = OrderedDict()

    def get(self, path, originalPath=None):
        with self._lock:
            if path in self._cache:
                # Move to end of LRU
                slide = self._cache.pop(path)
                self._cache[path] = slide
                return slide

        osr = OpenSlide(path)
        # try:
        #    osr = OpenSlide(path)
        # except:
        #    osr = ImageSlide(path)
        # Fix for 16 bits tiff files
        # if osr._image.getextrema()[1] > 256:
        #     osr._image = osr._image.point(lambda i:i*(1./256)).convert('L')

        slide = DeepZoomGenerator(osr, **self.dz_opts)
        slide.osr = osr

        slide.associated_images = {}
        for name, image in slide.osr.associated_images.items():
            slide.associated_images[name] = image

        try:
            mpp_x = osr.properties[openslide.PROPERTY_NAME_MPP_X]
            mpp_y = osr.properties[openslide.PROPERTY_NAME_MPP_Y]
            slide.properties = osr.properties
            slide.mpp = (float(mpp_x) + float(mpp_y)) / 2
        except (KeyError, ValueError):
            try:
                if osr.properties["tiff.ResolutionUnit"] == "centimetre":
                    numerator = 10000  # microns in CM
                else:
                    numerator = 25400  # Microns in Inch
                mpp_x = numerator / float(osr.properties["tiff.XResolution"])
                mpp_y = numerator / float(osr.properties["tiff.YResolution"])
                slide.properties = osr.properties
                slide.mpp = (float(mpp_x) + float(mpp_y)) / 2
            except:
                slide.mpp = 0
        try:
            slide.properties = slide.properties
        except:
            slide.properties = osr.properties
        slide.tileLock = Lock()
        if originalPath:
            slide.properties = {"Path": originalPath}
        with self._lock:
            if path not in self._cache:
                while len(self._cache) >= self.cache_size:
                    self._cache.popitem(last=False)
                self._cache[path] = slide
        return slide
Пример #40
0
class ConnectionState:
    def __init__(self, *, dispatch, chunker, syncer, http, loop, **options):
        self.loop = loop
        self.http = http
        self.max_messages = max(options.get('max_messages', 5000), 100)
        self.dispatch = dispatch
        self.chunker = chunker
        self.syncer = syncer
        self.is_bot = None
        self.shard_count = None
        self._ready_task = None
        self._fetch_offline = options.get('fetch_offline_members', True)
        self.heartbeat_timeout = options.get('heartbeat_timeout', 60.0)
        self._listeners = []

        activity = options.get('activity', None)
        if activity:
            if not isinstance(activity, _ActivityTag):
                raise TypeError(
                    'activity parameter must be one of Game, Streaming, or Activity.'
                )

            activity = activity.to_dict()

        status = options.get('status', None)
        if status:
            if status is Status.offline:
                status = 'invisible'
            else:
                status = str(status)

        self._activity = activity
        self._status = status

        self.clear()

    def clear(self):
        self.user = None
        self._users = weakref.WeakValueDictionary()
        self._emojis = {}
        self._calls = {}
        self._guilds = {}
        self._voice_clients = {}

        # LRU of max size 128
        self._private_channels = OrderedDict()
        # extra dict to look up private channels by user id
        self._private_channels_by_user = {}
        self._messages = deque(maxlen=self.max_messages)

    def process_listeners(self, listener_type, argument, result):
        removed = []
        for i, listener in enumerate(self._listeners):
            if listener.type != listener_type:
                continue

            future = listener.future
            if future.cancelled():
                removed.append(i)
                continue

            try:
                passed = listener.predicate(argument)
            except Exception as e:
                future.set_exception(e)
                removed.append(i)
            else:
                if passed:
                    future.set_result(result)
                    removed.append(i)
                    if listener.type == ListenerType.chunk:
                        break

        for index in reversed(removed):
            del self._listeners[index]

    @property
    def self_id(self):
        u = self.user
        return u.id if u else None

    @property
    def voice_clients(self):
        return list(self._voice_clients.values())

    def _get_voice_client(self, guild_id):
        return self._voice_clients.get(guild_id)

    def _add_voice_client(self, guild_id, voice):
        self._voice_clients[guild_id] = voice

    def _remove_voice_client(self, guild_id):
        self._voice_clients.pop(guild_id, None)

    def _update_references(self, ws):
        for vc in self.voice_clients:
            vc.main_ws = ws

    def store_user(self, data):
        # this way is 300% faster than `dict.setdefault`.
        user_id = int(data['id'])
        try:
            return self._users[user_id]
        except KeyError:
            user = User(state=self, data=data)
            if user.discriminator != '0000':
                self._users[user_id] = user
            return user

    def get_user(self, id):
        return self._users.get(id)

    def store_emoji(self, guild, data):
        emoji_id = int(data['id'])
        self._emojis[emoji_id] = emoji = Emoji(guild=guild,
                                               state=self,
                                               data=data)
        return emoji

    @property
    def guilds(self):
        return list(self._guilds.values())

    def _get_guild(self, guild_id):
        return self._guilds.get(guild_id)

    def _add_guild(self, guild):
        self._guilds[guild.id] = guild

    def _remove_guild(self, guild):
        self._guilds.pop(guild.id, None)

        for emoji in guild.emojis:
            self._emojis.pop(emoji.id, None)

        del guild

    @property
    def emojis(self):
        return list(self._emojis.values())

    def get_emoji(self, emoji_id):
        return self._emojis.get(emoji_id)

    @property
    def private_channels(self):
        return list(self._private_channels.values())

    def _get_private_channel(self, channel_id):
        try:
            value = self._private_channels[channel_id]
        except KeyError:
            return None
        else:
            self._private_channels.move_to_end(channel_id)
            return value

    def _get_private_channel_by_user(self, user_id):
        return self._private_channels_by_user.get(user_id)

    def _add_private_channel(self, channel):
        channel_id = channel.id
        self._private_channels[channel_id] = channel

        if self.is_bot and len(self._private_channels) > 128:
            _, to_remove = self._private_channels.popitem(last=False)
            if isinstance(to_remove, DMChannel):
                self._private_channels_by_user.pop(to_remove.recipient.id,
                                                   None)

        if isinstance(channel, DMChannel):
            self._private_channels_by_user[channel.recipient.id] = channel

    def add_dm_channel(self, data):
        channel = DMChannel(me=self.user, state=self, data=data)
        self._add_private_channel(channel)
        return channel

    def _remove_private_channel(self, channel):
        self._private_channels.pop(channel.id, None)
        if isinstance(channel, DMChannel):
            self._private_channels_by_user.pop(channel.recipient.id, None)

    def _get_message(self, msg_id):
        return utils.find(lambda m: m.id == msg_id, self._messages)

    def _add_guild_from_data(self, guild):
        guild = Guild(data=guild, state=self)
        self._add_guild(guild)
        return guild

    def chunks_needed(self, guild):
        for chunk in range(math.ceil(guild._member_count / 1000)):
            yield self.receive_chunk(guild.id)

    def _get_guild_channel(self, data):
        try:
            guild = self._get_guild(int(data['guild_id']))
        except KeyError:
            channel = self.get_channel(int(data['channel_id']))
            guild = None
        else:
            channel = guild and guild.get_channel(int(data['channel_id']))

        return channel, guild

    async def request_offline_members(self, guilds):
        # get all the chunks
        chunks = []
        for guild in guilds:
            chunks.extend(self.chunks_needed(guild))

        # we only want to request ~75 guilds per chunk request.
        splits = [guilds[i:i + 75] for i in range(0, len(guilds), 75)]
        for split in splits:
            await self.chunker(split)

        # wait for the chunks
        if chunks:
            try:
                await utils.sane_wait_for(chunks,
                                          timeout=len(chunks) * 30.0,
                                          loop=self.loop)
            except asyncio.TimeoutError:
                log.info('Somehow timed out waiting for chunks.')

    async def _delay_ready(self):
        try:
            launch = self._ready_state.launch

            # only real bots wait for GUILD_CREATE streaming
            if self.is_bot:
                while not launch.is_set():
                    # this snippet of code is basically waiting 2 seconds
                    # until the last GUILD_CREATE was sent
                    launch.set()
                    await asyncio.sleep(2, loop=self.loop)

            guilds = self._ready_state.guilds
            if self._fetch_offline:
                await self.request_offline_members(guilds)

            # remove the state
            try:
                del self._ready_state
            except AttributeError:
                pass  # already been deleted somehow

            # call GUILD_SYNC after we're done chunking
            if not self.is_bot:
                log.info('Requesting GUILD_SYNC for %s guilds',
                         len(self.guilds))
                await self.syncer([s.id for s in self.guilds])
        except asyncio.CancelledError:
            pass
        else:
            # dispatch the event
            self.dispatch('ready')
        finally:
            self._ready_task = None

    def parse_ready(self, data):
        if self._ready_task is not None:
            self._ready_task.cancel()

        self._ready_state = ReadyState(launch=asyncio.Event(), guilds=[])
        self.clear()
        self.user = ClientUser(state=self, data=data['user'])

        guilds = self._ready_state.guilds
        for guild_data in data['guilds']:
            guild = self._add_guild_from_data(guild_data)
            if (not self.is_bot and not guild.unavailable) or guild.large:
                guilds.append(guild)

        for relationship in data.get('relationships', []):
            try:
                r_id = int(relationship['id'])
            except KeyError:
                continue
            else:
                self.user._relationships[r_id] = Relationship(
                    state=self, data=relationship)

        for pm in data.get('private_channels', []):
            factory, _ = _channel_factory(pm['type'])
            self._add_private_channel(
                factory(me=self.user, data=pm, state=self))

        self.dispatch('connect')
        self._ready_task = asyncio.ensure_future(self._delay_ready(),
                                                 loop=self.loop)

    def parse_resumed(self, data):
        self.dispatch('resumed')

    def parse_message_create(self, data):
        channel, _ = self._get_guild_channel(data)
        message = Message(channel=channel, data=data, state=self)
        self.dispatch('message', message)
        self._messages.append(message)

    def parse_message_delete(self, data):
        raw = RawMessageDeleteEvent(data)
        self.dispatch('raw_message_delete', raw)

        found = self._get_message(raw.message_id)
        if found is not None:
            self.dispatch('message_delete', found)
            self._messages.remove(found)

    def parse_message_delete_bulk(self, data):
        raw = RawBulkMessageDeleteEvent(data)
        self.dispatch('raw_bulk_message_delete', raw)

        to_be_deleted = [
            message for message in self._messages
            if message.id in raw.message_ids
        ]
        for msg in to_be_deleted:
            self.dispatch('message_delete', msg)
            self._messages.remove(msg)

    def parse_message_update(self, data):
        raw = RawMessageUpdateEvent(data)
        self.dispatch('raw_message_edit', raw)
        message = self._get_message(raw.message_id)
        if message is not None:
            older_message = copy.copy(message)
            if 'call' in data:
                # call state message edit
                message._handle_call(data['call'])
            elif 'content' not in data:
                # embed only edit
                message.embeds = [Embed.from_data(d) for d in data['embeds']]
            else:
                message._update(channel=message.channel, data=data)

            self.dispatch('message_edit', older_message, message)

    def parse_message_reaction_add(self, data):
        emoji_data = data['emoji']
        emoji_id = utils._get_as_snowflake(emoji_data, 'id')
        emoji = PartialEmoji(animated=emoji_data.get('animated', False),
                             id=emoji_id,
                             name=emoji_data['name'])
        raw = RawReactionActionEvent(data, emoji)
        self.dispatch('raw_reaction_add', raw)

        # rich interface here
        message = self._get_message(raw.message_id)
        if message is not None:
            emoji = self._upgrade_partial_emoji(emoji)
            reaction = message._add_reaction(data, emoji, raw.user_id)
            user = self._get_reaction_user(message.channel, raw.user_id)
            if user:
                self.dispatch('reaction_add', reaction, user)

    def parse_message_reaction_remove_all(self, data):
        raw = RawReactionClearEvent(data)
        self.dispatch('raw_reaction_clear', raw)

        message = self._get_message(raw.message_id)
        if message is not None:
            old_reactions = message.reactions.copy()
            message.reactions.clear()
            self.dispatch('reaction_clear', message, old_reactions)

    def parse_message_reaction_remove(self, data):
        emoji_data = data['emoji']
        emoji_id = utils._get_as_snowflake(emoji_data, 'id')
        emoji = PartialEmoji(animated=emoji_data.get('animated', False),
                             id=emoji_id,
                             name=emoji_data['name'])
        raw = RawReactionActionEvent(data, emoji)
        self.dispatch('raw_reaction_remove', raw)

        message = self._get_message(raw.message_id)
        if message is not None:
            emoji = self._upgrade_partial_emoji(emoji)
            try:
                reaction = message._remove_reaction(data, emoji, raw.user_id)
            except (AttributeError,
                    ValueError) as e:  # eventual consistency lol
                pass
            else:
                user = self._get_reaction_user(message.channel, raw.user_id)
                if user:
                    self.dispatch('reaction_remove', reaction, user)

    def parse_presence_update(self, data):
        guild_id = utils._get_as_snowflake(data, 'guild_id')
        guild = self._get_guild(guild_id)
        if guild is None:
            log.warning(
                'PRESENCE_UPDATE referencing an unknown guild ID: %s. Discarding.',
                guild_id)
            return

        user = data['user']
        member_id = int(user['id'])
        member = guild.get_member(member_id)
        if member is None:
            if 'username' not in user:
                # sometimes we receive 'incomplete' member data post-removal.
                # skip these useless cases.
                return

            member = Member(guild=guild, data=data, state=self)
            guild._add_member(member)

        old_member = member._copy()
        member._presence_update(data=data, user=user)
        self.dispatch('member_update', old_member, member)

    def parse_user_update(self, data):
        self.user = ClientUser(state=self, data=data)

    def parse_channel_delete(self, data):
        guild = self._get_guild(utils._get_as_snowflake(data, 'guild_id'))
        channel_id = int(data['id'])
        if guild is not None:
            channel = guild.get_channel(channel_id)
            if channel is not None:
                guild._remove_channel(channel)
                self.dispatch('guild_channel_delete', channel)
        else:
            # the reason we're doing this is so it's also removed from the
            # private channel by user cache as well
            channel = self._get_private_channel(channel_id)
            if channel is not None:
                self._remove_private_channel(channel)
                self.dispatch('private_channel_delete', channel)

    def parse_channel_update(self, data):
        channel_type = try_enum(ChannelType, data.get('type'))
        channel_id = int(data['id'])
        if channel_type is ChannelType.group:
            channel = self._get_private_channel(channel_id)
            old_channel = copy.copy(channel)
            channel._update_group(data)
            self.dispatch('private_channel_update', old_channel, channel)
            return

        guild_id = utils._get_as_snowflake(data, 'guild_id')
        guild = self._get_guild(guild_id)
        if guild is not None:
            channel = guild.get_channel(channel_id)
            if channel is not None:
                old_channel = copy.copy(channel)
                channel._update(guild, data)
                self.dispatch('guild_channel_update', old_channel, channel)
            else:
                log.warning(
                    'CHANNEL_UPDATE referencing an unknown channel ID: %s. Discarding.',
                    channel_id)
        else:
            log.warning(
                'CHANNEL_UPDATE referencing an unknown guild ID: %s. Discarding.',
                guild_id)

    def parse_channel_create(self, data):
        factory, ch_type = _channel_factory(data['type'])
        if factory is None:
            log.warning(
                'CHANNEL_CREATE referencing an unknown channel type %s. Discarding.',
                data['type'])
            return

        channel = None

        if ch_type in (ChannelType.group, ChannelType.private):
            channel_id = int(data['id'])
            if self._get_private_channel(channel_id) is None:
                channel = factory(me=self.user, data=data, state=self)
                self._add_private_channel(channel)
                self.dispatch('private_channel_create', channel)
        else:
            guild_id = utils._get_as_snowflake(data, 'guild_id')
            guild = self._get_guild(guild_id)
            if guild is not None:
                channel = factory(guild=guild, state=self, data=data)
                guild._add_channel(channel)
                self.dispatch('guild_channel_create', channel)
            else:
                log.warning(
                    'CHANNEL_CREATE referencing an unknown guild ID: %s. Discarding.',
                    guild_id)
                return

    def parse_channel_pins_update(self, data):
        channel_id = int(data['channel_id'])
        channel = self.get_channel(channel_id)
        if channel is None:
            log.warning(
                'CHANNEL_PINS_UPDATE referencing an unknown channel ID: %s. Discarding.',
                channel_id)
            return

        last_pin = utils.parse_time(
            data['last_pin_timestamp']) if data['last_pin_timestamp'] else None

        try:
            # I have not imported discord.abc in this file
            # the isinstance check is also 2x slower than just checking this attribute
            # so we're just gonna check it since it's easier and faster and lazier
            channel.guild
        except AttributeError:
            self.dispatch('private_channel_pins_update', channel, last_pin)
        else:
            self.dispatch('guild_channel_pins_update', channel, last_pin)

    def parse_channel_recipient_add(self, data):
        channel = self._get_private_channel(int(data['channel_id']))
        user = self.store_user(data['user'])
        channel.recipients.append(user)
        self.dispatch('group_join', channel, user)

    def parse_channel_recipient_remove(self, data):
        channel = self._get_private_channel(int(data['channel_id']))
        user = self.store_user(data['user'])
        try:
            channel.recipients.remove(user)
        except ValueError:
            pass
        else:
            self.dispatch('group_remove', channel, user)

    def parse_guild_member_add(self, data):
        guild = self._get_guild(int(data['guild_id']))
        if guild is None:
            log.warning(
                'GUILD_MEMBER_ADD referencing an unknown guild ID: %s. Discarding.',
                data['guild_id'])
            return

        member = Member(guild=guild, data=data, state=self)
        guild._add_member(member)
        guild._member_count += 1
        self.dispatch('member_join', member)

    def parse_guild_member_remove(self, data):
        guild = self._get_guild(int(data['guild_id']))
        if guild is not None:
            user_id = int(data['user']['id'])
            member = guild.get_member(user_id)
            if member is not None:
                guild._remove_member(member)
                guild._member_count -= 1
                self.dispatch('member_remove', member)
        else:
            log.warning(
                'GUILD_MEMBER_REMOVE referencing an unknown guild ID: %s. Discarding.',
                data['guild_id'])

    def parse_guild_member_update(self, data):
        guild = self._get_guild(int(data['guild_id']))
        user = data['user']
        user_id = int(user['id'])
        if guild is None:
            log.warning(
                'GUILD_MEMBER_UPDATE referencing an unknown guild ID: %s. Discarding.',
                data['guild_id'])
            return

        member = guild.get_member(user_id)
        if member is not None:
            old_member = copy.copy(member)
            member._update(data, user)
            self.dispatch('member_update', old_member, member)
        else:
            log.warning(
                'GUILD_MEMBER_UPDATE referencing an unknown member ID: %s. Discarding.',
                user_id)

    def parse_guild_emojis_update(self, data):
        guild = self._get_guild(int(data['guild_id']))
        if guild is None:
            log.warning(
                'GUILD_EMOJIS_UPDATE referencing an unknown guild ID: %s. Discarding.',
                data['guild_id'])
            return

        before_emojis = guild.emojis
        for emoji in before_emojis:
            self._emojis.pop(emoji.id, None)
        guild.emojis = tuple(
            map(lambda d: self.store_emoji(guild, d), data['emojis']))
        self.dispatch('guild_emojis_update', guild, before_emojis,
                      guild.emojis)

    def _get_create_guild(self, data):
        if data.get('unavailable') == False:
            # GUILD_CREATE with unavailable in the response
            # usually means that the guild has become available
            # and is therefore in the cache
            guild = self._get_guild(int(data['id']))
            if guild is not None:
                guild.unavailable = False
                guild._from_data(data)
                return guild

        return self._add_guild_from_data(data)

    async def _chunk_and_dispatch(self, guild, unavailable):
        chunks = list(self.chunks_needed(guild))
        await self.chunker(guild)
        if chunks:
            try:
                await utils.sane_wait_for(chunks,
                                          timeout=len(chunks),
                                          loop=self.loop)
            except asyncio.TimeoutError:
                log.info('Somehow timed out waiting for chunks.')

        if unavailable == False:
            self.dispatch('guild_available', guild)
        else:
            self.dispatch('guild_join', guild)

    def parse_guild_create(self, data):
        unavailable = data.get('unavailable')
        if unavailable == True:
            # joined a guild with unavailable == True so..
            return

        guild = self._get_create_guild(data)

        # check if it requires chunking
        if guild.large:
            if unavailable == False:
                # check if we're waiting for 'useful' READY
                # and if we are, we don't want to dispatch any
                # event such as guild_join or guild_available
                # because we're still in the 'READY' phase. Or
                # so we say.
                try:
                    state = self._ready_state
                    state.launch.clear()
                    state.guilds.append(guild)
                except AttributeError:
                    # the _ready_state attribute is only there during
                    # processing of useful READY.
                    pass
                else:
                    return

            # since we're not waiting for 'useful' READY we'll just
            # do the chunk request here if wanted
            if self._fetch_offline:
                asyncio.ensure_future(self._chunk_and_dispatch(
                    guild, unavailable),
                                      loop=self.loop)
                return

        # Dispatch available if newly available
        if unavailable == False:
            self.dispatch('guild_available', guild)
        else:
            self.dispatch('guild_join', guild)

    def parse_guild_sync(self, data):
        guild = self._get_guild(int(data['id']))
        guild._sync(data)

    def parse_guild_update(self, data):
        guild = self._get_guild(int(data['id']))
        if guild is not None:
            old_guild = copy.copy(guild)
            guild._from_data(data)
            self.dispatch('guild_update', old_guild, guild)
        else:
            log.warning(
                'GUILD_UPDATE referencing an unknown guild ID: %s. Discarding.',
                data['id'])

    def parse_guild_delete(self, data):
        guild = self._get_guild(int(data['id']))
        if guild is None:
            log.warning(
                'GUILD_DELETE referencing an unknown guild ID: %s. Discarding.',
                data['id'])
            return

        if data.get('unavailable', False) and guild is not None:
            # GUILD_DELETE with unavailable being True means that the
            # guild that was available is now currently unavailable
            guild.unavailable = True
            self.dispatch('guild_unavailable', guild)
            return

        # do a cleanup of the messages cache
        self._messages = deque(
            (msg for msg in self._messages if msg.guild != guild),
            maxlen=self.max_messages)

        self._remove_guild(guild)
        self.dispatch('guild_remove', guild)

    def parse_guild_ban_add(self, data):
        # we make the assumption that GUILD_BAN_ADD is done
        # before GUILD_MEMBER_REMOVE is called
        # hence we don't remove it from cache or do anything
        # strange with it, the main purpose of this event
        # is mainly to dispatch to another event worth listening to for logging
        guild = self._get_guild(int(data['guild_id']))
        if guild is not None:
            try:
                user = User(data=data['user'], state=self)
            except KeyError:
                pass
            else:
                member = guild.get_member(user.id) or user
                self.dispatch('member_ban', guild, member)

    def parse_guild_ban_remove(self, data):
        guild = self._get_guild(int(data['guild_id']))
        if guild is not None:
            if 'user' in data:
                user = self.store_user(data['user'])
                self.dispatch('member_unban', guild, user)

    def parse_guild_role_create(self, data):
        guild = self._get_guild(int(data['guild_id']))
        if guild is None:
            log.warning(
                'GUILD_ROLE_CREATE referencing an unknown guild ID: %s. Discarding.',
                data['guild_id'])
            return

        role_data = data['role']
        role = Role(guild=guild, data=role_data, state=self)
        guild._add_role(role)
        self.dispatch('guild_role_create', role)

    def parse_guild_role_delete(self, data):
        guild = self._get_guild(int(data['guild_id']))
        if guild is not None:
            role_id = int(data['role_id'])
            role = utils.find(lambda r: r.id == role_id, guild.roles)
            try:
                guild._remove_role(role)
            except ValueError:
                return
            else:
                self.dispatch('guild_role_delete', role)
        else:
            log.warning(
                'GUILD_ROLE_DELETE referencing an unknown guild ID: %s. Discarding.',
                data['guild_id'])

    def parse_guild_role_update(self, data):
        guild = self._get_guild(int(data['guild_id']))
        if guild is not None:
            role_data = data['role']
            role_id = int(role_data['id'])
            role = utils.find(lambda r: r.id == role_id, guild.roles)
            if role is not None:
                old_role = copy.copy(role)
                role._update(role_data)
                self.dispatch('guild_role_update', old_role, role)
        else:
            log.warning(
                'GUILD_ROLE_UPDATE referencing an unknown guild ID: %s. Discarding.',
                data['guild_id'])

    def parse_guild_members_chunk(self, data):
        guild_id = int(data['guild_id'])
        guild = self._get_guild(guild_id)
        members = data.get('members', [])
        for member in members:
            m = Member(guild=guild, data=member, state=self)
            existing = guild.get_member(m.id)
            if existing is None or existing.joined_at is None:
                guild._add_member(m)

        log.info('Processed a chunk for %s members in guild ID %s.',
                 len(members), guild_id)
        self.process_listeners(ListenerType.chunk, guild, len(members))

    def parse_voice_state_update(self, data):
        guild = self._get_guild(utils._get_as_snowflake(data, 'guild_id'))
        channel_id = utils._get_as_snowflake(data, 'channel_id')
        if guild is not None:
            if int(data['user_id']) == self.user.id:
                voice = self._get_voice_client(guild.id)
                if voice is not None:
                    ch = guild.get_channel(channel_id)
                    if ch is not None:
                        voice.channel = ch

            member, before, after = guild._update_voice_state(data, channel_id)
            if member is not None:
                self.dispatch('voice_state_update', member, before, after)
            else:
                log.warning(
                    'VOICE_STATE_UPDATE referencing an unknown member ID: %s. Discarding.',
                    data['user_id'])
        else:
            # in here we're either at private or group calls
            call = self._calls.get(channel_id)
            if call is not None:
                call._update_voice_state(data)

    def parse_voice_server_update(self, data):
        try:
            key_id = int(data['guild_id'])
        except KeyError:
            key_id = int(data['channel_id'])

        vc = self._get_voice_client(key_id)
        if vc is not None:
            asyncio.ensure_future(vc._create_socket(key_id, data))

    def parse_typing_start(self, data):
        channel, guild = self._get_guild_channel(data)
        if channel is not None:
            member = None
            user_id = utils._get_as_snowflake(data, 'user_id')
            if isinstance(channel, DMChannel):
                member = channel.recipient
            elif isinstance(channel, TextChannel):
                member = guild.get_member(user_id)
            elif isinstance(channel, GroupChannel):
                member = utils.find(lambda x: x.id == user_id,
                                    channel.recipients)

            if member is not None:
                timestamp = datetime.datetime.utcfromtimestamp(
                    data.get('timestamp'))
                self.dispatch('typing', channel, member, timestamp)

    def parse_relationship_add(self, data):
        key = int(data['id'])
        old = self.user.get_relationship(key)
        new = Relationship(state=self, data=data)
        self.user._relationships[key] = new
        if old is not None:
            self.dispatch('relationship_update', old, new)
        else:
            self.dispatch('relationship_add', new)

    def parse_relationship_remove(self, data):
        key = int(data['id'])
        try:
            old = self.user._relationships.pop(key)
        except KeyError:
            pass
        else:
            self.dispatch('relationship_remove', old)

    def _get_reaction_user(self, channel, user_id):
        if isinstance(channel, TextChannel):
            return channel.guild.get_member(user_id)
        return self.get_user(user_id)

    def get_reaction_emoji(self, data):
        emoji_id = utils._get_as_snowflake(data, 'id')

        if not emoji_id:
            return data['name']

        try:
            return self._emojis[emoji_id]
        except KeyError:
            return PartialEmoji(animated=data.get('animated', False),
                                id=emoji_id,
                                name=data['name'])

    def _upgrade_partial_emoji(self, emoji):
        emoji_id = emoji.id
        if not emoji_id:
            return emoji.name
        try:
            return self._emojis[emoji_id]
        except KeyError:
            return emoji

    def get_channel(self, id):
        if id is None:
            return None

        pm = self._get_private_channel(id)
        if pm is not None:
            return pm

        for guild in self.guilds:
            channel = guild.get_channel(id)
            if channel is not None:
                return channel

    def create_message(self, *, channel, data):
        return Message(state=self, channel=channel, data=data)

    def receive_chunk(self, guild_id):
        future = self.loop.create_future()
        listener = Listener(ListenerType.chunk, future,
                            lambda s: s.id == guild_id)
        self._listeners.append(listener)
        return future
Пример #41
0
class FontConfig(object):
    def __init__(self):
        self._fontconfig = self._load_fontconfig_library()
        self._search_cache = OrderedDict()
        self._cache_size = 20

    def dispose(self):
        while len(self._search_cache) > 0:
            self._search_cache.popitem().dispose()

        self._fontconfig.FcFini()
        self._fontconfig = None

    def create_search_pattern(self):
        return FontConfigSearchPattern(self._fontconfig)

    def find_font(self, name, size=12, bold=False, italic=False):
        result = self._get_from_search_cache(name, size, bold, italic)
        if result:
            return result

        search_pattern = self.create_search_pattern()
        search_pattern.name = name
        search_pattern.size = size
        search_pattern.bold = bold
        search_pattern.italic = italic

        result = search_pattern.match()
        self._add_to_search_cache(search_pattern, result)
        return result

    def have_font(self, name):
        result = self.find_font(name)
        if result:
            # Check the name matches, fontconfig can return a default
            if name and result.name and result.name.lower() != name.lower():
                return False
            return True
        else:
            return False

    def char_index(self, ft_face, character):
        return self._fontconfig.FcFreeTypeCharIndex(ft_face, ord(character))

    def _add_to_search_cache(self, search_pattern, result_pattern):
        self._search_cache[(search_pattern.name, search_pattern.size,
                            search_pattern.bold,
                            search_pattern.italic)] = result_pattern
        if len(self._search_cache) > self._cache_size:
            self._search_cache.popitem(last=False)[1].dispose()

    def _get_from_search_cache(self, name, size, bold, italic):
        result = self._search_cache.get((name, size, bold, italic), None)

        if result and result.is_valid:
            return result
        else:
            return None

    @staticmethod
    def _load_fontconfig_library():
        fontconfig = pyglet.lib.load_library('fontconfig')
        fontconfig.FcInit()

        fontconfig.FcPatternBuild.restype = c_void_p
        fontconfig.FcPatternCreate.restype = c_void_p
        fontconfig.FcFontMatch.restype = c_void_p
        fontconfig.FcFreeTypeCharIndex.restype = c_uint

        fontconfig.FcPatternAddDouble.argtypes = [c_void_p, c_char_p, c_double]
        fontconfig.FcPatternAddInteger.argtypes = [c_void_p, c_char_p, c_int]
        fontconfig.FcPatternAddString.argtypes = [c_void_p, c_char_p, c_char_p]
        fontconfig.FcConfigSubstitute.argtypes = [c_void_p, c_void_p, c_int]
        fontconfig.FcDefaultSubstitute.argtypes = [c_void_p]
        fontconfig.FcFontMatch.argtypes = [c_void_p, c_void_p, c_void_p]
        fontconfig.FcPatternDestroy.argtypes = [c_void_p]

        fontconfig.FcPatternGetFTFace.argtypes = [
            c_void_p, c_char_p, c_int, c_void_p
        ]
        fontconfig.FcPatternGet.argtypes = [
            c_void_p, c_char_p, c_int, c_void_p
        ]

        return fontconfig
Пример #42
0
class FIFODictOrderedDict:
    """A simple FIFO mapping between keys and values. Implemented using an
       OrderedDict. When the max. capacity is reached, the key/value pair that
       has been in the dict the longest time is removed.
    """
    def __init__(self, size, finalizer=None):
        """Create a FIFODictOrderedDict with the given maximum size.

           Arguments:
           - size: Determines the maximum size of the dict.
           - finalizer: If finalizer is given, it must be a callable
             f(key, value). It is then called, when a item is removed due to
             the size of the dict reaching the maximum (finalizer is NOT called
             when an item is explicitly deleted with del d[key] or when the
             dict is cleared).
        """
        if not isinstance(size, type(0)):
            raise TypeError("size must be an int")
        if not size > 0:
            raise ValueError("size must be positive")
        if finalizer is not None and not callable(finalizer):
            raise TypeError("finalizer must be None or a callable")

        self.__size = size
        self.__data = OrderedDict()
        self.__finalizer = finalizer

    def add(self, key, val):
        """Add a key/value pair to the dict.

           If a pair p with the same key already exists, p is replaced by the
           new pair n, but n gets p's position in the FIFO dict and is deleted
           when the old pair p would have been deleted. When the maximum
           capacity is reached, the pair with the oldest key is deleted
           from the dict.

           The argument key is the key and the argument val is the value.
        """
        if key in self.__data:
            self.__data[key] = val  # Replace old value
        elif len(self.__data) < self.__size:
            # The dict is not full yet. Just add the new pair.
            self.__data[key] = val
        else:
            # The dict is full. We have to delete the oldest item first.
            if self.__finalizer:
                (delKey, delValue) = self.__data.popitem(last=False)
                self.__finalizer(delKey, delValue)
            else:
                self.__data.popitem(last=False)
            self.__data[key] = val

    def get(self, key, default=None):
        """Find and return the element a given key maps to.

           Look for the given key in the dict and return the associated value
           if found. If not found, the value of default is returned.
        """
        return self.__data.get(key, default)

    def clear(self):
        """Delete all key/value pairs from the dict"""
        self.__data = OrderedDict()

    def __setitem__(self, key, item):
        self.add(key, item)

    def __getitem__(self, key):
        return self.__data[key]

    def __len__(self):
        return len(self.__data)

    def __str__(self):
        allitems = []
        for key in self.__data:
            val = self.__data[key]
            item = "%s: %s" % (str(key), str(val))
            allitems.append(item)
        return "{%s}" % ", ".join(allitems)

    def __contains__(self, item):
        return (item in self.__data)

    def __delitem__(self, item):
        if item not in self.__data:
            raise KeyError(item)

        del self.__data[item]

    def __iter__(self):
        for k in self.__data:
            yield k
Пример #43
0
class Cache(object):
    def __init__(self, name, max_entries=1000, keylen=1, lru=False):
        if lru:
            self.cache = LruCache(max_size=max_entries)
            self.max_entries = None
        else:
            self.cache = OrderedDict()
            self.max_entries = max_entries

        self.name = name
        self.keylen = keylen
        self.sequence = 0
        self.thread = None
        caches_by_name[name] = self.cache

    def check_thread(self):
        expected_thread = self.thread
        if expected_thread is None:
            self.thread = threading.current_thread()
        else:
            if expected_thread is not threading.current_thread():
                raise ValueError(
                    "Cache objects can only be accessed from the main thread")

    def get(self, *keyargs):
        if len(keyargs) != self.keylen:
            raise ValueError("Expected a key to have %d items", self.keylen)

        if keyargs in self.cache:
            cache_counter.inc_hits(self.name)
            return self.cache[keyargs]

        cache_counter.inc_misses(self.name)
        raise KeyError()

    def update(self, sequence, *args):
        self.check_thread()
        if self.sequence == sequence:
            # Only update the cache if the caches sequence number matches the
            # number that the cache had before the SELECT was started (SYN-369)
            self.prefill(*args)

    def prefill(self, *args):  # because I can't  *keyargs, value
        keyargs = args[:-1]
        value = args[-1]

        if len(keyargs) != self.keylen:
            raise ValueError("Expected a key to have %d items", self.keylen)

        if self.max_entries is not None:
            while len(self.cache) >= self.max_entries:
                self.cache.popitem(last=False)

        self.cache[keyargs] = value

    def invalidate(self, *keyargs):
        self.check_thread()
        if len(keyargs) != self.keylen:
            raise ValueError("Expected a key to have %d items", self.keylen)
        # Increment the sequence number so that any SELECT statements that
        # raced with the INSERT don't update the cache (SYN-369)
        self.sequence += 1
        self.cache.pop(keyargs, None)

    def invalidate_all(self):
        self.check_thread()
        self.sequence += 1
        self.cache.clear()
Пример #44
0
class Domains(object):

	def __init__(self, master):
		self.master = master
		self.log = master.log
		self.domain = master.mongo.domain
		self.catecory = master.mongo.catecory
		self.template = master.mongo.template
		self.article = master.mongo.spider_article
		self.exc_article = master.mongo.spider_exc
		self.html_file = master.mongo.html_file
		self.url_redis = redis.Redis(**master.conf.redis_url)
		self.domains = PQDict(key=lambda x: x.value.domain['_id'])
		self.fetching = dict()
		self.waiting = OrderedDict()
		self.doing = dict()
		self.sync_round = 1800
		self.last = -1

		master.fetch_adapter.register(['cate','art','page','img'], 
			self.fetch_get, self.fetch, self.fetch_cancel)
		master.handle_adapter.register(['cate'], 
			self.handle_get, self.handle, self.handle_cancel)

	@property
	def counter(self):
		res = {
			'fetch':len(self.fetching), 
			'domain_wait':len(self.waiting),
			'domain_doing':len(self.doing),
			'fetch_cate':0,
			'fetch_art':0,
			'fetch_img':0,
			'fetch_page':0,
		}
		for cmd, _ in self.fetching.itervalues():
			res['fetch_' + cmd] += 1
		return res

	def is_fetching(self, key):
		return key in self.fetching

	def is_doing(self, key):
		return key in self.fetching \
			or key in self.waiting \
			or key in self.doing

	def sync(self, quit=False):
		self.sync_last(quit)
		self.sync_other(quit)

	def sync_last(self, quit):
		if not quit and self.sync_round > time.time() - self.last:
			return

		last = time.time()
		domains, tpls = {}, {}

		for domain in self.domains:
			domains.update(domain.back(self.last, last))
			tpls.update(domain.tpls.back(self.last, last))

		if not quit:
			self.load_domains(self.last, last)
			self.load_tpls(self.last, last)

		for domain in domains.itervalues():
			self.domain.save(domain)
		for tpl in tpls.itervalues():
			self.template.save(tpl)

		self.last = last

	def sync_other(self, quit):
		for domain in self.domains:
			domain.sync(quit)
		self.domains.heapify()

	def load_domains(self, start, end):
		doc = {'status':'common', 'last':{'$gt':start, '$lte':end}}
		domains = self.domain.find(doc)
		for domain in domains:
			if domain['_id'] not in self.domains:
				xdomain = Domain(self, domain)
				self.domains.put(xdomain)
				if start > 0:
					xdomain.load()
			else:
				self.domains[domain['_id']].update(domain)
		if domains.count() > 0:
			self.log.info('load %d domains.' % domains.count())

	def load_tpls(self, start, end):
		doc = {'status':'common', 'last':{'$gt':start, '$lte':end}}
		tpls = self.template.find(doc)
		for tpl in tpls:
			with self.domains.get2do(tpl['domain']) as domain:
				domain.tpls.put(tpl)

		if tpls.count > 0:
			self.log.info('load %d tpls.' % tpls.count())

	def add_url(self, key, domain):
		return self.url_redis.sadd(domain, key)

	def has_url(self, key, domain):
		return self.url_redis.sismember(domain, key)

	def selector(self, domain, tpl):
		if domain in self.domains:
			return self.domains[domain].tpls.selector(tpl)
		return {}

	def new_arts(self, article, urls):
		with self.domains.get2do(article['domain']) as domain:
			return domain.new_arts(urls, 'art', article)
		return 0

	def fetch_page(self, page):
		with self.domains.get2do(page['domain']) as domain:
			return domain.pages.put(page)
		return False

	def fetch_img(self, img):
		with self.domains.get2do(img['domain']) as domain:
			return domain.imgs.put(img)
		return False

	def new_handle(self, key, value):
		self.waiting[key] = value

	def quit(self):
		for cmd, task in self.fetching.itervalues():
			self.domains[task['domain']].cancel(cmd, task)
		self.fetching.clear()

		for cmd, task, _ in self.waiting.itervalues():
			self.domains[task['domain']].cancel(cmd, task)
		self.waiting.clear()

		for cmd, task in self.doing.itervalues():
			self.domains[task['domain']].cancel(cmd, task)
		self.doing.clear()

	def fetch_get(self, count):
		tasks = []
		if not self.domains:
			return tasks

		null = 0
		for _ in xrange(count):
			cmd, task = None, None
			with self.domains.get2do() as domain:
				cmd, task = domain.get()

			if not task:
				null += 1
				if null >= 5:
					break
				self.domains.heapify()
				continue
				
			tasks.append({'key':task['_id'], 'cmd':cmd, 'info':task})
			self.fetching[task['_id']] = (cmd, task)

		return tasks

	def fetch_cancel(self, key, cmd):
		if key in self.fetching:
			cmd, task = self.fetching.pop(key)
			with self.domains.get2do(task['domain']) as domain:
				domain.cancel(cmd, task)

	def fetch(self, key, cmd, res):
		if key in self.fetching:
			cmd, task = self.fetching.pop(key)
			with self.domains.get2do(task['domain']) as domain:
				domain.fetch(cmd, task, res)
				
	def handle_get(self, count, **kwargs):
		tasks = []
		for _ in xrange(min(len(self.waiting), count)):
			cmd, task, ext = self.waiting.popitem()[1]
			tasks.append({'key':task['_id'], 'cmd':cmd, 'info':task, 'ext':ext})
			self.doing[task['_id']] = (cmd, task)
		return tasks

	def handle_cancel(self, key, cmd):
		if key in self.doing:
			cmd, task = self.doing.pop(key)
			with self.domains.get2do(task['domain']) as domain:
				domain.cancel(cmd, task)

	def handle(self, key, cmd, res):
		if key in self.doing:
			cmd, task = self.doing.pop(key)
			with self.domains.get2do(task['domain']) as domain:
				domain.handle(cmd, task, res)
Пример #45
0
class UVar(object):
    """
    A class to hold a variable associated with the UGrid. Data can be on the
    nodes, edges, etc. -- "UGrid Variable"

    It holds an array of the data, as well as the attributes associated
    with that data  -- this is mapped to a netcdf variable with
    attributes(attributes get stored in the netcdf file)
    """
    def __init__(self, name, location, data=None, attributes=None):
        """
        create a UVar object
        :param name: the name of the variable (depth, u_velocity, etc.)
        :type name: string

        :param location: the type of grid element the data is associated with:
                         'node', 'edge', or 'face'

        :param data: The data itself
        :type data: 1-d numpy array or array-like object ().
                    If you have a list or tuple, it should be something that can be
                    converted to a numpy array (list, etc.)
        """
        self.name = name

        if location not in ['node', 'edge', 'face', 'boundary']:
            raise ValueError("location must be one of: "
                             "'node', 'edge', 'face', 'boundary'")

        self.location = location

        if data is None:
            # Could be any data type, but we'll default to float
            self._data = np.zeros((0, ), dtype=np.float64)
        else:
            self._data = asarraylike(data)

        # FixMe: we need a separate attribute dict -- we really do'nt want all this
        #        getting mixed up with the python object attributes
        self.attributes = {} if attributes is None else attributes
        # if the data is a netcdf variable, pull the attributes from there
        try:
            for attr in data.ncattrs():
                self.attributes[attr] = data.getncattr(attr)
        except AttributeError:  # must not be a netcdf variable
            pass

        self._cache = OrderedDict()

    # def update_attrs(self, attrs):
    #     """
    #     update the attributes of the UVar object

    #     :param attr: Dict containing attributes to be added to the object
    #     """
    #     for key, val in attrs.items():
    #         setattr(self, key, val)

    @property
    def data(self):
        """
        The data associated with the UVar -- a numpy array-like object with the actual data
        """
        return self._data

    @data.setter
    def data(self, data):
        self._data = asarraylike(data)

    @data.deleter
    def data(self):
        self._data = self._data = np.zeros((0, ), dtype=np.float64)

    @property
    def shape(self):
        """
        The shape of the data array associated with the UVar.
        """
        return self.data.shape

    @property
    def max(self):
        """ maximum value of the variable """
        return np.max(self._data)

    @property
    def min(self):
        """ minimum value of the variable """
        return np.min(self._data)

    @property
    def dtype(self):
        """ data type of the variable """
        return self.data.dtype

    @property
    def ndim(self):
        """ number of dimensions of the variable """
        return self.data.ndim

    def __getitem__(self, item):
        """
        Transfers responsibility to the data's __getitem__ if not cached
        """
        rv = None
        if str(item) in self._cache:
            rv = self._cache[str(item)]
        else:
            rv = self._data.__getitem__(item)
            self._cache[str(item)] = rv
            if len(self._cache) > 3:
                self._cache.popitem(last=False)
        return rv

    def __str__(self):
        print("in __str__, data is:", self.data)
        msg = ("UVar object: {0:s}, on the {1:s}s, and {2:d} data "
               "points\nAttributes: {3}").format
        return msg(self.name, self.location, len(self.data), self.attributes)

    def __len__(self):
        return len(self.data)
Пример #46
0
__author__ = 'rakesh'

#What is orderedDict
#An OrderedDict is a dict that remembers the order that keys were first inserted. If a new entry overwrites an existing entry, the original insertion position is left unchanged. Deleting an entry and reinserting it will move it to the end.

from collections import OrderedDict

LRUCache = OrderedDict()
count = 1
for i in [2, 4, 5, 6, 7, 9, 10]:
    LRUCache[i] = count
    count += 1

print LRUCache
LRUCache.popitem(last=False)
print LRUCache
# print LRUCache
#
# # del LRUCache[2]  #if you delete the old entry then you ened
# # LRUCache[2] = ""
# # print LRUCache
#
# #The best thing about orderedDict is that it remembers the order in which the keys are inserted. If the new entry overwrites and existing entry, the original insertion position will remain unchanged. Deleting an entry and reinseeting it will move to the end. This is really good for LRU Cache will deletes the entry
#
# #dictionary sorted by key
#
# LRUCache = sorted(LRUCache.items(), key= lambda t: t[1])
# print LRUCache  #It is really amazing that you can sort your LRUCache
#
# #there are lots of operation that you can perform
# # >>> # regular unsorted dictionary
Пример #47
0
class OrderedSet(object):
    def __init__(self, iterable=[]):
        self._dict = OrderedDict([(elem, True) for elem in iterable])

    def add(self, elem):
        self._dict[elem] = True

    def remove(self, elem):
        del self._dict[elem]

    def discard(self, elem):
        self._dict.pop(elem, None)

    def pop(self, last=True):
        return self._dict.popitem(last)[0]

    def clear(self):
        self._dict.clear()

    def copy(self):
        tmp = OrderedSet()
        tmp._dict = self._dict.copy()
        return tmp

    #--------------------------------------------------------------------------
    # Boolean set functions
    #--------------------------------------------------------------------------
    def isdisjoint(self, other):
        for elem in self._dict:
            if elem in other: return False
        for elem in other:
            if elem in self._dict: return False
        return True

    def issubset(self, other):
        for elem in self._dict:
            if elem not in other: return False
        return True

    def issuperset(self, other):
        for elem in other:
            if elem not in self._dict: return False
        return True

    # Since __eq__ will return False for two OrderedSets with same elements but
    # a different order so provide a separate function.
    def isequal(self, other):
        if not isinstance(other, self.__class__): return NotImplemented
        if len(self) != len(other): return False
        for elem in self._dict.keys():
            if elem not in other._dict: return False
        return True

    #--------------------------------------------------------------------------
    # Set operations
    #--------------------------------------------------------------------------
    def union(self, *others):
        tmp = self.copy()
        for other in others:
            if isinstance(other, self.__class__):
                tmp._dict.update(other._dict)
            else:
                tmp._dict.update({key: True for key in other})
        return tmp

    def intersection(self, *others):
        tmp = self.copy()
        if not others: return tmp
        tmp2 = set(self._dict.keys()).intersection(*others)
        for key in self._dict.keys():
            if key not in tmp2: tmp._dict.pop(key, None)
        return tmp

    def difference(self, *others):
        tmp = self.copy()
        if not others: return tmp
        tmp2 = set()
        tmp2.update(*others)
        for key in tmp2:
            tmp._dict.pop(key, None)
        return tmp

    def symmetric_difference(self, other):
        tmp = set(self._dict.keys())
        tmp.intersection_update(other)
        tmp2 = self.union(other)
        for key in tmp:
            del tmp2._dict[key]
        return tmp2

    def update(self, *others):
        for other in others:
            if isinstance(other, self.__class__):
                self._dict.update(other._dict)
            else:
                self._dict.update({key: True for key in other})

    def intersection_update(self, *others):
        if not others: return
        tmp = set(self._dict.keys())
        tmp2 = set(tmp).intersection(*others)
        for key in tmp:
            if key not in tmp2: del self._dict[key]

    def difference_update(self, *others):
        if not others: return
        tmp2 = set()
        tmp2.update(*others)
        for key in tmp2:
            self._dict.pop(key, None)

    def symmetric_difference_update(self, other):
        tmp = set(self._dict.keys())
        tmp.intersection_update(other)
        self.update(other)
        for key in tmp:
            del self._dict[key]

    #--------------------------------------------------------------------------
    # Special functions to support set and container operations
    #--------------------------------------------------------------------------

    def __contains__(self, elem):
        """Implemement set 'in' operator."""
        return elem in self._dict

    def __bool__(self):
        """Implemement set bool operator."""
        return bool(self._dict)

    def __len__(self):
        return len(self._dict)

    def __iter__(self):
        for k, v in self._dict.items():
            yield k

    def __eq__(self, other):
        # Not sure why this shouldn't raise a TypeError for set but I want the
        # behaviour to be consistent with standard set.
        """Overloaded boolean operator."""
        if isinstance(other, self.__class__):
            return self._dict == other._dict
        elif isinstance(other, set):
            if len(self) != len(other): return False
            if not self.issubset(other): return False
            return self.issuperset(other)
        return NotImplemented

    def __ne__(self, other):
        """Overloaded boolean operator."""
        result = self.__eq__(other)
        if result is NotImplemented: return NotImplemented
        return not result

    def __lt__(self, other):
        """Implemement set < operator."""
        if not isinstance(other, self.__class__) and \
           not isinstance(other, set):
            return NotImplemented
        return self <= other and self != other

    def __le__(self, other):
        """Implemement set <= operator."""
        if not isinstance(other, self.__class__) and \
           not isinstance(other, set):
            return NotImplemented
        return self.issubset(other)

    def __gt__(self, other):
        """Implemement set > operator."""
        if not isinstance(other, self.__class__) and \
           not isinstance(other, set):
            return NotImplemented
        return self >= other and self != other

    def __ge__(self, other):
        """Implemement set >= operator."""
        if not isinstance(other, self.__class__) and \
           not isinstance(other, set):
            return NotImplemented
        return self.issuperset(other)

    def __or__(self, other):
        """Implemement set | operator."""
        return self.union(other)

    def __and__(self, other):
        """Implemement set & operator."""
        return self.intersection(other)

    def __sub__(self, other):
        """Implemement set - operator."""
        return self.difference(other)

    def __xor__(self, other):
        """Implemement set ^ operator."""
        return self.symmetric_difference(other)

    def __ior__(self, other):
        """Implemement set |= operator."""
        self.update(other)
        return self

    def __iand__(self, other):
        """Implemement set &= operator."""
        self.intersection_update(other)
        return self

    def __isub__(self, other):
        """Implemement set -= operator."""
        self.difference_update(other)
        return self

    def __ixor__(self, other):
        """Implemement set ^= operator."""
        self.symmetric_difference_update(other)
        return self

    #--------------------------------------------------------------------------
    # String representation
    #--------------------------------------------------------------------------

    def __str__(self):
        if not self: return "set()"
        return "{" + ", ".join([repr(e) for e in self]) + "}"

    def __repr__(self):
        if not self: return "{}()".format(type(self).__name__)
        return self.__str__()
Пример #48
0
    if previous is not None and previous != data or len(tmp.keys()) == 0:
        f = SlmCcdbEntry(runStart, run - 1, previous)
        if len(tmp.keys()) == 0:
            f.runMax = None
        runStart = run
        print(f)
        f.writeFile(directory='./slm-data')
        fcmd.write(f.getCommand() + '\n')
    previous = data
fcmd.close()

###################################################################
###################################################################

fcmd = open('hwp2ccdb.sh', 'w')
runStart, hwpStart = hwpData.popitem(False)
while len(hwpData) > 0:
    run, hwp = hwpData.popitem(False)
    if hwp != hwpStart or len(hwpData) == 0:
        if hwp != hwpStart:
            runEnd = run - 1
        else:
            runEnd = run
        entry = HwpCcdbEntry(runStart, runEnd, data={'hwp': hwpStart})
        print(entry)
        entry.writeFile(directory='./hwp-data')
        fcmd.write(entry.getCommand() + '\n')
        runStart, hwpStart = run, hwp
fcmd.close()

print('')
Пример #49
0
class ConsistencyTestClass(object):
    """
    This class contains all the Fortran consistency check tests.
    The logs dictionary contains a deque object with a list of all source lines
    that fail a particular test (given as the logs key)
    """
    def __init__(self):
        self.logs = OrderedDict()

    ##############

    def process(self):
        """
        Check results from all tests that have been run:
        1. For each test:
            i.  log (as info) test description and number of lines of code that fail the test
            ii. log (as info) all lines of code that do not conform to standards
        2. return total number of errors across all tests
        """
        tot_err_cnt = 0
        while self.logs:
            desc, log = self.logs.popitem(last=False)
            err_cnt = len(log)
            LOGGER.info("* %s: %d error(s) found", desc, err_cnt)
            while log:
                msg = log.popleft()
                LOGGER.info("  %s", msg)
            tot_err_cnt += err_cnt
        return tot_err_cnt

    ##############

    def init_log(self, description):
        """
        If self.logs does not already have a key for description, set
        self.logs[description] to an empty deque list.
        """
        if description not in self.logs.keys():
            self.logs[description] = deque([])

    ##############

    def check_for_hard_tabs(self, file_and_line, line):
        """
        Log any lines containing hard tabs
        """
        test_desc = 'Check for hard tabs'
        self.init_log(test_desc)
        if "\t" in line:
            self.logs[test_desc].append(
                "%s: %s" % (file_and_line, line.replace("\t", 2 * UNIBLOCK)))

    ##############

    def check_for_trailing_whitespace(self, file_and_line, line):
        """
        Log any lines containing trailing whitespace
        """
        test_desc = 'Check for trailing white space'
        self.init_log(test_desc)
        full_line_len = len(line)
        no_trailing_space_len = len(line.rstrip(" "))
        if no_trailing_space_len < full_line_len:
            self.logs[test_desc].append(
                "%s: %s" %
                (file_and_line, line.rstrip(" ") +
                 (full_line_len - no_trailing_space_len) * UNIBLOCK))

    ##############

    def check_line_length(self,
                          file_and_line,
                          line,
                          comment_char="!",
                          max_len=132):
        """
        Log any lines exceeding max_len
        Currently ignores comment characters / anything following
        """
        test_desc = 'Check length of lines'
        self.init_log(test_desc)
        line_len = len(line.split(comment_char)[0].rstrip(" "))
        if line_len > max_len:
            self.logs[test_desc].append("%s: %s" %
                                        (file_and_line, line[:max_len] +
                                         (line_len - max_len) * UNIBLOCK))

    ##############

    def check_case_in_module_statements(self,
                                        file_and_line,
                                        line,
                                        comment_char="!"):
        """
        The following module statements should be all lowercase:
        * implicit none
        * public
        * private
        * save
        Note that at some point we may want to remove "save" altogether,
        since it is implicit in a module
        """
        test_desc = 'Check for case sensitive statements'
        self.init_log(test_desc)
        statements = ["implicit none", "public", "private", "save"]
        # ignore comments, and strip all white space
        line_without_comments = line.split(comment_char)[0].strip(" ")
        if line_without_comments.lower() in statements:
            if line_without_comments not in statements:
                self.logs[test_desc].append("%s: %s" % (file_and_line, line))

    ##############

    def check_for_spaces(self, file_and_line, line, comment_char="!"):
        """
        The following statements should all include spaces:
        * else if
        * end if
        * else where
        * end where
        * end do
        * end module
        """
        test_desc = 'Check for spaces in statements'
        self.init_log(test_desc)
        statements = [
            "elseif", "endif", "elsewhere", "endwhere", "enddo", "endmodule"
        ]
        # ignore comments, and strip all white space
        line_without_comments = line.split(comment_char)[0].strip(" ")
        for bad_statement in statements:
            if line_without_comments.lower().startswith(bad_statement):
                self.logs[test_desc].append(
                    "%s: %s" % (file_and_line, line_without_comments))
                break

    ##############

    def check_for_double_quotes(self, file_and_line, line):
        """
        All Fortran strings should appear as 'string', not "string"
        """
        test_desc = 'Check for double quotes in statements'
        self.init_log(test_desc)
        if '"' in line:
            self.logs[test_desc].append("%s: %s" % (file_and_line, line))

    ##############

    def check_logical_statements(self, file_and_line, line):
        """
        Use symbols, not words, for logical operators:
        * >=, not .ge.
        * >, not .gt.
        * <=, not .le.
        * <, not .lt.
        * ==, not .eq.
        * /=, not .ne.
        """
        test_desc = 'Check for unwanted logical operators'
        self.init_log(test_desc)
        operators = ['.ge.', '.gt.', '.le.', '.lt.', '.eq.', '.ne.']
        for operator in operators:
            if operator in line:
                self.logs[test_desc].append("%s: %s" % (file_and_line, line))
                break

    ##############

    def check_r8_settings(self, file_and_line, line, comment_char="!"):
        """
        Make sure all real numbers are cast as r8
        """
        test_desc = 'Check for r8'
        self.init_log(test_desc)
        import re
        # Looking for decimal numbers that do not end in _r8
        # Edge cases:
        # 1. ignore decimals in comments
        # 2. Ignore decimals in format strings (e.g. E24.16)
        # 3. Allow 1.0e-2_r8
        line_without_comments = line.split(comment_char)[0].strip(" ")

        # Regex notes
        # 1. (?<!\w) -- do not match numbers immediately following a letter,
        #    such as E24 or I0 (these are Fortran format strings)
        #    [regex refers to this as a negative lookbehind]
        # 2. \d+\. -- match N consecutive decimal digits (for N>=1) followed
        #    by a decimal point
        # 3. (\d+[eE]([+-])?)? -- Optionally match a number followed by either
        #    e or E (optionally followed by + or -)
        # 4. \d+ -- match N consecutive decimal digits (for N>=1)
        # 5. (?!\d+|_|[eE]) -- do not match a decimal, an underscore, an e,
        #    or an E
        #    [regex refers to this as a negative lookahead]
        regex = r'(?<!\w)\d+\.(\d+[eE]([+-])?)?\d+(?!\d+|_|[eE])'
        valid = re.compile(regex)
        if valid.search(line_without_comments):
            self.logs[test_desc].append("%s: %s" % (file_and_line, line))
Пример #50
0
class UMVar(object):
    """
    A class to group multiple UVars (or other data sources) and retrieve common information.
    All the variables grouped in this class must have the same shape, location, and unique
    names.

    TODO: Add attribues that all grouped variables have in common to the UMVar?
    """
    def __init__(self, name, location='none', data=None, attributes=None):
        """
        :param name: the name of the data (depth, u_velocity, etc.)
        :type name: string

        :param location: the type of grid element the data is associated with:
                         'node', 'edge', or 'face' the data is assigned to

        :param data: the data
        :type data: list-like of data sources that satisfy the conditions of util.asarraylike.
                    All data sources must have the same shape.
                    Examples: netCDF Dataset, numpy array
        """

        self.name = name

        if location not in ['node', 'edge', 'face', 'boundary', 'none']:
            raise ValueError(
                "location must be one of: 'node', 'edge', 'face', 'boundary', or 'none'"
            )

        self.location = location

        if len(data) == 1:
            raise ValueError(
                "UMVar need at least 2 data sources of the same size and shape"
            )

        if not all([isarraylike(d) for d in data]):
            raise ValueError("Data must satisfy isarraylike or be a UVar")

        self.shape = data[0].shape
        if not all([d.shape == self.shape for d in data]):
            raise ValueError(
                "All data sources must be the same size and shape")

        for d in data:
            setattr(self, d.name, d)

        self.variables = [d.name for d in data]
        self._cache = OrderedDict()

    def add_var(self, var):
        if var.shape != self.shape:
            raise ValueError('Variable {0} has incorrect shape {1}'.format(
                var.name, var.shape))
        if var.name in self.variables:
            raise ValueError('Variable {0} already exists in UMVar'.format(
                var.name))
        self.variables.append(var.name)
        setattr(self, var.name, var)

    def __getitem__(self, item):
        if str(item) in self._cache:
            return self._cache[str(item)]
        else:
            rv = np.ma.column_stack([
                self.__getattribute__(var).__getitem__(item)
                for var in self.variables
            ])
            self._cache[str(item)] = rv
            if len(self._cache) > 3:
                self._cache.popitem(last=False)
            return rv
Пример #51
0
class LRUQueue(object):
    """
    LRUQueue is a data structure that orders objects by
      their insertion time, and supports an update/touch operation
      that resets an item to the newest slot.

    This is an example of a priority queue, ordered by
      insertion time, with explicit support for "touch".
    """
    def __init__(self, key=lambda n: n):
        """
        The `key` parameter may be provided if the
          items in the queue are complex.
        The `key` parameter should select a unique "id" field from
          each item.
        """
        super(LRUQueue, self).__init__()
        self._q = OrderedDict()
        self._key = key

    def push(self, v):
        k = self._key(v)
        self._q[k] = v

    def pop(self):
        return self._q.popitem(last=False)[1]

    def touch(self, v):
        """
        Reset the given value back to the newest slot.
        """
        k = self._key(v)
        del self._q[k]
        self._q[k] = v

    def size(self):
        return len(self._q)

    def __len__(self):
        return self.size()

    @staticmethod
    def test():
        q = LRUQueue()
        assert q.size() == 0
        assert len(q) == 0

        q.push(0)
        assert q.size() == 1
        assert len(q) == 1

        assert q.pop() == 0
        assert q.size() == 0
        assert len(q) == 0

        q.push(0)
        q.push(1)
        assert q.pop() == 0
        assert q.pop() == 1

        q.push(0)
        q.push(1)
        q.touch(0)
        assert q.pop() == 1
        assert q.pop() == 0

        q = LRUQueue(key=lambda n: n[0])
        q.push([0])
        assert q.pop() == [0]

        q.push([0])
        q.push([1])
        assert q.pop() == [0]
        assert q.pop() == [1]
        return True
class PositionsManager(Initializable):
    MAX_POSITIONS_COUNT = 2000

    def __init__(self, config, trader, exchange_manager):
        super().__init__()
        self.logger = get_logger(self.__class__.__name__)
        self.config, self.trader, self.exchange_manager = config, trader, exchange_manager
        self.positions_initialized = False  # TODO
        self.positions = OrderedDict()

    async def initialize_impl(self):
        self._reset_positions()

    def get_open_positions(self, symbol=None, since=-1, limit=-1):
        return self._select_positions(True, symbol, since, limit)

    def get_closed_positions(self, symbol=None, since=-1, limit=-1):
        return self._select_positions(False, symbol, since, limit)

    def upsert_position(self, position_id, raw_position) -> bool:
        if position_id not in self.positions:
            self.positions[position_id] = self._create_position_from_raw(
                raw_position)
            self._check_positions_size()
            return True

        return self._update_position_from_raw(self.positions[position_id],
                                              raw_position)

    def upsert_position_instance(self, position) -> bool:
        if position.position_id not in self.positions:
            self.positions[position.position_id] = position
            self._check_positions_size()
            return True
        # TODO
        return False

    # private
    def _check_positions_size(self):
        if len(self.positions) > self.MAX_POSITIONS_COUNT:
            self._remove_oldest_positions(int(self.MAX_POSITIONS_COUNT / 2))

    def _create_position_from_raw(self, raw_position):
        position = Position(self.trader)
        position.update_position_from_raw(raw_position)
        return position

    def _update_position_from_raw(self, position, raw_position):
        return position.update_position_from_raw(raw_position)

    def _select_positions(self,
                          status=PositionStatus.OPEN,
                          symbol=None,
                          since=-1,
                          limit=-1):
        positions = [
            position for position in self.positions.values()
            if (position.status == status and (
                symbol is None or (symbol and position.symbol == symbol)) and (
                    since == -1 or (since and position.timestamp < since)))
        ]
        return positions if limit == -1 else positions[0:limit]

    def _reset_positions(self):
        self.positions_initialized = False
        self.positions = OrderedDict()

    def _remove_oldest_positions(self, nb_to_remove):
        for _ in range(nb_to_remove):
            self.positions.popitem(last=False)
Пример #53
0
def wordCount(file, input):
    tel_sorted_by_value = OrderedDict(
        sorted(file.items(), key=lambda x: x[1], reverse=True))
    for x in xrange(input):
        print tel_sorted_by_value.popitem(last=False)
class LRUCache(HasStrictTraits):
    """ A least-recently used cache.

    Items older than `size()` accesses are dropped from the cache.

    """

    size = Int

    # Called with the key and value that was dropped from the cache
    cache_drop_callback = Callable

    # This event contains the set of cached cell keys whenever it changes
    updated = Event()

    _lock = Instance(RLock, args=())

    _cache = Instance(OrderedDict)

    def __init__(self, size, **traits):
        self.size = size
        self._initialize_cache()
        super(LRUCache, self).__init__(**traits)

    def _initialize_cache(self):
        with self._lock:
            if self._cache is None:
                self._cache = OrderedDict()
            else:
                self._cache.clear()

    def _renew(self, key):
        with self._lock:
            r = self._cache.pop(key)
            self._cache[key] = r
        return r

    # -------------------------------------------------------------------------
    # LRUCache interface
    # -------------------------------------------------------------------------

    def __contains__(self, key):
        with self._lock:
            return key in self._cache

    def __len__(self):
        with self._lock:
            return len(self._cache)

    def __getitem__(self, key):
        with self._lock:
            return self._renew(key)

    def __setitem__(self, key, result):
        try:
            dropped = None
            with self._lock:
                self._cache[key] = result
                self._renew(key)
                if self.size < len(self._cache):
                    dropped = self._cache.popitem(last=False)
            if dropped and self.cache_drop_callback is not None:
                self.cache_drop_callback(*dropped)
        finally:
            self.updated = list(self.keys())

    def get(self, key, default=None):
        try:
            return self[key]
        except KeyError:
            return default

    def items(self):
        with self._lock:
            return list(self._cache.items())

    def keys(self):
        with self._lock:
            return list(self._cache.keys())

    def values(self):
        with self._lock:
            return list(self._cache.values())

    def clear(self):
        with self._lock:
            self._initialize_cache()
        self.updated = []
Пример #55
0
print(q)

from collections import defaultdict
dd = defaultdict(lambda: 'Null')
dd['kay1'] = '123'
print(dd['kay1'], dd['kay2'])

from collections import OrderedDict
d = dict([('a', 1), ('b', 2), ('c', 3)])
print(d)
od = OrderedDict([('b', 2), ('a', 1), ('c', 3)])
print(od, od.keys())  # order by insert order
od['e'] = 4
od['e'] = 7
print(od)
od.popitem()
print(od)
od.popitem(last=False)
print(od)


class LastUpdateOrderDict(OrderedDict):
    def __init__(self, capacity):
        super(LastUpdateOrderDict, self).__init__()
        self.capacity = capacity

    def __setitem__(self, key, value):
        containsKey = 1 if key in self else 0
        if len(self) - containsKey >= self.capacity:
            last = self.popitem(last=False)
            print('remove:', last)
Пример #56
0
class PyPIEvents:
    """
    When treated as an iterator, this class yields (package, version,
    timestamp, action) tuples indicating new packages or package versions
    registered on PyPI where action is one of 'create', 'source', or 'remove'.
    A small attempt is made to avoid duplicate reports, but we don't attempt to
    avoid reporting stuff already in the database (it's simpler to just start
    from the beginning of PyPI's log and work through it).

    The iterator only retrieves a small batch of entries at a time as PyPI
    (very sensibly) limits the number of entries in a single query (to 50,000
    at the time of writing), so the instance will need repeated querying to
    retrieve all rows (this works in our favour though as it means there's an
    obvious place to poll for control events between batches).

    :param str pypi_root:
        The web address at which to find the PyPI XML-RPC server.

    :param int serial:
        The serial number of the event from which to start reading.

    :param int retries:
        The number of retries the class may attempt if the HTTP connection
        fails.

    :param int cache_size:
        The size of the internal cache used to attempt to avoid duplicate
        reports.
    """
    # pylint: disable=too-few-public-methods
    add_file_re = re.compile(r'^add ([^ ]+) file')
    create_re = re.compile(r'^create$')
    remove_re = re.compile(r'^remove(?: (?:package|release))?')

    def __init__(self,
                 pypi_xmlrpc='https://pypi.org/pypi',
                 serial=0,
                 retries=3,
                 cache_size=1000):
        self.retries = retries
        self.next_read = datetime.now(tz=UTC)
        self.serial = serial
        # Keep a list of the last cache_size (package, version) tuples so we
        # can make a vague attempt at reducing duplicate reports
        self.cache = OrderedDict()
        self.cache_size = cache_size
        self.transport = PiWheelsTransport()
        self.client = xmlrpc.client.ServerProxy(pypi_xmlrpc, self.transport)

    def _get_events(self):
        # On rare occasions we get some form of HTTP improper state, or DNS
        # lookups fail. In this case just return an empty list and try again
        # later. If we get a protocol error with error 5xx it's a server-side
        # problem, so we again return an empty list and try later
        try:
            return self.client.changelog_since_serial(self.serial)
        except (OSError, http.client.ImproperConnectionState):
            return []
        except xmlrpc.client.ProtocolError as exc:
            if exc.errcode >= 500:
                return []
            else:
                raise

    def __iter__(self):
        # The next_read flag is used to delay reads to PyPI once we get to the
        # end of the event log entries
        if datetime.now(tz=UTC) > self.next_read:
            events = self._get_events()
            if events:
                for (package, version, timestamp, action, serial) in events:
                    timestamp = datetime.fromtimestamp(timestamp, tz=UTC)
                    match = self.add_file_re.search(action)
                    if match is not None:
                        action = ('source'
                                  if match.group(1) == 'source' else 'create')
                        try:
                            self.cache.move_to_end((package, version))
                        except KeyError:
                            self.cache[(package, version)] = (timestamp,
                                                              action)
                            yield (package, version, timestamp, action)
                        else:
                            (last_timestamp,
                             last_action) = self.cache[(package, version)]
                            if (last_action, action) == ('create', 'source'):
                                self.cache[(package,
                                            version)] = (last_timestamp,
                                                         action)
                                yield (package, version, last_timestamp,
                                       action)
                        while len(self.cache) > self.cache_size:
                            self.cache.popitem(last=False)
                    elif self.create_re.search(action) is not None:
                        yield (package, None, timestamp, 'create')
                    elif self.remove_re.search(action) is not None:
                        # If version is None here, indicating package deletion
                        # we could search and remove all corresponding versions
                        # from the cache but, frankly, it's not worth it
                        if version is not None:
                            self.cache.pop((package, version), None)
                        yield (package, version, timestamp, 'remove')
                    self.serial = serial
            else:
                # If the read is empty we've reached the end of the event log
                # or an error has occurred; make sure we don't bother PyPI for
                # another 10 seconds
                self.next_read = datetime.now(tz=UTC) + timedelta(seconds=10)
Пример #57
0
class CachedStore(BaseStore):
    """
    A thread-safe cached persistent store of the subscriber database.
    Prerequisite: persistent_store need to be thread safe
    """

    def __init__(self, persistent_store, cache_capacity=512, loop=None):
        self._lock = threading.Lock()
        self._cache = OrderedDict()
        self._cache_capacity = cache_capacity
        self._persistent_store = persistent_store
        self._on_ready = OnDataReady(loop=loop)

    def add_subscriber(self, subscriber_data):
        """
        Method that adds the subscriber.
        """
        sid = SIDUtils.to_str(subscriber_data.sid)
        with self._lock:
            if sid in self._cache:
                raise DuplicateSubscriberError(sid)

            self._persistent_store.add_subscriber(subscriber_data)
            self._cache_put(sid, subscriber_data)
        self._on_ready.add_subscriber(subscriber_data)

    @contextmanager
    def edit_subscriber(self, subscriber_id):
        """
        Context manager to modify the subscriber data.
        """
        with self._lock:
            if subscriber_id in self._cache:
                data = self._cache_get(subscriber_id)
                subscriber_data = copy.deepcopy(data)
            else:
                subscriber_data = \
                    self._persistent_store.get_subscriber_data(subscriber_id)
            yield subscriber_data
            self._persistent_store.update_subscriber(subscriber_data)
            self._cache_put(subscriber_id, subscriber_data)

    def delete_subscriber(self, subscriber_id):
        """
        Method that deletes a subscriber, if present.
        """
        with self._lock:
            if subscriber_id in self._cache:
                del self._cache[subscriber_id]

            self._persistent_store.delete_subscriber(subscriber_id)

    def delete_all_subscribers(self):
        """
        Method that removes all the subscribers from the store
        """
        with self._lock:
            self._cache_clear()
            self._persistent_store.delete_all_subscribers()

    def resync(self, subscribers):
        """
        Method that should resync the store with the mentioned list of
        subscribers. The resync leaves the current state of subscribers
        intact.

        Args:
            subscribers - list of subscribers to be in the store.
        """
        with self._lock:
            self._cache_clear()
            self._persistent_store.resync(subscribers)
        self._on_ready.resync(subscribers)

    def get_subscriber_data(self, subscriber_id):
        """
        Method that returns the subscriber data for the subscriber.
        """
        with self._lock:
            if subscriber_id in self._cache:
                return self._cache_get(subscriber_id)
            else:
                subscriber_data = \
                    self._persistent_store.get_subscriber_data(subscriber_id)
                self._cache_put(subscriber_id, subscriber_data)
                return subscriber_data

    def list_subscribers(self):
        """
        Method that returns the list of subscribers stored.
        Note: this method is not cached since it's easier to get the whole list
        from persistent store
        """
        return self._persistent_store.list_subscribers()

    async def on_ready(self):
        return await self._on_ready.event.wait()

    def _cache_get(self, k):
        """
        Get from the LRU cache. Move the last hit entry to the end.
        """
        self._cache.move_to_end(k)
        return self._cache[k]

    def _cache_put(self, k, v):
        """
        Put to the LRU cache. Evict the first item if full.
        """
        if self._cache_capacity == len(self._cache):
            self._cache.popitem(last=False)
        self._cache[k] = v

    def _cache_list(self):
        return list(self._cache.keys())

    def _cache_clear(self):
        self._cache.clear()
Пример #58
0
    def parseTypeDefinitions(self, outname, xmlDescription):
        def typeReady(element, types, xmlNamespaces):
            "Are all member types defined?"
            parentname = type_aliases.get(
                element.get("Name"), element.get("Name")
            )  # If a type contains itself, declare that type as available
            for child in element:
                if child.tag == "{http://opcfoundation.org/BinarySchema/}Field":
                    childname = get_type_name(child.get("TypeName"))[1]
                    if childname != "Bit" and childname != parentname:
                        try:
                            get_type_for_name(child.get("TypeName"), types,
                                              xmlNamespaces)
                        except TypeNotDefinedException:
                            # Type is using other types which are not yet loaded, try later
                            return False
            return True

        def unknownTypes(element, types, xmlNamespaces):
            "Return all unknown types (for debugging)"
            unknowns = []
            for child in element:
                if child.tag == "{http://opcfoundation.org/BinarySchema/}Field":
                    try:
                        get_type_for_name(child.get("TypeName"), types,
                                          xmlNamespaces)
                    except TypeNotDefinedException:
                        # Type is using other types which are not yet loaded, try later
                        unknowns.append(child.get("TypeName"))
            return unknowns

        def structWithOptionalFields(element):
            "Is this a structure with optional fields?"
            opt_fields = []
            for child in element:
                if child.tag != "{http://opcfoundation.org/BinarySchema/}Field":
                    continue
                typename = child.get("TypeName")
                if typename and get_type_name(typename)[1] == "Bit":
                    if re.match(re.compile('.+Specified'), child.get("Name")):
                        opt_fields.append(child.get("Name"))
                    elif child.get("Name") == "Reserved1":
                        if len(opt_fields) + int(child.get("Length")) != 32:
                            return False
                        else:
                            break
                    else:
                        return False
                else:
                    return False
            for child in element:
                switchfield = child.get("SwitchField")
                if switchfield and switchfield in opt_fields:
                    opt_fields.remove(switchfield)
            return len(opt_fields) == 0

        def structWithBitFields(element):
            "Is this a structure with bitfields?"
            for child in element:
                typename = child.get("TypeName")
                if typename and get_type_name(typename)[1] == "Bit":
                    return True
            return False

        snippets = OrderedDict()
        xmlDoc = etree.iterparse(xmlDescription, events=['start-ns'])
        xmlNamespaces = dict([node for _, node in xmlDoc])
        if xmlDoc.root.get("TargetNamespace"):
            targetNamespace = xmlDoc.root.get("TargetNamespace")
            if not targetNamespace in self.namespaceIndexMap:
                raise RuntimeError(
                    "TargetNamespace '{targetNs}' is not listed in namespace index mapping. "
                    "Use the following option to define the mapping (can be used multiple times). "
                    "--namespaceMap=X:{targetNs} where X is the resulting namespace index in the server."
                    .format(targetNs=targetNamespace))
        else:
            raise RuntimeError(
                "TargetNamespace Attribute not defined in BSD file.")
        for typeXml in xmlDoc.root:
            if not typeXml.get("Name"):
                continue
            name = typeXml.get("Name")
            snippets[name] = typeXml

        detectLoop = len(snippets) + 1
        while len(snippets) > 0:
            if detectLoop == len(snippets):
                name, typeXml = snippets.popitem()
                raise RuntimeError(
                    "Infinite loop detected or type not found while processing types "
                    + name + ": unknonwn subtype " +
                    str(unknownTypes(typeXml, self.types, xmlNamespaces)) +
                    ". If the unknown subtype is 'Bit', then maybe a struct with "
                    +
                    "optional fields is defined wrong in the .bsd-file. If not, maybe "
                    +
                    "you need to import additional types with the --import flag. "
                    +
                    "E.g. '--import==UA_TYPES#/path/to/deps/ua-nodeset/Schema/"
                    + "Opc.Ua.Types.bsd'")
            detectLoop = len(snippets)
            for name, typeXml in list(snippets.items()):
                if (targetNamespace in self.types
                        and name in self.types[targetNamespace]
                    ) or name in excluded_types:
                    del snippets[name]
                    continue
                if not typeReady(typeXml, self.types, xmlNamespaces):
                    continue
                if structWithBitFields(
                        typeXml) and not structWithOptionalFields(typeXml):
                    continue
                if name in builtin_types:
                    new_type = BuiltinType(name)
                elif typeXml.tag == "{http://opcfoundation.org/BinarySchema/}EnumeratedType":
                    new_type = EnumerationType(outname, typeXml,
                                               targetNamespace)
                elif typeXml.tag == "{http://opcfoundation.org/BinarySchema/}OpaqueType":
                    new_type = OpaqueType(
                        outname, typeXml, targetNamespace,
                        get_base_type_for_opaque(name)['name'])
                elif typeXml.tag == "{http://opcfoundation.org/BinarySchema/}StructuredType":
                    try:
                        new_type = StructType(outname, typeXml,
                                              targetNamespace, self.types,
                                              xmlNamespaces)
                    except TypeNotDefinedException:
                        # Type is using other types which are not yet loaded, try later
                        continue
                else:
                    raise Exception("Type not known")

                self.insert_type(new_type)
                del snippets[name]
Пример #59
0
def run_epoch(game_obj,
              mcts_operator_p,
              mcts_operator_q,
              p_configs,
              q_configs,
              max_game_length=62,
              prior_nodes_repo_size=300):

    # report the new board
    _state = game_obj.states[-1][0]
    json_state = json.dumps(_state.tolist())
    UDPSock_BOARD.send(json_state)

    # read parameters
    tree_depth_p = p_configs['tree_depth']
    memory_p = p_configs['memory']
    allowed_time_p = p_configs['allowed_time']
    tree_depth_q = q_configs['tree_depth']
    memory_q = q_configs['memory']
    allowed_time_q = q_configs['allowed_time']

    # start
    trace = []
    DATA_p = []
    #	DATA_q = []

    # in-simulation simluation re-use
    #prior_nodes_repo = OrderedDict(enumerate(range(prior_nodes_repo_size)))
    prior_nodes_repo = OrderedDict()

    # actual play
    _iter = 0
    det_pass = {1: False, -1: False}  # check if any move is possible or not
    while True:

        ########################################################################
        ########################################################################
        ########################################################################
        # emergency stop
        _iter += 1
        if _iter > max_game_length:
            break
        # end if
        rootLogger.info("===============\n")
        rootLogger.info(" Game turn: %d\n" % _iter)
        rootLogger.info("===============")

        rootLogger.info("Player B turn\n")
        # mcts_operator_p's turn
        # (1) select last n steps
        last_states = game_obj.states[-memory_p:]
        # (2) feed to agent
        mcts_operator_p.feed(last_states)

        # (2.5) find if node has been sampled before
        #		rootLogger.info('last_states')
        #		rootLogger.info(last_states)
        _key = make_node_key(last_states)
        prior_node = prior_nodes_repo.get(_key)

        # (3) agent run mcts
        rootLogger.info(" = start MCTS\n")
        results = mcts_operator_p.start_mcts(tree_depth=tree_depth_p,
                                             allowed_time=allowed_time_p,
                                             prior_node=prior_node,
                                             logger=logger_p)  # end start
        updated_node, sampled_nodes = results

        # (3.5) store sampled nodes for re-use
        for _node in sampled_nodes:
            key = make_node_key(_node.data['states'])
            prior_nodes_repo.update({key: _node})
        # end for

        # control the size of repo
        excess_n = len(prior_nodes_repo) - prior_nodes_repo_size
        for _counter in range(excess_n):
            prior_nodes_repo.popitem(last=False)
        # end for

        # (4) record the MCTS run (first layer)
        rootLogger.info(' = collect MCTS data\n')
        mcts_probs = mcts_operator_p.get_mcts_probs()
        DATA_p.append({'states': last_states, 'probs': mcts_probs})
        # (5) select move
        move_node = mcts_operator_p.select_move()

        # check surrender or pass
        if move_node == (-1, 0):  # surrender
            winner = -cur_player
            break
        elif move_node == (-1, 1):  # pass
            rootLogger.info(' - PASS\n')
            det_pass[cur_player] = True
            if det_pass[
                    -cur_player] == True:  # opponent also no move, end game
                break
            # end if
        # end if

        # (6) record move
        cur_player = last_states[-1][1]
        move = move_node.data['move']
        _confidence = mcts_operator_p.max_confidence
        rootLogger.info(' - PLAYS %s (confidence: %4.1f%%)\n' %
                        (str(move), _confidence * 100))

        # send confidence value
        UDPSock_MISC.send(_confidence)
        trace.append({
            'player': cur_player,
            'move': move,
            'confidence': _confidence
        })

        # actually transit into the next state
        move_state = move_node.data['states'][-1]
        game_obj.set_state(move_state)

        # report the new board
        _state = game_obj.states[-1][0]
        json_state = json.dumps(_state.tolist())
        UDPSock_BOARD.send(json_state)

        det_pass[cur_player] = False
        det_pass[-cur_player] = False

        ########################################################################
        ########################################################################
        ########################################################################
        # emergency stop
        _iter += 1
        if _iter > max_game_length:
            break
        # end if
        rootLogger.info("===============\n")
        rootLogger.info(" Game turn: %d\n" % _iter)
        rootLogger.info("===============\n")

        rootLogger.info("Player W turn\n")

        # mcts_operator_q's turn
        # (1) select last n steps
        last_states = game_obj.states[-memory_q:]
        # (2.5) find if node has been sampled before
        _key = make_node_key(last_states)
        prior_node = prior_nodes_repo.get(_key)
        # start background run
        control_Q = queue.Queue()
        sample_Q = queue.LifoQueue(
        )  # keep only last two run (in fact need last one only)
        sample_Q.put({})
        args = (
            control_Q,
            sample_Q,
            mcts_operator_q,
            last_states,
            prior_node,
            make_node_key,
            tree_depth_q,
            allowed_time_q,
            logger_q,
        )
        prc_mcts = Process(target=mcts_background_run, args=args)
        prc_mcts.start()
        rootLogger.info(' = start background MCTS process\n')

        # ===== USER INTERACTION HERE ==== #
        # find all legal moves
        nexts = game_obj.get_all_legal_moves(last_states)
        if len(nexts) == 0:
            rootLogger.info('No legal moves for player\n')
            rootLogger.info(
                'No more possible moves. Click any empty cell to continue.\n')
            (user_input, addr) = UDPSock_IN.recvfrom(buf)
            move_node = (-1, 1)
            input_move = (-1, 1)
        else:
            legal_moves = {item['move']: item for item in nexts}
            # read input from player
            while True:
                try:
                    rootLogger.info('  = legal moves: %s\n' %
                                    str(list(legal_moves.keys())))
                    rootLogger.info(' = waiting for player to respond\n')
                    #					user_input = input('Enter your move: ')
                    while True:
                        (user_input, addr) = UDPSock_IN.recvfrom(buf)
                        print(' = receive input:', user_input)
                        break
                    # end while

                    input_move = tuple(map(int, user_input.split()[:2]))
                    if input_move not in legal_moves:
                        err_msg = 'Invalid move'
                        UDPSock.sendto(err_msg.encode(),
                                       ('localhost', output_socket_post))
                        raise (Exception(err_msg))
                    # end if
                    move_state = legal_moves[input_move]['state']
                    break
                except Exception as e:
                    rootLogger.info('Error: %s\n' % str(e))
                # end try
            # end while
        # end if

        # get the samples from background run and put to repo
        _repo = sample_Q.get_nowait()
        prior_nodes_repo.update(_repo)

        # send signal through queue to end the background process
        control_Q.put('END')
        #		control_Q.put('END')
        #		prc_mcts.terminate()
        #		for i in range(20):
        #			rootLogger.info ('killed background process')

        # control the size of repo
        excess_n = len(prior_nodes_repo) - prior_nodes_repo_size
        for _counter in range(excess_n):
            prior_nodes_repo.popitem(last=False)
        # end for

        # (4) record the MCTS run (first layer)
        # note: optional in interactive play
        rootLogger.info(' = collect MCTS data\n')
        #		mcts_probs = mcts_operator_q.get_mcts_probs()
        #		DATA_q.append({'states': last_states, 'probs': mcts_probs})

        # (5) select move
        #		move_node = mcts_operator_q.select_move()
        # (6) record move
        cur_player = last_states[-1][1]
        #		move = move_node.data['move']

        # confidence is undefined in interactive mode
        #		_confidence = mcts_operator_q.max_confidence
        #		rootLogger.info(' - PLAYS %s (confidence: %4.1f%%)' % (str(move), _confidence*100))
        #		trace.append({'player': cur_player, 'move': move, 'confidence': _confidence})
        trace.append({'player': cur_player, 'move': input_move})

        # check surrender or pass
        if move_node == (-1, 0):  # surrender
            winner = -cur_player
            break
        elif move_node == (-1, 1):  # pass
            rootLogger.info(' - PASS\n')
            det_pass[cur_player] = True
            if det_pass[
                    -cur_player] == True:  # opponent also no move, end game
                break
            # end if
        # end if

        # actually transit into the next state
#		move_state = move_node.data['states'][-1]
        game_obj.set_state(move_state)

        # report the new board
        _state = game_obj.states[-1][0]
        json_state = json.dumps(_state.tolist())
        UDPSock_BOARD.send(json_state)

        det_pass[cur_player] = False
        det_pass[-cur_player] = False
    # wnd while

    # determine winner
    final_state = game_obj.states[-1]
    winner = game_obj.get_winner(final_state)

    # decorate the data
    for item in DATA_p:
        item['winner'] = winner
    # end for
#	for item in DATA_q:
#		item['winner'] = winner
#	# end for

#	return {'data_p': DATA_p, 'data_q': DATA_q, 'trace': trace, 'game_obj': game_obj}
    return {'data_p': DATA_p, 'trace': trace, 'game_obj': game_obj}
Пример #60
0
class TileValue(Layer):
  """A wrapper for rendering an image of uint8, where you can choose a colour for each, or show through the background if you want. Has a tile cache, to make it suitably fast to render."""
  def __init__(self, values, tile_size=256, cache_size = 1024):
    """Initalises the value viewer; you can use None if you would rather initialise it later."""
    # Store various bits of info...
    self.tile_size = tile_size
    self.cache_size = cache_size
    self.visible = True

    # Setup the cache and stroe the values...
    self.cache = OrderedDict()
    self.cache_key = 0 # Incrimented each time the contents is replaced, and included in the tile key - avoids memory churn.
    self.set_values(values)
    
    # Indicates if we are using interpolation or not...
    self.interpolate = False
    
    # The colours to use for the mask channels, with None to let the background show through...
    # (If we index outside the array then that is None.)
    self.colour = []
    
    # A temporary, used when creating tiles...
    self.temp = cairo.ImageSurface(cairo.FORMAT_ARGB32, tile_size, tile_size)
    self.temp_ctx = cairo.Context(self.temp)
  

  def set_values(self, values):
    """Replaces the current values array with a new one."""
    # Default values for if None is provided...
    if values==None: values = numpy.zeros((480, 640), dtype=numpy.uint8)
    
    # Some shared setup stuff...
    stride = cairo.ImageSurface.format_stride_for_width(cairo.FORMAT_A8, values.shape[1])
    mask = numpy.empty((values.shape[0], stride), dtype=numpy.uint8)
    temp = cairo.ImageSurface.create_for_data(mask, cairo.FORMAT_A8, mask.shape[1], mask.shape[0], stride)
    
    # For each value create an alpha mask...
    self.values = []
    for i in xrange(values.max()+1):
      # Create a mask for this layer...
      mask[:,:] = 0
      mask[values==i] = 255
    
      # Copy the mask into perminant storage...
      ms = cairo.ImageSurface(cairo.FORMAT_A8, mask.shape[1], mask.shape[0])
      
      ctx = cairo.Context(ms)
      ctx.set_source_surface(temp, 0, 0)
      ctx.paint()
      
      self.values.append(ms)
    
    # Clean up temp - its dependent on the memory in mask...
    del temp
    
    # Change the cache key, so we recycle old tiles rather than use them...
    self.cache_key += 1

  
  def get_size(self):
    """Returns the tuple (height, width) for the original size."""
    if len(self.values)==0: return (480, 640)
    return (self.values[0].get_height(), self.values[0].get_width())
  
  
  def get_interpolate(self):
    """Returns True if the mask is interpolated, False if it is not."""
    return self.interpolate
    
  def set_interpolate(self, interpolate):
    """True to interpolate, False to not. Defaults to True"""
    self.interpolate = interpolate
  
  
  def get_colour(self, value):
    """Returns the colour used for the given part of the mask, as 4 tuple with the last element alpha, or None if it is transparent."""
    if value < len(self.colour): return self.colour[value]
    else: return None
  
  def set_colour(self, value, col = None):
    """Sets the colour for a value, as a 4-tuple (r,g,b,a), or None for totally transparent."""
    if len(self.colour)<=value: self.colour += [None] * (value + 1 - len(self.colour))
    self.colour[value] = col
    self.cache_key += 1
  
  
  def fetch_tile(self, scale, bx, by, extra = 0):
    """Fetches a tile, given a scale (Multiplication of original dimensions.) and base coordinates (bx, by) - the tile will be the size provided on class initialisation. This request is going through a caching layer, which will hopefuly have the needed tile. If not it will be generated and the tile that has been used the least recently thrown away."""
    
    # Instance the key for this tile and check if it is in the cache, if so grab it, rearrange it to the top of the queue and return it...
    key = (scale, bx, by, self.interpolate, self.cache_key)
    if key in self.cache:
      ret = self.cache[key]
      del self.cache[key]
      self.cache[key] = ret
      return ret
    
    # Select a new tile to render into - either create one or recycle whatever is going to die at the end of the cache...
    if len(self.cache)>=(self.cache_size-extra):
      ret = self.cache.popitem()[1]
    else:
      ret = cairo.ImageSurface(cairo.FORMAT_ARGB32, self.tile_size, self.tile_size)
    
    # Render the tile, with the appropriate scaling...
    ctx = cairo.Context(ret)
    ctx.save()
    ctx.set_operator(cairo.OPERATOR_SOURCE)
    ctx.set_source_rgba(0.0, 0.0, 0.0, 0.0)
    ctx.paint()
    ctx.restore()
    
    if scale<8.0:
      self.temp_ctx.save()
      self.temp_ctx.translate(-bx, -by)
      self.temp_ctx.scale(scale, scale)
      
      for i, mask in enumerate(self.values[:len(self.colour)]):
        col = self.colour[i]
        if col!=None:
          self.temp_ctx.set_source_rgba(col[0], col[1], col[2], col[3])
          self.temp_ctx.set_operator(cairo.OPERATOR_SOURCE)
          self.temp_ctx.paint()
          
          oasp = cairo.SurfacePattern(mask)
          oasp.set_filter(cairo.FILTER_BILINEAR if self.interpolate else cairo.FILTER_NEAREST)
          
          self.temp_ctx.set_source(oasp)
          self.temp_ctx.set_operator(cairo.OPERATOR_DEST_IN)
          self.temp_ctx.paint()

          ctx.set_source_surface(self.temp)
          ctx.paint()

      self.temp_ctx.restore()
    else:
      # Cairo has an annoying habit of failing if you push the scale too far - this makes it recursive for such situations...
      power = math.log(scale) / math.log(2.0)
      child_scale = 2**(int(math.floor(power))-2)
      remain_scale = scale / child_scale
      
      child_bx = int(math.floor((bx-1) / (remain_scale*0.5*self.tile_size))) * self.tile_size//2
      child_by = int(math.floor((by-1) / (remain_scale*0.5*self.tile_size))) * self.tile_size//2
        
      child = self.fetch_tile(child_scale, child_bx, child_by, extra+1)
      
      oasp = cairo.SurfacePattern(child)
      oasp.set_filter(cairo.FILTER_BILINEAR if self.interpolate else cairo.FILTER_NEAREST)
      
      ctx.translate(-(bx - child_bx*remain_scale), -(by - child_by*remain_scale))
      ctx.scale(remain_scale, remain_scale)
      ctx.set_source(oasp)
      ctx.paint()
    
    # Store the tile in the cache and return...
    self.cache[key] = ret
    return ret
    
    
  def draw(self, ctx, vp):
    """Draws the image into the provided context, matching the provided viewport."""
    if not self.visible:
      return
    
    # Calculate the scale, base coordinates and number of tiles in each dimension...
    scale = vp.width / float(vp.end_x - vp.start_x)
    
    base_x = int(math.floor(vp.start_x * scale))
    base_y = int(math.floor(vp.start_y * scale))
    
    tile_bx = int(math.floor(base_x / float(self.tile_size))) * self.tile_size
    tile_by = int(math.floor(base_y / float(self.tile_size))) * self.tile_size
    
    # Loop and draw the required tiles, with the correct offset...
    y = tile_by
    while y < int(base_y+vp.height+1):
      x = tile_bx
      while x < int(base_x+vp.width+1):
        tile = self.fetch_tile(scale, x, y)
        
        ctx.set_source_surface(tile, x - base_x, y - base_y)
        ctx.rectangle(x - base_x, y - base_y, self.tile_size, self.tile_size)
        ctx.fill()
        
        x += self.tile_size
      y += self.tile_size