Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit afe55bb

Browse files
committed
Add API for static strings, primarily good for identifiers.
Thanks to Konrad Schöbel and Jasper Schulz for helping with the mass-editing.
1 parent 67df285 commit afe55bb

50 files changed

Lines changed: 571 additions & 233 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Include/abstract.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ extern "C" {
77
#ifdef PY_SSIZE_T_CLEAN
88
#define PyObject_CallFunction _PyObject_CallFunction_SizeT
99
#define PyObject_CallMethod _PyObject_CallMethod_SizeT
10+
#define _PyObject_CallMethodId _PyObject_CallMethodId_SizeT
1011
#endif
1112

1213
/* Abstract Object Interface (many thanks to Jim Fulton) */
@@ -307,11 +308,22 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
307308
Python expression: o.method(args).
308309
*/
309310

311+
PyAPI_FUNC(PyObject *) _PyObject_CallMethodId(PyObject *o, _Py_Identifier *method,
312+
char *format, ...);
313+
314+
/*
315+
Like PyObject_CallMethod, but expect a _Py_Identifier* as the
316+
method name.
317+
*/
318+
310319
PyAPI_FUNC(PyObject *) _PyObject_CallFunction_SizeT(PyObject *callable,
311320
char *format, ...);
312321
PyAPI_FUNC(PyObject *) _PyObject_CallMethod_SizeT(PyObject *o,
313322
char *name,
314323
char *format, ...);
324+
PyAPI_FUNC(PyObject *) _PyObject_CallMethodId_SizeT(PyObject *o,
325+
_Py_Identifier *name,
326+
char *format, ...);
315327

316328
PyAPI_FUNC(PyObject *) PyObject_CallFunctionObjArgs(PyObject *callable,
317329
...);

Include/object.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,7 @@ PyAPI_FUNC(unsigned int) PyType_ClearCache(void);
454454
PyAPI_FUNC(void) PyType_Modified(PyTypeObject *);
455455

456456
/* Generic operations on objects */
457+
struct _Py_Identifier;
457458
#ifndef Py_LIMITED_API
458459
PyAPI_FUNC(int) PyObject_Print(PyObject *, FILE *, int);
459460
PyAPI_FUNC(void) _Py_BreakPoint(void);
@@ -471,6 +472,9 @@ PyAPI_FUNC(int) PyObject_HasAttrString(PyObject *, const char *);
471472
PyAPI_FUNC(PyObject *) PyObject_GetAttr(PyObject *, PyObject *);
472473
PyAPI_FUNC(int) PyObject_SetAttr(PyObject *, PyObject *, PyObject *);
473474
PyAPI_FUNC(int) PyObject_HasAttr(PyObject *, PyObject *);
475+
PyAPI_FUNC(PyObject *) _PyObject_GetAttrId(PyObject *, struct _Py_Identifier *);
476+
PyAPI_FUNC(int) _PyObject_SetAttrId(PyObject *, struct _Py_Identifier *, PyObject *);
477+
PyAPI_FUNC(int) _PyObject_HasAttrId(PyObject *, struct _Py_Identifier *);
474478
#ifndef Py_LIMITED_API
475479
PyAPI_FUNC(PyObject **) _PyObject_GetDictPtr(PyObject *);
476480
#endif

Include/unicodeobject.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2024,6 +2024,40 @@ PyAPI_FUNC(int) _PyUnicode_CheckConsistency(
20242024
int check_content);
20252025
#endif
20262026

2027+
/********************* String Literals ****************************************/
2028+
/* This structure helps managing static strings. The basic usage goes like this:
2029+
Instead of doing
2030+
2031+
r = PyObject_CallMethod(o, "foo", "args", ...);
2032+
2033+
do
2034+
2035+
_Py_identifier(foo);
2036+
...
2037+
r = _PyObject_CallMethodId(o, &PyId_foo, "args", ...);
2038+
2039+
PyId_foo is a static variable, either on block level or file level. On first
2040+
usage, the string "foo" is interned, and the structures are linked. On interpreter
2041+
shutdown, all strings are released (through _PyUnicode_ClearStaticStrings).
2042+
2043+
Alternatively, _Py_static_string allows to choose the variable name.
2044+
_PyUnicode_FromId returns a new reference to the interned string.
2045+
_PyObject_{Get,Set,Has}AttrId are __getattr__ versions using _Py_Identifier*.
2046+
*/
2047+
typedef struct _Py_Identifier {
2048+
struct _Py_Identifier *next;
2049+
const char* string;
2050+
PyObject *object;
2051+
} _Py_Identifier;
2052+
2053+
#define _Py_static_string(varname, value) static _Py_Identifier varname = { 0, value, 0 };
2054+
#define _Py_identifier(varname) _Py_static_string(PyId_##varname, #varname)
2055+
2056+
/* Return an interned Unicode object for an Identifier; may fail if there is no memory.*/
2057+
PyAPI_FUNC(PyObject*) _PyUnicode_FromId(_Py_Identifier*);
2058+
/* Clear all static strings. */
2059+
PyAPI_FUNC(void) _PyUnicode_ClearStaticStrings(void);
2060+
20272061
#ifdef __cplusplus
20282062
}
20292063
#endif

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ What's New in Python 3.3 Alpha 1?
1010
Core and Builtins
1111
-----------------
1212

