Skip to content

Commit 91edbdd

Browse files
committed
Add _type_marker_str to module_state for teardown
1 parent d21bf2b commit 91edbdd

File tree

3 files changed

+47
-36
lines changed

3 files changed

+47
-36
lines changed

bson/_cbsonmodule.c

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ struct module_state {
5555
PyObject* DatetimeMS;
5656
PyObject* _min_datetime_ms;
5757
PyObject* _max_datetime_ms;
58+
PyObject* _type_marker_str;
5859
};
5960

6061
#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
@@ -378,6 +379,9 @@ static int _load_python_objects(PyObject* module) {
378379
PyObject* compiled = NULL;
379380
struct module_state *state = GETSTATE(module);
380381

382+
/* Python str for faster _type_marker check */
383+
state->_type_marker_str = PyUnicode_FromString("_type_marker");
384+
381385
if (_load_object(&state->Binary, "bson.binary", "Binary") ||
382386
_load_object(&state->Code, "bson.code", "Code") ||
383387
_load_object(&state->ObjectId, "bson.objectid", "ObjectId") ||
@@ -428,13 +432,12 @@ static int _load_python_objects(PyObject* module) {
428432
*
429433
* Return the type marker, 0 if there is no marker, or -1 on failure.
430434
*/
431-
static PyObject *TYPEMARKERSTR;
432-
static long _type_marker(PyObject* object) {
435+
static long _type_marker(PyObject* object, PyObject* _type_marker_str) {
433436
PyObject* type_marker = NULL;
434437
long type = 0;
435438

436-
if (PyObject_HasAttr(object, TYPEMARKERSTR)) {
437-
type_marker = PyObject_GetAttr(object, TYPEMARKERSTR);
439+
if (PyObject_HasAttr(object, _type_marker_str)) {
440+
type_marker = PyObject_GetAttr(object, _type_marker_str);
438441
if (type_marker == NULL) {
439442
return -1;
440443
}
@@ -498,13 +501,12 @@ int cbson_convert_type_registry(PyObject* registry_obj, type_registry_t* registr
498501
return 0;
499502
}
500503

501-
/* Fill out a codec_options_t* from a CodecOptions object. Use with the "O&"
502-
* format spec in PyArg_ParseTuple.
504+
/* Fill out a codec_options_t* from a CodecOptions object.
503505
*
504506
* Return 1 on success. options->document_class is a new reference.
505507
* Return 0 on failure.
506508
*/
507-
int convert_codec_options(PyObject* options_obj, void* p) {
509+
int convert_codec_options(PyObject* self, PyObject* options_obj, void* p) {
508510
codec_options_t* options = (codec_options_t*)p;
509511
PyObject* type_registry_obj = NULL;
510512
long type_marker;
@@ -521,7 +523,8 @@ int convert_codec_options(PyObject* options_obj, void* p) {
521523
&options->datetime_conversion))
522524
return 0;
523525

524-
type_marker = _type_marker(options->document_class);
526+
type_marker = _type_marker(options->document_class,
527+
GETSTATE(self)->_type_marker_str);
525528
if (type_marker < 0) {
526529
return 0;
527530
}
@@ -724,7 +727,7 @@ static int _write_element_to_buffer(PyObject* self, buffer_t buffer,
724727
* problems with python sub interpreters. Our custom types should
725728
* have a _type_marker attribute, which we can switch on instead.
726729
*/
727-
long type = _type_marker(value);
730+
long type = _type_marker(value, state->_type_marker_str);
728731
if (type < 0) {
729732
return 0;
730733
}
@@ -1376,7 +1379,7 @@ int write_dict(PyObject* self, buffer_t buffer,
13761379
long type_marker;
13771380

13781381
/* check for RawBSONDocument */
1379-
type_marker = _type_marker(dict);
1382+
type_marker = _type_marker(dict, state->_type_marker_str);
13801383
if (type_marker < 0) {
13811384
return 0;
13821385
}
@@ -1498,18 +1501,20 @@ static PyObject* _cbson_dict_to_bson(PyObject* self, PyObject* args) {
14981501
PyObject* result;
14991502
unsigned char check_keys;
15001503
unsigned char top_level = 1;
1504+
PyObject* options_obj;
15011505
codec_options_t options;
15021506
buffer_t buffer;
15031507
PyObject* raw_bson_document_bytes_obj;
15041508
long type_marker;
15051509

1506-
if (!PyArg_ParseTuple(args, "ObO&|b", &dict, &check_keys,
1507-
convert_codec_options, &options, &top_level)) {
1510+
if (!(PyArg_ParseTuple(args, "ObO|b", &dict, &check_keys,
1511+
&options_obj, &top_level) &&
1512+
convert_codec_options(self, options_obj, &options))) {
15081513
return NULL;
15091514
}
15101515

15111516
/* check for RawBSONDocument */
1512-
type_marker = _type_marker(dict);
1517+
type_marker = _type_marker(dict, GETSTATE(self)->_type_marker_str);
15131518
if (type_marker < 0) {
15141519
destroy_codec_options(&options);
15151520
return NULL;
@@ -2520,6 +2525,7 @@ static PyObject* _cbson_element_to_dict(PyObject* self, PyObject* args) {
25202525
/* TODO: Support buffer protocol */
25212526
char* string;
25222527
PyObject* bson;
2528+
PyObject* options_obj;
25232529
codec_options_t options;
25242530
unsigned position;
25252531
unsigned max;
@@ -2529,8 +2535,9 @@ static PyObject* _cbson_element_to_dict(PyObject* self, PyObject* args) {
25292535
PyObject* value;
25302536
PyObject* result_tuple;
25312537

2532-
if (!PyArg_ParseTuple(args, "OIIO&p", &bson, &position, &max,
2533-
convert_codec_options, &options, &raw_array)) {
2538+
if (!(PyArg_ParseTuple(args, "OIIOp", &bson, &position, &max,
2539+
&options_obj, &raw_array) &&
2540+
convert_codec_options(self, options_obj, &options))) {
25342541
return NULL;
25352542
}
25362543

@@ -2632,7 +2639,7 @@ static PyObject* _cbson_bson_to_dict(PyObject* self, PyObject* args) {
26322639
Py_buffer view = {0};
26332640

26342641
if (! (PyArg_ParseTuple(args, "OO", &bson, &options_obj) &&
2635-
convert_codec_options(options_obj, &options))) {
2642+
convert_codec_options(self, options_obj, &options))) {
26362643
return result;
26372644
}
26382645

@@ -2709,10 +2716,8 @@ static PyObject* _cbson_decode_all(PyObject* self, PyObject* args) {
27092716
PyObject* options_obj = NULL;
27102717
Py_buffer view = {0};
27112718

2712-
if (!PyArg_ParseTuple(args, "OO", &bson, &options_obj)) {
2713-
return NULL;
2714-
}
2715-
if (!convert_codec_options(options_obj, &options)) {
2719+
if (!(PyArg_ParseTuple(args, "OO", &bson, &options_obj) &&
2720+
convert_codec_options(self, options_obj, &options))) {
27162721
return NULL;
27172722
}
27182723

@@ -2960,6 +2965,7 @@ static int _cbson_clear(PyObject *m) {
29602965
Py_CLEAR(GETSTATE(m)->MaxKey);
29612966
Py_CLEAR(GETSTATE(m)->UTC);
29622967
Py_CLEAR(GETSTATE(m)->REType);
2968+
Py_CLEAR(GETSTATE(m)->_type_marker_str);
29632969
return 0;
29642970
}
29652971

@@ -3025,7 +3031,5 @@ PyInit__cbson(void)
30253031
INITERROR;
30263032
}
30273033

3028-
TYPEMARKERSTR = PyUnicode_FromString("_type_marker");
3029-
30303034
return m;
30313035
}

bson/_cbsonmodule.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ typedef struct codec_options_t {
8686

8787
#define _cbson_convert_codec_options_INDEX 4
8888
#define _cbson_convert_codec_options_RETURN int
89-
#define _cbson_convert_codec_options_PROTO (PyObject* options_obj, void* p)
89+
#define _cbson_convert_codec_options_PROTO (PyObject* self, PyObject* options_obj, void* p)
9090

9191
#define _cbson_destroy_codec_options_INDEX 5
9292
#define _cbson_destroy_codec_options_RETURN void

pymongo/_cmessagemodule.c

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -75,19 +75,21 @@ static PyObject* _cbson_query_message(PyObject* self, PyObject* args) {
7575
int num_to_return;
7676
PyObject* query;
7777
PyObject* field_selector;
78+
PyObject* options_obj;
7879
codec_options_t options;
7980
buffer_t buffer = NULL;
8081
int length_location, message_length;
8182
PyObject* result = NULL;
8283

83-
if (!PyArg_ParseTuple(args, "Iet#iiOOO&",
84+
if (!(PyArg_ParseTuple(args, "Iet#iiOOO",
8485
&flags,
8586
"utf-8",
8687
&collection_name,
8788
&collection_name_length,
8889
&num_to_skip, &num_to_return,
8990
&query, &field_selector,
90-
convert_codec_options, &options)) {
91+
&options_obj) &&
92+
convert_codec_options(state->_cbson, options_obj, &options))) {
9193
return NULL;
9294
}
9395
buffer = pymongo_buffer_new();
@@ -220,6 +222,7 @@ static PyObject* _cbson_op_msg(PyObject* self, PyObject* args) {
220222
Py_ssize_t identifier_length = 0;
221223
PyObject* docs;
222224
PyObject* doc;
225+
PyObject* options_obj;
223226
codec_options_t options;
224227
buffer_t buffer = NULL;
225228
int length_location, message_length;
@@ -229,14 +232,15 @@ static PyObject* _cbson_op_msg(PyObject* self, PyObject* args) {
229232
PyObject* iterator = NULL;
230233

231234
/*flags, command, identifier, docs, opts*/
232-
if (!PyArg_ParseTuple(args, "IOet#OO&",
235+
if (!(PyArg_ParseTuple(args, "IOet#OO",
233236
&flags,
234237
&command,
235238
"utf-8",
236239
&identifier,
237240
&identifier_length,
238241
&docs,
239-
convert_codec_options, &options)) {
242+
&options_obj) &&
243+
convert_codec_options(state->_cbson, options_obj, &options))) {
240244
return NULL;
241245
}
242246
buffer = pymongo_buffer_new();
@@ -528,14 +532,15 @@ _cbson_encode_batched_op_msg(PyObject* self, PyObject* args) {
528532
PyObject* ctx = NULL;
529533
PyObject* to_publish = NULL;
530534
PyObject* result = NULL;
535+
PyObject* options_obj;
531536
codec_options_t options;
532537
buffer_t buffer;
533538
struct module_state *state = GETSTATE(self);
534539

535-
if (!PyArg_ParseTuple(args, "bOObO&O",
540+
if (!(PyArg_ParseTuple(args, "bOObOO",
536541
&op, &command, &docs, &ack,
537-
convert_codec_options, &options,
538-
&ctx)) {
542+
&options_obj, &ctx) &&
543+
convert_codec_options(state->_cbson, options_obj, &options))) {
539544
return NULL;
540545
}
541546
if (!(buffer = pymongo_buffer_new())) {
@@ -581,14 +586,15 @@ _cbson_batched_op_msg(PyObject* self, PyObject* args) {
581586
PyObject* ctx = NULL;
582587
PyObject* to_publish = NULL;
583588
PyObject* result = NULL;
589+
PyObject* options_obj;
584590
codec_options_t options;
585591
buffer_t buffer;
586592
struct module_state *state = GETSTATE(self);
587593

588-
if (!PyArg_ParseTuple(args, "bOObO&O",
594+
if (!(PyArg_ParseTuple(args, "bOObOO",
589595
&op, &command, &docs, &ack,
590-
convert_codec_options, &options,
591-
&ctx)) {
596+
&options_obj, &ctx) &&
597+
convert_codec_options(state->_cbson, options_obj, &options))) {
592598
return NULL;
593599
}
594600
if (!(buffer = pymongo_buffer_new())) {
@@ -850,14 +856,15 @@ _cbson_encode_batched_write_command(PyObject* self, PyObject* args) {
850856
PyObject* ctx = NULL;
851857
PyObject* to_publish = NULL;
852858
PyObject* result = NULL;
859+
PyObject* options_obj;
853860
codec_options_t options;
854861
buffer_t buffer;
855862
struct module_state *state = GETSTATE(self);
856863

857-
if (!PyArg_ParseTuple(args, "et#bOOO&O", "utf-8",
864+
if (!(PyArg_ParseTuple(args, "et#bOOOO", "utf-8",
858865
&ns, &ns_len, &op, &command, &docs,
859-
convert_codec_options, &options,
860-
&ctx)) {
866+
&options_obj, &ctx) &&
867+
convert_codec_options(state->_cbson, options_obj, &options))) {
861868
return NULL;
862869
}
863870
if (!(buffer = pymongo_buffer_new())) {

0 commit comments

Comments
 (0)