Skip to content

Commit c9362e3

Browse files
committed
Implement interleaving, hash functions and *args __init__
1 parent 4d172c2 commit c9362e3

File tree

2 files changed

+90
-10
lines changed

2 files changed

+90
-10
lines changed

Objects/interpolationobject.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,19 @@ interpolation_compare(interpolationobject *self, PyObject *other, int op)
9898
return PyBool_FromLong(op == Py_EQ ? eq : !eq);
9999
}
100100

101+
static Py_hash_t
102+
interpolation_hash(interpolationobject *self)
103+
{
104+
PyObject *tuple = PyTuple_Pack(4, self->value, self->expr, self->conv, self->format_spec);
105+
if (!tuple) {
106+
return -1;
107+
}
108+
109+
Py_hash_t hash = PyObject_Hash(tuple);
110+
Py_DECREF(tuple);
111+
return hash;
112+
}
113+
101114
static PyMemberDef interpolation_members[] = {
102115
{"value", Py_T_OBJECT_EX, offsetof(interpolationobject, value), Py_READONLY, "Value"},
103116
{"expr", Py_T_OBJECT_EX, offsetof(interpolationobject, expr), Py_READONLY, "Expr"},
@@ -117,6 +130,7 @@ PyTypeObject _PyInterpolation_Type = {
117130
.tp_dealloc = (destructor) interpolation_dealloc,
118131
.tp_repr = (reprfunc) interpolation_repr,
119132
.tp_richcompare = (richcmpfunc) interpolation_compare,
133+
.tp_hash = (hashfunc) interpolation_hash,
120134
.tp_members = interpolation_members,
121135
};
122136

Objects/templateobject.c

Lines changed: 76 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22
#include "Python.h"
33
#include <stddef.h>
44

5+
#include "pycore_global_objects.h" // _Py_STR
6+
#include "pycore_runtime.h" // _Py_STR
7+
58
#include "pycore_template.h"
9+
#include "pycore_interpolation.h"
610

711
typedef struct {
812
PyObject_HEAD
@@ -17,16 +21,71 @@ template_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1721
return NULL;
1822
}
1923

20-
static char *kwlist[] = {"args", NULL};
21-
PyObject *selfargs;
22-
23-
if (PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist,
24-
&selfargs) < 0) {
25-
Py_DECREF(self);
24+
Py_ssize_t argslen = PyTuple_GET_SIZE(args);
25+
Py_ssize_t interleaved_len = 0;
26+
int last_was_str = 0;
27+
28+
for (Py_ssize_t i = 0; i < argslen; i++) {
29+
PyObject *item = PyTuple_GET_ITEM(args, i);
30+
if (PyUnicode_Check(item)) {
31+
if (!last_was_str) {
32+
interleaved_len++;
33+
}
34+
last_was_str = 1;
35+
}
36+
else if (PyObject_TypeCheck(item, &_PyInterpolation_Type)) {
37+
if (!last_was_str) {
38+
interleaved_len++;
39+
}
40+
interleaved_len++;
41+
last_was_str = 0;
42+
}
43+
else {
44+
PyErr_SetString(PyExc_TypeError, "Template items need to be of type 'str' or 'Interpolation'");
45+
return NULL;
46+
}
47+
}
48+
if (!last_was_str) {
49+
interleaved_len++;
50+
}
51+
52+
PyObject *interleaved = PyTuple_New(interleaved_len);
53+
if (!interleaved) {
2654
return NULL;
2755
}
2856

29-
Py_XSETREF(self->args, Py_NewRef(selfargs));
57+
last_was_str = 0;
58+
Py_ssize_t j = 0;
59+
for (Py_ssize_t i = 0; i < argslen; i++) {
60+
PyObject *item = PyTuple_GET_ITEM(args, i);
61+
if (PyUnicode_Check(item)) {
62+
if (last_was_str) {
63+
PyObject *concat = PyUnicode_Concat(PyTuple_GET_ITEM(interleaved, j - 1), item);
64+
if (!concat) {
65+
Py_DECREF(interleaved);
66+
return NULL;
67+
}
68+
PyTuple_SetItem(interleaved, j - 1, concat);
69+
}
70+
else {
71+
PyTuple_SET_ITEM(interleaved, j++, Py_NewRef(item));
72+
}
73+
last_was_str = 1;
74+
}
75+
else if (PyObject_TypeCheck(item, &_PyInterpolation_Type)) {
76+
if (!last_was_str) {
77+
PyTuple_SET_ITEM(interleaved, j++, &_Py_STR(empty));
78+
}
79+
PyTuple_SET_ITEM(interleaved, j++, Py_NewRef(item));
80+
last_was_str = 0;
81+
}
82+
}
83+
if (!last_was_str) {
84+
PyTuple_SET_ITEM(interleaved, j++, &_Py_STR(empty));
85+
}
86+
87+
assert(j == interleaved_len);
88+
Py_XSETREF(self->args, interleaved);
3089
return self;
3190
}
3291

@@ -59,6 +118,12 @@ template_compare(templateobject *self, PyObject *other, int op)
59118
return PyObject_RichCompare(self->args, ((templateobject *) other)->args, op);
60119
}
61120

121+
static Py_hash_t
122+
template_hash(templateobject *self)
123+
{
124+
return PyObject_Hash(self->args);
125+
}
126+
62127
static PyObject *
63128
template_add_template_str(templateobject *template, PyUnicodeObject *str, int templateleft)
64129
{
@@ -81,7 +146,7 @@ template_add_template_str(templateobject *template, PyUnicodeObject *str, int te
81146
PyTuple_SET_ITEM(tuple, i + j, Py_NewRef(str));
82147
}
83148

84-
PyObject *newtemplate = PyObject_CallOneArg((PyObject *) &_PyTemplate_Type, tuple);
149+
PyObject *newtemplate = PyObject_CallObject((PyObject *) &_PyTemplate_Type, tuple);
85150
Py_DECREF(tuple);
86151
return newtemplate;
87152
}
@@ -105,7 +170,7 @@ template_add_templates(templateobject *self, templateobject *other)
105170
PyTuple_SET_ITEM(tuple, i + j, Py_NewRef(PyTuple_GET_ITEM(other->args, j)));
106171
}
107172

108-
PyObject *newtemplate = PyObject_CallOneArg((PyObject *) &_PyTemplate_Type, tuple);
173+
PyObject *newtemplate = PyObject_CallObject((PyObject *) &_PyTemplate_Type, tuple);
109174
Py_DECREF(tuple);
110175
return newtemplate;
111176
}
@@ -149,6 +214,7 @@ PyTypeObject _PyTemplate_Type = {
149214
.tp_dealloc = (destructor) template_dealloc,
150215
.tp_repr = (reprfunc) template_repr,
151216
.tp_richcompare = (richcmpfunc) template_compare,
217+
.tp_hash = (hashfunc) template_hash,
152218
.tp_members = template_members,
153219
};
154220

@@ -164,7 +230,7 @@ _PyTemplate_Create(PyObject **values, Py_ssize_t oparg)
164230
PyTuple_SET_ITEM(tuple, i, Py_NewRef(values[i]));
165231
}
166232

167-
PyObject *template = PyObject_CallOneArg((PyObject *) &_PyTemplate_Type, tuple);
233+
PyObject *template = PyObject_CallObject((PyObject *) &_PyTemplate_Type, tuple);
168234
Py_DECREF(tuple);
169235
return template;
170236
}

0 commit comments

Comments
 (0)