13+
- Add internal API for static strings (_Py_identifier et.al.).
14+
1315
- Issue #13063: the Windows error ERROR_NO_DATA (numbered 232 and described
1416
as "The pipe is being closed") is now mapped to POSIX errno EPIPE
1517
(previously EINVAL).

Modules/_bisectmodule.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,9 @@ insort_right(PyObject *self, PyObject *args, PyObject *kw)
8686
if (PyList_Insert(list, index, item) < 0)
8787
return NULL;
8888
} else {
89-
result = PyObject_CallMethod(list, "insert", "nO", index, item);
89+
_Py_identifier(insert);
90+
91+
result = _PyObject_CallMethodId(list, &PyId_insert, "nO", index, item);
9092
if (result == NULL)
9193
return NULL;
9294
Py_DECREF(result);
@@ -186,7 +188,9 @@ insort_left(PyObject *self, PyObject *args, PyObject *kw)
186188
if (PyList_Insert(list, index, item) < 0)
187189
return NULL;
188190
} else {
189-
result = PyObject_CallMethod(list, "insert", "iO", index, item);
191+
_Py_identifier(insert);
192+
193+
result = _PyObject_CallMethodId(list, &PyId_insert, "iO", index, item);
190194
if (result == NULL)
191195
return NULL;
192196
Py_DECREF(result);

Modules/_collectionsmodule.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1334,13 +1334,15 @@ defdict_reduce(defdictobject *dd)
13341334
PyObject *items;
13351335
PyObject *iter;
13361336
PyObject *result;
1337+
_Py_identifier(items);
1338+
13371339
if (dd->default_factory == NULL || dd->default_factory == Py_None)
13381340
args = PyTuple_New(0);
13391341
else
13401342
args = PyTuple_Pack(1, dd->default_factory);
13411343
if (args == NULL)
13421344
return NULL;
1343-
items = PyObject_CallMethod((PyObject *)dd, "items", "()");
1345+
items = _PyObject_CallMethodId((PyObject *)dd, &PyId_items, "()");
13441346
if (items == NULL) {
13451347
Py_DECREF(args);
13461348
return NULL;

Modules/_ctypes/_ctypes.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3679,8 +3679,10 @@ _build_result(PyObject *result, PyObject *callargs,
36793679
PyTuple_SET_ITEM(tup, index, v);
36803680
index++;
36813681
} else if (bit & outmask) {
3682+
_Py_identifier(__ctypes_from_outparam__);
3683+
36823684
v = PyTuple_GET_ITEM(callargs, i);
3683-
v = PyObject_CallMethod(v, "__ctypes_from_outparam__", NULL);
3685+
v = _PyObject_CallMethodId(v, &PyId___ctypes_from_outparam__, NULL);
36843686
if (v == NULL || numretvals == 1) {
36853687
Py_DECREF(callargs);
36863688
return v;

Modules/_ctypes/callproc.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1687,13 +1687,15 @@ unpickle(PyObject *self, PyObject *args)
16871687
PyObject *state;
16881688
PyObject *result;
16891689
PyObject *tmp;
1690+
_Py_identifier(__new__);
1691+
_Py_identifier(__setstate__);
16901692

16911693
if (!PyArg_ParseTuple(args, "OO", &typ, &state))
16921694
return NULL;
1693-
result = PyObject_CallMethod(typ, "__new__", "O", typ);
1695+
result = _PyObject_CallMethodId(typ, &PyId___new__, "O", typ);
16941696
if (result == NULL)
16951697
return NULL;
1696-
tmp = PyObject_CallMethod(result, "__setstate__", "O", state);
1698+
tmp = _PyObject_CallMethodId(result, &PyId___setstate__, "O", state);
16971699
if (tmp == NULL) {
16981700
Py_DECREF(result);
16991701
return NULL;

Modules/_cursesmodule.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1418,10 +1418,12 @@ PyCursesWindow_PutWin(PyCursesWindowObject *self, PyObject *stream)
14181418
while (1) {
14191419
char buf[BUFSIZ];
14201420
Py_ssize_t n = fread(buf, 1, BUFSIZ, fp);
1421+
_Py_identifier(write);
1422+
14211423
if (n <= 0)
14221424
break;
14231425
Py_DECREF(res);
1424-
res = PyObject_CallMethod(stream, "write", "y#", buf, n);
1426+
res = _PyObject_CallMethodId(stream, &PyId_write, "y#", buf, n);
14251427
if (res == NULL)
14261428
break;
14271429
}
@@ -1911,6 +1913,7 @@ PyCurses_GetWin(PyCursesWindowObject *self, PyObject *stream)
19111913
WINDOW *win;
19121914

19131915
PyCursesInitialised;
1916+
_Py_identifier(read);
19141917

19151918
strcpy(fn, "/tmp/py.curses.getwin.XXXXXX");
19161919
fd = mkstemp(fn);
@@ -1922,7 +1925,7 @@ PyCurses_GetWin(PyCursesWindowObject *self, PyObject *stream)
19221925
remove(fn);
19231926
return PyErr_SetFromErrnoWithFilename(PyExc_IOError, fn);
19241927
}
1925-
data = PyObject_CallMethod(stream, "read", "");
1928+
data = _PyObject_CallMethodId(stream, &PyId_read, "");
19261929
if (data == NULL) {
19271930
fclose(fp);
19281931
remove(fn);

0 commit comments

Comments
 (0)