static PyObject * lru_cache_cache_info(lru_cache_object *self, PyObject *unused) { return PyObject_CallFunction(self->cache_info_type, "nnOn", self->hits, self->misses, self->maxsize_O, PyDict_GET_SIZE(self->cache)); }
static PyObject * lru_cache_make_key(PyObject *args, PyObject *kwds, int typed) { PyObject *key, *keyword, *value; Py_ssize_t key_size, pos, key_pos, kwds_size; /* short path, key will match args anyway, which is a tuple */ if (!typed && !kwds) { Py_INCREF(args); return args; } kwds_size = kwds ? PyDict_GET_SIZE(kwds) : 0; assert(kwds_size >= 0); key_size = PyTuple_GET_SIZE(args); if (kwds_size) key_size += kwds_size * 2 + 1; if (typed) key_size += PyTuple_GET_SIZE(args) + kwds_size; key = PyTuple_New(key_size); if (key == NULL) return NULL; key_pos = 0; for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) { PyObject *item = PyTuple_GET_ITEM(args, pos); Py_INCREF(item); PyTuple_SET_ITEM(key, key_pos++, item); } if (kwds_size) { Py_INCREF(kwd_mark); PyTuple_SET_ITEM(key, key_pos++, kwd_mark); for (pos = 0; PyDict_Next(kwds, &pos, &keyword, &value);) { Py_INCREF(keyword); PyTuple_SET_ITEM(key, key_pos++, keyword); Py_INCREF(value); PyTuple_SET_ITEM(key, key_pos++, value); } assert(key_pos == PyTuple_GET_SIZE(args) + kwds_size * 2 + 1); } if (typed) { for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) { PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(args, pos)); Py_INCREF(item); PyTuple_SET_ITEM(key, key_pos++, item); } if (kwds_size) { for (pos = 0; PyDict_Next(kwds, &pos, &keyword, &value);) { PyObject *item = (PyObject *)Py_TYPE(value); Py_INCREF(item); PyTuple_SET_ITEM(key, key_pos++, item); } } } assert(key_pos == key_size); return key; }
static PyObject * ellipsis_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_GET_SIZE(kwargs))) { PyErr_SetString(PyExc_TypeError, "EllipsisType takes no arguments"); return NULL; } Py_INCREF(Py_Ellipsis); return Py_Ellipsis; }
static PyObject * function_call(PyObject *func, PyObject *arg, PyObject *kw) { PyObject *result; PyObject *argdefs; PyObject *kwtuple = NULL; PyObject **d, **k; Py_ssize_t nk, nd; argdefs = PyFunction_GET_DEFAULTS(func); if (argdefs != NULL && PyTuple_Check(argdefs)) { d = &PyTuple_GET_ITEM((PyTupleObject *)argdefs, 0); nd = PyTuple_GET_SIZE(argdefs); } else { d = NULL; nd = 0; } if (kw != NULL && PyDict_Check(kw)) { Py_ssize_t pos, i; nk = PyDict_GET_SIZE(kw); kwtuple = PyTuple_New(2*nk); if (kwtuple == NULL) return NULL; k = &PyTuple_GET_ITEM(kwtuple, 0); pos = i = 0; while (PyDict_Next(kw, &pos, &k[i], &k[i+1])) { Py_INCREF(k[i]); Py_INCREF(k[i+1]); i += 2; } nk = i/2; } else { k = NULL; nk = 0; } result = PyEval_EvalCodeEx( PyFunction_GET_CODE(func), PyFunction_GET_GLOBALS(func), (PyObject *)NULL, &PyTuple_GET_ITEM(arg, 0), PyTuple_GET_SIZE(arg), k, nk, d, nd, PyFunction_GET_KW_DEFAULTS(func), PyFunction_GET_CLOSURE(func)); Py_XDECREF(kwtuple); return result; }
static PyObject * partial_call(partialobject *pto, PyObject *args, PyObject *kwargs) { PyObject *kwargs2, *res; assert (PyCallable_Check(pto->fn)); assert (PyTuple_Check(pto->args)); assert (PyDict_Check(pto->kw)); if (PyDict_GET_SIZE(pto->kw) == 0) { /* kwargs can be NULL */ kwargs2 = kwargs; Py_XINCREF(kwargs2); } else { /* bpo-27840, bpo-29318: dictionary of keyword parameters must be copied, because a function using "**kwargs" can modify the dictionary. */ kwargs2 = PyDict_Copy(pto->kw); if (kwargs2 == NULL) { return NULL; } if (kwargs != NULL) { if (PyDict_Merge(kwargs2, kwargs, 1) != 0) { Py_DECREF(kwargs2); return NULL; } } } if (pto->use_fastcall) { res = partial_fastcall(pto, &PyTuple_GET_ITEM(args, 0), PyTuple_GET_SIZE(args), kwargs2); } else { res = partial_call_impl(pto, args, kwargs2); } Py_XDECREF(kwargs2); return res; }
static PyObject * bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds) { lru_list_elem *link; PyObject *key, *result; Py_hash_t hash; key = lru_cache_make_key(args, kwds, self->typed); if (!key) return NULL; hash = PyObject_Hash(key); if (hash == -1) { Py_DECREF(key); return NULL; } link = (lru_list_elem *)_PyDict_GetItem_KnownHash(self->cache, key, hash); if (link) { lru_cache_extricate_link(link); lru_cache_append_link(self, link); self->hits++; result = link->result; Py_INCREF(result); Py_DECREF(key); return result; } if (PyErr_Occurred()) { Py_DECREF(key); return NULL; } result = PyObject_Call(self->func, args, kwds); if (!result) { Py_DECREF(key); return NULL; } if (self->full && self->root.next != &self->root) { /* Use the oldest item to store the new key and result. */ PyObject *oldkey, *oldresult; /* Extricate the oldest item. */ link = self->root.next; lru_cache_extricate_link(link); /* Remove it from the cache. The cache dict holds one reference to the link, and the linked list holds yet one reference to it. */ if (_PyDict_DelItem_KnownHash(self->cache, link->key, link->hash) < 0) { lru_cache_append_link(self, link); Py_DECREF(key); Py_DECREF(result); return NULL; } /* Keep a reference to the old key and old result to prevent their ref counts from going to zero during the update. That will prevent potentially arbitrary object clean-up code (i.e. __del__) from running while we're still adjusting the links. */ oldkey = link->key; oldresult = link->result; link->hash = hash; link->key = key; link->result = result; if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link, hash) < 0) { Py_DECREF(link); Py_DECREF(oldkey); Py_DECREF(oldresult); return NULL; } lru_cache_append_link(self, link); Py_INCREF(result); /* for return */ Py_DECREF(oldkey); Py_DECREF(oldresult); } else { /* Put result in a new link at the front of the queue. */ link = (lru_list_elem *)PyObject_GC_New(lru_list_elem, &lru_list_elem_type); if (link == NULL) { Py_DECREF(key); Py_DECREF(result); return NULL; } link->hash = hash; link->key = key; link->result = result; _PyObject_GC_TRACK(link); if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link, hash) < 0) { Py_DECREF(link); return NULL; } lru_cache_append_link(self, link); Py_INCREF(result); /* for return */ self->full = (PyDict_GET_SIZE(self->cache) >= self->maxsize); } self->misses++; return result; }
static PyObject * lru_cache_make_key(PyObject *args, PyObject *kwds, int typed) { PyObject *key, *sorted_items; Py_ssize_t key_size, pos, key_pos; /* short path, key will match args anyway, which is a tuple */ if (!typed && !kwds) { Py_INCREF(args); return args; } if (kwds && PyDict_GET_SIZE(kwds) > 0) { sorted_items = PyDict_Items(kwds); if (!sorted_items) return NULL; if (PyList_Sort(sorted_items) < 0) { Py_DECREF(sorted_items); return NULL; } } else sorted_items = NULL; key_size = PyTuple_GET_SIZE(args); if (sorted_items) key_size += PyList_GET_SIZE(sorted_items); if (typed) key_size *= 2; if (sorted_items) key_size++; key = PyTuple_New(key_size); if (key == NULL) goto done; key_pos = 0; for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) { PyObject *item = PyTuple_GET_ITEM(args, pos); Py_INCREF(item); PyTuple_SET_ITEM(key, key_pos++, item); } if (sorted_items) { Py_INCREF(kwd_mark); PyTuple_SET_ITEM(key, key_pos++, kwd_mark); for (pos = 0; pos < PyList_GET_SIZE(sorted_items); ++pos) { PyObject *item = PyList_GET_ITEM(sorted_items, pos); Py_INCREF(item); PyTuple_SET_ITEM(key, key_pos++, item); } } if (typed) { for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) { PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(args, pos)); Py_INCREF(item); PyTuple_SET_ITEM(key, key_pos++, item); } if (sorted_items) { for (pos = 0; pos < PyList_GET_SIZE(sorted_items); ++pos) { PyObject *tp_items = PyList_GET_ITEM(sorted_items, pos); PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(tp_items, 1)); Py_INCREF(item); PyTuple_SET_ITEM(key, key_pos++, item); } } } assert(key_pos == key_size); done: if (sorted_items) Py_DECREF(sorted_items); return key; }
static PyObject * partial_new(PyTypeObject *type, PyObject *args, PyObject *kw) { PyObject *func, *pargs, *nargs, *pkw; partialobject *pto; if (PyTuple_GET_SIZE(args) < 1) { PyErr_SetString(PyExc_TypeError, "type 'partial' takes at least one argument"); return NULL; } pargs = pkw = NULL; func = PyTuple_GET_ITEM(args, 0); if (Py_TYPE(func) == &partial_type && type == &partial_type) { partialobject *part = (partialobject *)func; if (part->dict == NULL) { pargs = part->args; pkw = part->kw; func = part->fn; assert(PyTuple_Check(pargs)); assert(PyDict_Check(pkw)); } } if (!PyCallable_Check(func)) { PyErr_SetString(PyExc_TypeError, "the first argument must be callable"); return NULL; } /* create partialobject structure */ pto = (partialobject *)type->tp_alloc(type, 0); if (pto == NULL) return NULL; pto->fn = func; Py_INCREF(func); nargs = PyTuple_GetSlice(args, 1, PY_SSIZE_T_MAX); if (nargs == NULL) { Py_DECREF(pto); return NULL; } if (pargs == NULL || PyTuple_GET_SIZE(pargs) == 0) { pto->args = nargs; Py_INCREF(nargs); } else if (PyTuple_GET_SIZE(nargs) == 0) { pto->args = pargs; Py_INCREF(pargs); } else { pto->args = PySequence_Concat(pargs, nargs); if (pto->args == NULL) { Py_DECREF(nargs); Py_DECREF(pto); return NULL; } assert(PyTuple_Check(pto->args)); } Py_DECREF(nargs); if (pkw == NULL || PyDict_GET_SIZE(pkw) == 0) { if (kw == NULL) { pto->kw = PyDict_New(); } else { Py_INCREF(kw); pto->kw = kw; } } else { pto->kw = PyDict_Copy(pkw); if (kw != NULL && pto->kw != NULL) { if (PyDict_Merge(pto->kw, kw, 1) != 0) { Py_DECREF(pto); return NULL; } } } if (pto->kw == NULL) { Py_DECREF(pto); return NULL; } return (PyObject *)pto; }
static PyObject * partial_call(partialobject *pto, PyObject *args, PyObject *kw) { PyObject *ret; PyObject *argappl, *kwappl; PyObject **stack; Py_ssize_t nargs; assert (PyCallable_Check(pto->fn)); assert (PyTuple_Check(pto->args)); assert (PyDict_Check(pto->kw)); if (PyTuple_GET_SIZE(pto->args) == 0) { stack = &PyTuple_GET_ITEM(args, 0); nargs = PyTuple_GET_SIZE(args); argappl = NULL; } else if (PyTuple_GET_SIZE(args) == 0) { stack = &PyTuple_GET_ITEM(pto->args, 0); nargs = PyTuple_GET_SIZE(pto->args); argappl = NULL; } else { stack = NULL; argappl = PySequence_Concat(pto->args, args); if (argappl == NULL) { return NULL; } assert(PyTuple_Check(argappl)); } if (PyDict_GET_SIZE(pto->kw) == 0) { kwappl = kw; Py_XINCREF(kwappl); } else { kwappl = PyDict_Copy(pto->kw); if (kwappl == NULL) { Py_XDECREF(argappl); return NULL; } if (kw != NULL) { if (PyDict_Merge(kwappl, kw, 1) != 0) { Py_XDECREF(argappl); Py_DECREF(kwappl); return NULL; } } } if (stack) { ret = _PyObject_FastCallDict(pto->fn, stack, nargs, kwappl); } else { ret = PyObject_Call(pto->fn, argappl, kwappl); Py_DECREF(argappl); } Py_XDECREF(kwappl); return ret; }
PyObject* pysqlite_cache_get(pysqlite_Cache* self, PyObject* args) { PyObject* key = args; pysqlite_Node* node; pysqlite_Node* ptr; PyObject* data; node = (pysqlite_Node*)PyDict_GetItem(self->mapping, key); if (node) { /* an entry for this key already exists in the cache */ /* increase usage counter of the node found */ if (node->count < LONG_MAX) { node->count++; } /* if necessary, reorder entries in the cache by swapping positions */ if (node->prev && node->count > node->prev->count) { ptr = node->prev; while (ptr->prev && node->count > ptr->prev->count) { ptr = ptr->prev; } if (node->next) { node->next->prev = node->prev; } else { self->last = node->prev; } if (node->prev) { node->prev->next = node->next; } if (ptr->prev) { ptr->prev->next = node; } else { self->first = node; } node->next = ptr; node->prev = ptr->prev; if (!node->prev) { self->first = node; } ptr->prev = node; } } else { /* There is no entry for this key in the cache, yet. We'll insert a new * entry in the cache, and make space if necessary by throwing the * least used item out of the cache. */ if (PyDict_GET_SIZE(self->mapping) == self->size) { if (self->last) { node = self->last; if (PyDict_DelItem(self->mapping, self->last->key) != 0) { return NULL; } if (node->prev) { node->prev->next = NULL; } self->last = node->prev; node->prev = NULL; Py_DECREF(node); } } data = PyObject_CallFunction(self->factory, "O", key); if (!data) { return NULL; } node = pysqlite_new_node(key, data); if (!node) { return NULL; } node->prev = self->last; Py_DECREF(data); if (PyDict_SetItem(self->mapping, key, (PyObject*)node) != 0) { Py_DECREF(node); return NULL; } if (self->last) { self->last->next = node; } else { self->first = node; } self->last = node; } Py_INCREF(node->data); return node->data; }