18
18
#define PY_GET_TYPE (Obj ) ((Obj)->ob_type)
19
19
#endif
20
20
21
- static PyObject * BrotliError ;
21
+ static const char kErrorAttr [] = "error" ;
22
+ static const char kModuleAttr [] = "_module" ;
22
23
23
24
static const char kInvalidBufferError [] =
24
25
"brotli: data must be a C-contiguous buffer" ;
@@ -195,8 +196,26 @@ PyDoc_STRVAR(brotli_doc,
195
196
"Implementation module for the Brotli library." );
196
197
/* clang-format on */
197
198
198
- static void set_brotli_exception (const char * msg ) {
199
- PyErr_SetString (BrotliError , msg );
199
+ static void set_brotli_exception (PyObject * context , const char * msg ) {
200
+ assert (context != NULL );
201
+ PyObject * module = NULL ;
202
+ PyObject * type = NULL ;
203
+ PyObject * error = NULL ;
204
+ if (PyModule_Check (context )) {
205
+ module = context ;
206
+ } else if (PyType_Check (context )) {
207
+ type = context ;
208
+ } else {
209
+ type = (PyObject * )PY_GET_TYPE (context );
210
+ assert (type != NULL );
211
+ }
212
+ if (type ) {
213
+ module = PyObject_GetAttrString (type , kModuleAttr );
214
+ }
215
+ assert (module != NULL );
216
+ error = PyObject_GetAttrString (module , kErrorAttr );
217
+ assert (error != NULL );
218
+ PyErr_SetString (error , msg );
200
219
}
201
220
202
221
/*
@@ -354,7 +373,7 @@ static PyObject* brotli_Compressor_new(PyTypeObject* type, PyObject* args,
354
373
self -> processing = 0 ;
355
374
self -> enc = BrotliEncoderCreateInstance (0 , 0 , 0 );
356
375
if (self -> enc == NULL ) {
357
- set_brotli_exception (kCompressCreateError );
376
+ set_brotli_exception (( PyObject * ) type , kCompressCreateError );
358
377
PY_GET_TYPE (self )-> tp_free ((PyObject * )self );
359
378
return NULL ;
360
379
}
@@ -386,30 +405,30 @@ static int brotli_Compressor_init(PyBrotli_Compressor* self, PyObject* args,
386
405
if ((mode == 0 ) || (mode == 1 ) || (mode == 2 )) {
387
406
BrotliEncoderSetParameter (self -> enc , BROTLI_PARAM_MODE , (uint32_t )mode );
388
407
} else {
389
- set_brotli_exception (kInvalidModeError );
408
+ set_brotli_exception (( PyObject * ) self , kInvalidModeError );
390
409
self -> healthy = 0 ;
391
410
return -1 ;
392
411
}
393
412
if (quality <= 11 ) {
394
413
BrotliEncoderSetParameter (self -> enc , BROTLI_PARAM_QUALITY ,
395
414
(uint32_t )quality );
396
415
} else {
397
- set_brotli_exception (kInvalidQualityError );
416
+ set_brotli_exception (( PyObject * ) self , kInvalidQualityError );
398
417
self -> healthy = 0 ;
399
418
return -1 ;
400
419
}
401
420
if ((10 <= lgwin ) && (lgwin <= 24 )) {
402
421
BrotliEncoderSetParameter (self -> enc , BROTLI_PARAM_LGWIN , (uint32_t )lgwin );
403
422
} else {
404
- set_brotli_exception (kInvalidLgwinError );
423
+ set_brotli_exception (( PyObject * ) self , kInvalidLgwinError );
405
424
self -> healthy = 0 ;
406
425
return -1 ;
407
426
}
408
427
if ((lgblock == 0 ) || ((16 <= lgblock ) && (lgblock <= 24 ))) {
409
428
BrotliEncoderSetParameter (self -> enc , BROTLI_PARAM_LGBLOCK ,
410
429
(uint32_t )lgblock );
411
430
} else {
412
- set_brotli_exception (kInvalidLgblockError );
431
+ set_brotli_exception (( PyObject * ) self , kInvalidLgblockError );
413
432
self -> healthy = 0 ;
414
433
return -1 ;
415
434
}
@@ -471,7 +490,7 @@ static PyObject* compress_stream(PyBrotli_Compressor* self,
471
490
ret = Buffer_Finish (& buffer );
472
491
if (ret == NULL ) oom = 1 ;
473
492
} else { /* Not ok */
474
- set_brotli_exception (kCompressError );
493
+ set_brotli_exception (( PyObject * ) self , kCompressError );
475
494
}
476
495
477
496
error :
@@ -495,11 +514,11 @@ static PyObject* brotli_Compressor_process(PyBrotli_Compressor* self,
495
514
Py_buffer input ;
496
515
497
516
if (self -> healthy == 0 ) {
498
- set_brotli_exception (kCompressUnhealthyError );
517
+ set_brotli_exception (( PyObject * ) self , kCompressUnhealthyError );
499
518
return NULL ;
500
519
}
501
520
if (self -> processing != 0 ) {
502
- set_brotli_exception (kCompressConcurrentError );
521
+ set_brotli_exception (( PyObject * ) self , kCompressConcurrentError );
503
522
return NULL ;
504
523
}
505
524
@@ -522,11 +541,11 @@ static PyObject* brotli_Compressor_flush(PyBrotli_Compressor* self) {
522
541
PyObject * ret = NULL ;
523
542
524
543
if (self -> healthy == 0 ) {
525
- set_brotli_exception (kCompressUnhealthyError );
544
+ set_brotli_exception (( PyObject * ) self , kCompressUnhealthyError );
526
545
return NULL ;
527
546
}
528
547
if (self -> processing != 0 ) {
529
- set_brotli_exception (kCompressConcurrentError );
548
+ set_brotli_exception (( PyObject * ) self , kCompressConcurrentError );
530
549
return NULL ;
531
550
}
532
551
@@ -540,11 +559,11 @@ static PyObject* brotli_Compressor_finish(PyBrotli_Compressor* self) {
540
559
PyObject * ret = NULL ;
541
560
542
561
if (self -> healthy == 0 ) {
543
- set_brotli_exception (kCompressUnhealthyError );
562
+ set_brotli_exception (( PyObject * ) self , kCompressUnhealthyError );
544
563
return NULL ;
545
564
}
546
565
if (self -> processing != 0 ) {
547
- set_brotli_exception (kCompressConcurrentError );
566
+ set_brotli_exception (( PyObject * ) self , kCompressConcurrentError );
548
567
return NULL ;
549
568
}
550
569
@@ -578,7 +597,7 @@ static PyObject* brotli_Decompressor_new(PyTypeObject* type, PyObject* args,
578
597
579
598
self -> dec = BrotliDecoderCreateInstance (0 , 0 , 0 );
580
599
if (self -> dec == NULL ) {
581
- set_brotli_exception (kDecompressCreateError );
600
+ set_brotli_exception (( PyObject * ) type , kDecompressCreateError );
582
601
PY_GET_TYPE (self )-> tp_free ((PyObject * )self );
583
602
return NULL ;
584
603
}
@@ -633,11 +652,11 @@ static PyObject* brotli_Decompressor_process(PyBrotli_Decompressor* self,
633
652
int oom = 0 ;
634
653
635
654
if (self -> healthy == 0 ) {
636
- set_brotli_exception (kDecompressUnhealthyError );
655
+ set_brotli_exception (( PyObject * ) self , kDecompressUnhealthyError );
637
656
return NULL ;
638
657
}
639
658
if (self -> processing != 0 ) {
640
- set_brotli_exception (kDecompressConcurrentError );
659
+ set_brotli_exception (( PyObject * ) self , kDecompressConcurrentError );
641
660
return NULL ;
642
661
}
643
662
@@ -654,7 +673,7 @@ static PyObject* brotli_Decompressor_process(PyBrotli_Decompressor* self,
654
673
655
674
if (self -> unconsumed_data_length > 0 ) {
656
675
if (input .len > 0 ) {
657
- set_brotli_exception (kDecompressSinkError );
676
+ set_brotli_exception (( PyObject * ) self , kDecompressSinkError );
658
677
goto finally ;
659
678
}
660
679
next_in = self -> unconsumed_data ;
@@ -693,7 +712,7 @@ static PyObject* brotli_Decompressor_process(PyBrotli_Decompressor* self,
693
712
if (oom ) {
694
713
goto finally ;
695
714
} else if (result == BROTLI_DECODER_RESULT_ERROR ) {
696
- set_brotli_exception (kDecompressError );
715
+ set_brotli_exception (( PyObject * ) self , kDecompressError );
697
716
goto finally ;
698
717
}
699
718
@@ -712,7 +731,7 @@ static PyObject* brotli_Decompressor_process(PyBrotli_Decompressor* self,
712
731
713
732
if ((result == BROTLI_DECODER_RESULT_SUCCESS ) && (avail_in > 0 )) {
714
733
/* TODO(eustas): Add API to ignore / fetch unused "tail"? */
715
- set_brotli_exception (kDecompressError );
734
+ set_brotli_exception (( PyObject * ) self , kDecompressError );
716
735
goto finally ;
717
736
}
718
737
@@ -742,11 +761,11 @@ static PyObject* brotli_Decompressor_process(PyBrotli_Decompressor* self,
742
761
743
762
static PyObject * brotli_Decompressor_is_finished (PyBrotli_Decompressor * self ) {
744
763
if (self -> healthy == 0 ) {
745
- set_brotli_exception (kDecompressUnhealthyError );
764
+ set_brotli_exception (( PyObject * ) self , kDecompressUnhealthyError );
746
765
return NULL ;
747
766
}
748
767
if (self -> processing != 0 ) {
749
- set_brotli_exception (kDecompressConcurrentError );
768
+ set_brotli_exception (( PyObject * ) self , kDecompressConcurrentError );
750
769
return NULL ;
751
770
}
752
771
if (BrotliDecoderIsFinished (self -> dec )) {
@@ -759,11 +778,11 @@ static PyObject* brotli_Decompressor_is_finished(PyBrotli_Decompressor* self) {
759
778
static PyObject * brotli_Decompressor_can_accept_more_data (
760
779
PyBrotli_Decompressor * self ) {
761
780
if (self -> healthy == 0 ) {
762
- set_brotli_exception (kDecompressUnhealthyError );
781
+ set_brotli_exception (( PyObject * ) self , kDecompressUnhealthyError );
763
782
return NULL ;
764
783
}
765
784
if (self -> processing != 0 ) {
766
- set_brotli_exception (kDecompressConcurrentError );
785
+ set_brotli_exception (( PyObject * ) self , kDecompressConcurrentError );
767
786
return NULL ;
768
787
}
769
788
if (self -> unconsumed_data_length > 0 ) {
@@ -832,7 +851,7 @@ static PyObject* brotli_decompress(PyObject* self, PyObject* args,
832
851
if (oom ) {
833
852
goto finally ;
834
853
} else if (result != BROTLI_DECODER_RESULT_SUCCESS || available_in > 0 ) {
835
- set_brotli_exception (kDecompressError );
854
+ set_brotli_exception (( PyObject * ) self , kDecompressError );
836
855
goto finally ;
837
856
}
838
857
@@ -1032,16 +1051,15 @@ PyMODINIT_FUNC INIT_BROTLI(void) {
1032
1051
PyObject * error_type = NULL ;
1033
1052
PyObject * compressor_type = NULL ;
1034
1053
PyObject * decompressor_type = NULL ;
1054
+ PyObject * obj = NULL ; /* Dangling ref, don't deref this one. */
1035
1055
1036
1056
if (m == NULL ) goto error ;
1037
1057
1038
1058
error_type = PyErr_NewExceptionWithDoc ((char * )"brotli.error" ,
1039
1059
brotli_error_doc , NULL , NULL );
1040
1060
if (error_type == NULL ) goto error ;
1041
1061
1042
- if (RegisterObject (m , "error" , error_type ) < 0 ) goto error ;
1043
- /* Assumption: pointer is used only while module is alive and well. */
1044
- BrotliError = error_type ;
1062
+ if (RegisterObject (m , kErrorAttr , error_type ) < 0 ) goto error ;
1045
1063
error_type = NULL ;
1046
1064
1047
1065
#if PY_MAJOR_VERSION >= 3
@@ -1056,12 +1074,16 @@ PyMODINIT_FUNC INIT_BROTLI(void) {
1056
1074
if (compressor_type == NULL ) goto error ;
1057
1075
if (PyType_Ready ((PyTypeObject * )compressor_type ) < 0 ) goto error ;
1058
1076
if (RegisterObject (m , "Compressor" , compressor_type ) < 0 ) goto error ;
1077
+ obj = compressor_type ;
1059
1078
compressor_type = NULL ;
1079
+ if (PyObject_SetAttrString (obj , kModuleAttr , m ) < 0 ) goto error ;
1060
1080
1061
1081
if (decompressor_type == NULL ) goto error ;
1062
1082
if (PyType_Ready ((PyTypeObject * )decompressor_type ) < 0 ) goto error ;
1063
1083
if (RegisterObject (m , "Decompressor" , decompressor_type ) < 0 ) goto error ;
1084
+ obj = decompressor_type ;
1064
1085
decompressor_type = NULL ;
1086
+ if (PyObject_SetAttrString (obj , kModuleAttr , m ) < 0 ) goto error ;
1065
1087
1066
1088
PyModule_AddIntConstant (m , "MODE_GENERIC" , (int )BROTLI_MODE_GENERIC );
1067
1089
PyModule_AddIntConstant (m , "MODE_TEXT" , (int )BROTLI_MODE_TEXT );
0 commit comments