Mercurial > cpython-lru_cache-weakref
view Modules/_scproxy.c @ 87690:66c1c9f32567 default tip
Add use_weakref option to functools.lru_cache
The use_weakref option makes lru_cache create weak references to the function
arguments when creating the cache key, which prevents them from staying in the
memory forever even after all other references to them are gone.
This is a proof of concept for http://bugs.python.org/issue19859
| author | Radomir Dopieralski <devel@sheep.art.pl> |
|---|---|
| date | Tue, 03 Dec 2013 16:02:48 +0100 |
| parents | e332cd95f414 |
| children |
line wrap: on
line source
/* * Helper method for urllib to fetch the proxy configuration settings * using the SystemConfiguration framework. */ #include <Python.h> #include <SystemConfiguration/SystemConfiguration.h> static int32_t cfnum_to_int32(CFNumberRef num) { int32_t result; CFNumberGetValue(num, kCFNumberSInt32Type, &result); return result; } static PyObject* cfstring_to_pystring(CFStringRef ref) { const char* s; s = CFStringGetCStringPtr(ref, kCFStringEncodingUTF8); if (s) { return PyUnicode_DecodeUTF8( s, strlen(s), NULL); } else { CFIndex len = CFStringGetLength(ref); Boolean ok; PyObject* result; char* buf; buf = PyMem_Malloc(len*4); if (buf == NULL) { PyErr_NoMemory(); return NULL; } ok = CFStringGetCString(ref, buf, len * 4, kCFStringEncodingUTF8); if (!ok) { PyMem_Free(buf); return NULL; } else { result = PyUnicode_DecodeUTF8( buf, strlen(buf), NULL); PyMem_Free(buf); } return result; } } static PyObject* get_proxy_settings(PyObject* mod __attribute__((__unused__))) { CFDictionaryRef proxyDict = NULL; CFNumberRef aNum = NULL; CFArrayRef anArray = NULL; PyObject* result = NULL; PyObject* v; int r; proxyDict = SCDynamicStoreCopyProxies(NULL); if (!proxyDict) { Py_INCREF(Py_None); return Py_None; } result = PyDict_New(); if (result == NULL) goto error; if (&kSCPropNetProxiesExcludeSimpleHostnames != NULL) { aNum = CFDictionaryGetValue(proxyDict, kSCPropNetProxiesExcludeSimpleHostnames); if (aNum == NULL) { v = PyBool_FromLong(0); } else { v = PyBool_FromLong(cfnum_to_int32(aNum)); } } else { v = PyBool_FromLong(0); } if (v == NULL) goto error; r = PyDict_SetItemString(result, "exclude_simple", v); Py_DECREF(v); v = NULL; if (r == -1) goto error; anArray = CFDictionaryGetValue(proxyDict, kSCPropNetProxiesExceptionsList); if (anArray != NULL) { CFIndex len = CFArrayGetCount(anArray); CFIndex i; v = PyTuple_New(len); if (v == NULL) goto error; r = PyDict_SetItemString(result, "exceptions", v); Py_DECREF(v); if (r == -1) goto error; for (i = 0; i < len; i++) { CFStringRef aString = NULL; aString = CFArrayGetValueAtIndex(anArray, i); if (aString == NULL) { PyTuple_SetItem(v, i, Py_None); Py_INCREF(Py_None); } else { PyObject* t = cfstring_to_pystring(aString); if (!t) { PyTuple_SetItem(v, i, Py_None); Py_INCREF(Py_None); } else { PyTuple_SetItem(v, i, t); } } } } CFRelease(proxyDict); return result; error: if (proxyDict) CFRelease(proxyDict); Py_XDECREF(result); return NULL; } static int set_proxy(PyObject* proxies, char* proto, CFDictionaryRef proxyDict, CFStringRef enabledKey, CFStringRef hostKey, CFStringRef portKey) { CFNumberRef aNum; aNum = CFDictionaryGetValue(proxyDict, enabledKey); if (aNum && cfnum_to_int32(aNum)) { CFStringRef hostString; hostString = CFDictionaryGetValue(proxyDict, hostKey); aNum = CFDictionaryGetValue(proxyDict, portKey); if (hostString) { int r; PyObject* h = cfstring_to_pystring(hostString); PyObject* v; if (h) { if (aNum) { int32_t port = cfnum_to_int32(aNum); v = PyUnicode_FromFormat("http://%U:%ld", h, (long)port); } else { v = PyUnicode_FromFormat("http://%U", h); } Py_DECREF(h); if (!v) return -1; r = PyDict_SetItemString(proxies, proto, v); Py_DECREF(v); return r; } } } return 0; } static PyObject* get_proxies(PyObject* mod __attribute__((__unused__))) { PyObject* result = NULL; int r; CFDictionaryRef proxyDict = NULL; proxyDict = SCDynamicStoreCopyProxies(NULL); if (proxyDict == NULL) { return PyDict_New(); } result = PyDict_New(); if (result == NULL) goto error; r = set_proxy(result, "http", proxyDict, kSCPropNetProxiesHTTPEnable, kSCPropNetProxiesHTTPProxy, kSCPropNetProxiesHTTPPort); if (r == -1) goto error; r = set_proxy(result, "https", proxyDict, kSCPropNetProxiesHTTPSEnable, kSCPropNetProxiesHTTPSProxy, kSCPropNetProxiesHTTPSPort); if (r == -1) goto error; r = set_proxy(result, "ftp", proxyDict, kSCPropNetProxiesFTPEnable, kSCPropNetProxiesFTPProxy, kSCPropNetProxiesFTPPort); if (r == -1) goto error; r = set_proxy(result, "gopher", proxyDict, kSCPropNetProxiesGopherEnable, kSCPropNetProxiesGopherProxy, kSCPropNetProxiesGopherPort); if (r == -1) goto error; CFRelease(proxyDict); return result; error: if (proxyDict) CFRelease(proxyDict); Py_XDECREF(result); return NULL; } static PyMethodDef mod_methods[] = { { "_get_proxy_settings", (PyCFunction)get_proxy_settings, METH_NOARGS, NULL, }, { "_get_proxies", (PyCFunction)get_proxies, METH_NOARGS, NULL, }, { 0, 0, 0, 0 } }; static struct PyModuleDef mod_module = { PyModuleDef_HEAD_INIT, "_scproxy", NULL, -1, mod_methods, NULL, NULL, NULL, NULL }; #ifdef __cplusplus extern "C" { #endif PyObject* PyInit__scproxy(void) { return PyModule_Create(&mod_module); } #ifdef __cplusplus } #endif
