_multidict.c 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646
  1. #include "Python.h"
  2. #include "structmember.h"
  3. // Include order important
  4. #include "_multilib/defs.h"
  5. #include "_multilib/istr.h"
  6. #include "_multilib/pair_list.h"
  7. #include "_multilib/dict.h"
  8. #include "_multilib/iter.h"
  9. #include "_multilib/views.h"
  10. static PyObject *collections_abc_mapping;
  11. static PyObject *collections_abc_mut_mapping;
  12. static PyObject *collections_abc_mut_multi_mapping;
  13. static PyTypeObject multidict_type;
  14. static PyTypeObject cimultidict_type;
  15. static PyTypeObject multidict_proxy_type;
  16. static PyTypeObject cimultidict_proxy_type;
  17. static PyObject *repr_func;
  18. #define MultiDict_CheckExact(o) (Py_TYPE(o) == &multidict_type)
  19. #define CIMultiDict_CheckExact(o) (Py_TYPE(o) == &cimultidict_type)
  20. #define MultiDictProxy_CheckExact(o) (Py_TYPE(o) == &multidict_proxy_type)
  21. #define CIMultiDictProxy_CheckExact(o) (Py_TYPE(o) == &cimultidict_proxy_type)
  22. /* Helper macro for something like isinstance(obj, Base) */
  23. #define _MultiDict_Check(o) \
  24. ((MultiDict_CheckExact(o)) || \
  25. (CIMultiDict_CheckExact(o)) || \
  26. (MultiDictProxy_CheckExact(o)) || \
  27. (CIMultiDictProxy_CheckExact(o)))
  28. /******************** Internal Methods ********************/
  29. /* Forward declaration */
  30. static PyObject *multidict_items(MultiDictObject *self);
  31. static inline PyObject *
  32. _multidict_getone(MultiDictObject *self, PyObject *key, PyObject *_default)
  33. {
  34. PyObject *val = pair_list_get_one(&self->pairs, key);
  35. if (val == NULL &&
  36. PyErr_ExceptionMatches(PyExc_KeyError) &&
  37. _default != NULL)
  38. {
  39. PyErr_Clear();
  40. Py_INCREF(_default);
  41. return _default;
  42. }
  43. return val;
  44. }
  45. static inline int
  46. _multidict_eq(MultiDictObject *self, MultiDictObject *other)
  47. {
  48. Py_ssize_t pos1 = 0,
  49. pos2 = 0;
  50. Py_hash_t h1 = 0,
  51. h2 = 0;
  52. PyObject *identity1 = NULL,
  53. *identity2 = NULL,
  54. *value1 = NULL,
  55. *value2 = NULL;
  56. int cmp_identity = 0,
  57. cmp_value = 0;
  58. if (self == other) {
  59. return 1;
  60. }
  61. if (pair_list_len(&self->pairs) != pair_list_len(&other->pairs)) {
  62. return 0;
  63. }
  64. while (_pair_list_next(&self->pairs, &pos1, &identity1, NULL, &value1, &h1) &&
  65. _pair_list_next(&other->pairs, &pos2, &identity2, NULL, &value2, &h2))
  66. {
  67. if (h1 != h2) {
  68. return 0;
  69. }
  70. cmp_identity = PyObject_RichCompareBool(identity1, identity2, Py_NE);
  71. if (cmp_identity < 0) {
  72. return -1;
  73. }
  74. cmp_value = PyObject_RichCompareBool(value1, value2, Py_NE);
  75. if (cmp_value < 0) {
  76. return -1;
  77. }
  78. if (cmp_identity || cmp_value) {
  79. return 0;
  80. }
  81. }
  82. return 1;
  83. }
  84. static inline int
  85. _multidict_update_items(MultiDictObject *self, pair_list_t *pairs)
  86. {
  87. return pair_list_update(&self->pairs, pairs);
  88. }
  89. static inline int
  90. _multidict_append_items(MultiDictObject *self, pair_list_t *pairs)
  91. {
  92. PyObject *key = NULL,
  93. *value = NULL;
  94. Py_ssize_t pos = 0;
  95. while (_pair_list_next(pairs, &pos, NULL, &key, &value, NULL)) {
  96. if (pair_list_add(&self->pairs, key, value) < 0) {
  97. return -1;
  98. }
  99. }
  100. return 0;
  101. }
  102. static inline int
  103. _multidict_append_items_seq(MultiDictObject *self, PyObject *arg,
  104. const char *name)
  105. {
  106. PyObject *key = NULL,
  107. *value = NULL,
  108. *item = NULL,
  109. *iter = PyObject_GetIter(arg);
  110. if (iter == NULL) {
  111. return -1;
  112. }
  113. while ((item = PyIter_Next(iter)) != NULL) {
  114. if (PyTuple_CheckExact(item)) {
  115. if (PyTuple_GET_SIZE(item) != 2) {
  116. goto invalid_type;
  117. }
  118. key = PyTuple_GET_ITEM(item, 0);
  119. Py_INCREF(key);
  120. value = PyTuple_GET_ITEM(item, 1);
  121. Py_INCREF(value);
  122. }
  123. else if (PyList_CheckExact(item)) {
  124. if (PyList_GET_SIZE(item) != 2) {
  125. goto invalid_type;
  126. }
  127. key = PyList_GET_ITEM(item, 0);
  128. Py_INCREF(key);
  129. value = PyList_GET_ITEM(item, 1);
  130. Py_INCREF(value);
  131. }
  132. else if (PySequence_Check(item)) {
  133. if (PySequence_Size(item) != 2) {
  134. goto invalid_type;
  135. }
  136. key = PySequence_GetItem(item, 0);
  137. value = PySequence_GetItem(item, 1);
  138. } else {
  139. goto invalid_type;
  140. }
  141. if (pair_list_add(&self->pairs, key, value) < 0) {
  142. goto fail;
  143. }
  144. Py_CLEAR(key);
  145. Py_CLEAR(value);
  146. Py_CLEAR(item);
  147. }
  148. Py_DECREF(iter);
  149. if (PyErr_Occurred()) {
  150. return -1;
  151. }
  152. return 0;
  153. invalid_type:
  154. PyErr_Format(
  155. PyExc_TypeError,
  156. "%s takes either dict or list of (key, value) pairs",
  157. name,
  158. NULL
  159. );
  160. goto fail;
  161. fail:
  162. Py_XDECREF(key);
  163. Py_XDECREF(value);
  164. Py_XDECREF(item);
  165. Py_DECREF(iter);
  166. return -1;
  167. }
  168. static inline int
  169. _multidict_list_extend(PyObject *list, PyObject *target_list)
  170. {
  171. PyObject *item = NULL,
  172. *iter = PyObject_GetIter(target_list);
  173. if (iter == NULL) {
  174. return -1;
  175. }
  176. while ((item = PyIter_Next(iter)) != NULL) {
  177. if (PyList_Append(list, item) < 0) {
  178. Py_DECREF(item);
  179. Py_DECREF(iter);
  180. return -1;
  181. }
  182. Py_DECREF(item);
  183. }
  184. Py_DECREF(iter);
  185. if (PyErr_Occurred()) {
  186. return -1;
  187. }
  188. return 0;
  189. }
  190. static inline int
  191. _multidict_extend_with_args(MultiDictObject *self, PyObject *arg,
  192. PyObject *kwds, const char *name, int do_add)
  193. {
  194. PyObject *arg_items = NULL, /* tracked by GC */
  195. *kwds_items = NULL; /* new reference */
  196. pair_list_t *pairs = NULL;
  197. int err = 0;
  198. if (kwds && !PyArg_ValidateKeywordArguments(kwds)) {
  199. return -1;
  200. }
  201. // TODO: mb can be refactored more clear
  202. if (_MultiDict_Check(arg) && kwds == NULL) {
  203. if (MultiDict_CheckExact(arg) || CIMultiDict_CheckExact(arg)) {
  204. pairs = &((MultiDictObject*)arg)->pairs;
  205. } else if (MultiDictProxy_CheckExact(arg) || CIMultiDictProxy_CheckExact(arg)) {
  206. pairs = &((MultiDictProxyObject*)arg)->md->pairs;
  207. }
  208. if (do_add) {
  209. return _multidict_append_items(self, pairs);
  210. }
  211. return _multidict_update_items(self, pairs);
  212. }
  213. if (PyObject_HasAttrString(arg, "items")) {
  214. if (_MultiDict_Check(arg)) {
  215. arg_items = multidict_items((MultiDictObject*)arg);
  216. } else {
  217. arg_items = PyMapping_Items(arg);
  218. }
  219. if (arg_items == NULL) {
  220. return -1;
  221. }
  222. } else {
  223. arg_items = arg;
  224. Py_INCREF(arg_items);
  225. }
  226. if (kwds) {
  227. PyObject *tmp = PySequence_List(arg_items);
  228. Py_DECREF(arg_items);
  229. arg_items = tmp;
  230. if (arg_items == NULL) {
  231. return -1;
  232. }
  233. kwds_items = PyDict_Items(kwds);
  234. if (kwds_items == NULL) {
  235. Py_DECREF(arg_items);
  236. return -1;
  237. }
  238. err = _multidict_list_extend(arg_items, kwds_items);
  239. Py_DECREF(kwds_items);
  240. if (err < 0) {
  241. Py_DECREF(arg_items);
  242. return -1;
  243. }
  244. }
  245. if (do_add) {
  246. err = _multidict_append_items_seq(self, arg_items, name);
  247. } else {
  248. err = pair_list_update_from_seq(&self->pairs, arg_items);
  249. }
  250. Py_DECREF(arg_items);
  251. return err;
  252. }
  253. static inline int
  254. _multidict_extend_with_kwds(MultiDictObject *self, PyObject *kwds,
  255. const char *name, int do_add)
  256. {
  257. PyObject *arg = NULL;
  258. int err = 0;
  259. if (!PyArg_ValidateKeywordArguments(kwds)) {
  260. return -1;
  261. }
  262. arg = PyDict_Items(kwds);
  263. if (do_add) {
  264. err = _multidict_append_items_seq(self, arg, name);
  265. } else {
  266. err = pair_list_update_from_seq(&self->pairs, arg);
  267. }
  268. Py_DECREF(arg);
  269. return err;
  270. }
  271. static inline int
  272. _multidict_extend(MultiDictObject *self, PyObject *args, PyObject *kwds,
  273. const char *name, int do_add)
  274. {
  275. PyObject *arg = NULL;
  276. if (args && PyObject_Length(args) > 1) {
  277. PyErr_Format(
  278. PyExc_TypeError,
  279. "%s takes at most 1 positional argument (%zd given)",
  280. name, PyObject_Length(args), NULL
  281. );
  282. return -1;
  283. }
  284. if (args && PyObject_Length(args) > 0) {
  285. if (!PyArg_UnpackTuple(args, name, 0, 1, &arg)) {
  286. return -1;
  287. }
  288. if (_multidict_extend_with_args(self, arg, kwds, name, do_add) < 0) {
  289. return -1;
  290. }
  291. } else if (kwds && PyObject_Length(kwds) > 0) {
  292. if (_multidict_extend_with_kwds(self, kwds, name, do_add) < 0) {
  293. return -1;
  294. }
  295. }
  296. return 0;
  297. }
  298. static inline PyObject *
  299. _multidict_copy(MultiDictObject *self, PyTypeObject *multidict_tp_object)
  300. {
  301. MultiDictObject *new_multidict = NULL;
  302. PyObject *arg_items = NULL,
  303. *items = NULL;
  304. new_multidict = (MultiDictObject*)PyType_GenericNew(
  305. multidict_tp_object, NULL, NULL);
  306. if (new_multidict == NULL) {
  307. return NULL;
  308. }
  309. if (multidict_tp_object->tp_init(
  310. (PyObject*)new_multidict, NULL, NULL) < 0)
  311. {
  312. return NULL;
  313. }
  314. items = multidict_items(self);
  315. if (items == NULL) {
  316. goto fail;
  317. }
  318. // TODO: "Implementation looks as slow as possible ..."
  319. arg_items = PyTuple_New(1);
  320. if (arg_items == NULL) {
  321. goto fail;
  322. }
  323. Py_INCREF(items);
  324. PyTuple_SET_ITEM(arg_items, 0, items);
  325. if (_multidict_extend(
  326. new_multidict, arg_items, NULL, "copy", 1) < 0)
  327. {
  328. goto fail;
  329. }
  330. Py_DECREF(items);
  331. Py_DECREF(arg_items);
  332. return (PyObject*)new_multidict;
  333. fail:
  334. Py_XDECREF(items);
  335. Py_XDECREF(arg_items);
  336. Py_DECREF(new_multidict);
  337. return NULL;
  338. }
  339. static inline PyObject *
  340. _multidict_proxy_copy(MultiDictProxyObject *self, PyTypeObject *type)
  341. {
  342. PyObject *new_multidict = PyType_GenericNew(type, NULL, NULL);
  343. if (new_multidict == NULL) {
  344. goto fail;
  345. }
  346. if (type->tp_init(new_multidict, NULL, NULL) < 0) {
  347. goto fail;
  348. }
  349. if (_multidict_extend_with_args(
  350. (MultiDictObject*)new_multidict, (PyObject*)self, NULL, "copy", 1) < 0)
  351. {
  352. goto fail;
  353. }
  354. return new_multidict;
  355. fail:
  356. Py_XDECREF(new_multidict);
  357. return NULL;
  358. }
  359. /******************** Base Methods ********************/
  360. static inline PyObject *
  361. multidict_getall(MultiDictObject *self, PyObject *args, PyObject *kwds)
  362. {
  363. PyObject *list = NULL,
  364. *key = NULL,
  365. *_default = NULL;
  366. static char *getall_keywords[] = {"key", "default", NULL};
  367. if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:getall",
  368. getall_keywords, &key, &_default))
  369. {
  370. return NULL;
  371. }
  372. list = pair_list_get_all(&self->pairs, key);
  373. if (list == NULL &&
  374. PyErr_ExceptionMatches(PyExc_KeyError) &&
  375. _default != NULL)
  376. {
  377. PyErr_Clear();
  378. Py_INCREF(_default);
  379. return _default;
  380. }
  381. return list;
  382. }
  383. static inline PyObject *
  384. multidict_getone(MultiDictObject *self, PyObject *args, PyObject *kwds)
  385. {
  386. PyObject *key = NULL,
  387. *_default = NULL;
  388. static char *getone_keywords[] = {"key", "default", NULL};
  389. if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:getone",
  390. getone_keywords, &key, &_default))
  391. {
  392. return NULL;
  393. }
  394. return _multidict_getone(self, key, _default);
  395. }
  396. static inline PyObject *
  397. multidict_get(MultiDictObject *self, PyObject *args, PyObject *kwds)
  398. {
  399. PyObject *key = NULL,
  400. *_default = Py_None,
  401. *ret;
  402. static char *getone_keywords[] = {"key", "default", NULL};
  403. if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:getone",
  404. getone_keywords, &key, &_default))
  405. {
  406. return NULL;
  407. }
  408. ret = _multidict_getone(self, key, _default);
  409. return ret;
  410. }
  411. static inline PyObject *
  412. multidict_keys(MultiDictObject *self)
  413. {
  414. return multidict_keysview_new((PyObject*)self);
  415. }
  416. static inline PyObject *
  417. multidict_items(MultiDictObject *self)
  418. {
  419. return multidict_itemsview_new((PyObject*)self);
  420. }
  421. static inline PyObject *
  422. multidict_values(MultiDictObject *self)
  423. {
  424. return multidict_valuesview_new((PyObject*)self);
  425. }
  426. static inline PyObject *
  427. multidict_reduce(MultiDictObject *self)
  428. {
  429. PyObject *items = NULL,
  430. *items_list = NULL,
  431. *args = NULL,
  432. *result = NULL;
  433. items = multidict_items(self);
  434. if (items == NULL) {
  435. goto ret;
  436. }
  437. items_list = PySequence_List(items);
  438. if (items_list == NULL) {
  439. goto ret;
  440. }
  441. args = PyTuple_Pack(1, items_list);
  442. if (args == NULL) {
  443. goto ret;
  444. }
  445. result = PyTuple_Pack(2, Py_TYPE(self), args);
  446. ret:
  447. Py_XDECREF(args);
  448. Py_XDECREF(items_list);
  449. Py_XDECREF(items);
  450. return result;
  451. }
  452. static inline PyObject *
  453. multidict_repr(PyObject *self)
  454. {
  455. return PyObject_CallFunctionObjArgs(
  456. repr_func, self, NULL);
  457. }
  458. static inline Py_ssize_t
  459. multidict_mp_len(MultiDictObject *self)
  460. {
  461. return pair_list_len(&self->pairs);
  462. }
  463. static inline PyObject *
  464. multidict_mp_subscript(MultiDictObject *self, PyObject *key)
  465. {
  466. return _multidict_getone(self, key, NULL);
  467. }
  468. static inline int
  469. multidict_mp_as_subscript(MultiDictObject *self, PyObject *key, PyObject *val)
  470. {
  471. if (val == NULL) {
  472. return pair_list_del(&self->pairs, key);
  473. } else {
  474. return pair_list_replace(&self->pairs, key, val);
  475. }
  476. }
  477. static inline int
  478. multidict_sq_contains(MultiDictObject *self, PyObject *key)
  479. {
  480. return pair_list_contains(&self->pairs, key);
  481. }
  482. static inline PyObject *
  483. multidict_tp_iter(MultiDictObject *self)
  484. {
  485. return multidict_keys_iter_new(self);
  486. }
  487. static inline PyObject *
  488. multidict_tp_richcompare(PyObject *self, PyObject *other, int op)
  489. {
  490. // TODO: refactoring me with love
  491. int cmp = 0;
  492. if (op != Py_EQ && op != Py_NE) {
  493. Py_RETURN_NOTIMPLEMENTED;
  494. }
  495. if (MultiDict_CheckExact(other) || CIMultiDict_CheckExact(other)) {
  496. cmp = _multidict_eq(
  497. (MultiDictObject*)self,
  498. (MultiDictObject*)other
  499. );
  500. if (cmp < 0) {
  501. return NULL;
  502. }
  503. if (op == Py_NE) {
  504. cmp = !cmp;
  505. }
  506. return PyBool_FromLong(cmp);
  507. }
  508. if (MultiDictProxy_CheckExact(other) || CIMultiDictProxy_CheckExact(other)) {
  509. cmp = _multidict_eq(
  510. (MultiDictObject*)self,
  511. ((MultiDictProxyObject*)other)->md
  512. );
  513. if (cmp < 0) {
  514. return NULL;
  515. }
  516. if (op == Py_NE) {
  517. cmp = !cmp;
  518. }
  519. return PyBool_FromLong(cmp);
  520. }
  521. cmp = PyObject_IsInstance(other, (PyObject*)collections_abc_mapping);
  522. if (cmp < 0) {
  523. return NULL;
  524. }
  525. if (cmp) {
  526. cmp = pair_list_eq_to_mapping(&((MultiDictObject*)self)->pairs, other);
  527. if (cmp < 0) {
  528. return NULL;
  529. }
  530. if (op == Py_NE) {
  531. cmp = !cmp;
  532. }
  533. return PyBool_FromLong(cmp);
  534. }
  535. Py_RETURN_NOTIMPLEMENTED;
  536. }
  537. static inline void
  538. multidict_tp_dealloc(MultiDictObject *self)
  539. {
  540. PyObject_GC_UnTrack(self);
  541. Py_TRASHCAN_SAFE_BEGIN(self);
  542. if (self->weaklist != NULL) {
  543. PyObject_ClearWeakRefs((PyObject *)self);
  544. };
  545. pair_list_dealloc(&self->pairs);
  546. Py_TYPE(self)->tp_free((PyObject *)self);
  547. Py_TRASHCAN_SAFE_END(self);
  548. }
  549. static inline int
  550. multidict_tp_traverse(MultiDictObject *self, visitproc visit, void *arg)
  551. {
  552. return pair_list_traverse(&self->pairs, visit, arg);
  553. }
  554. static inline int
  555. multidict_tp_clear(MultiDictObject *self)
  556. {
  557. return pair_list_clear(&self->pairs);
  558. }
  559. PyDoc_STRVAR(multidict_getall_doc,
  560. "Return a list of all values matching the key.");
  561. PyDoc_STRVAR(multidict_getone_doc,
  562. "Get first value matching the key.");
  563. PyDoc_STRVAR(multidict_get_doc,
  564. "Get first value matching the key.\n\nThe method is alias for .getone().");
  565. PyDoc_STRVAR(multidict_keys_doc,
  566. "Return a new view of the dictionary's keys.");
  567. PyDoc_STRVAR(multidict_items_doc,
  568. "Return a new view of the dictionary's items *(key, value) pairs).");
  569. PyDoc_STRVAR(multidict_values_doc,
  570. "Return a new view of the dictionary's values.");
  571. /******************** MultiDict ********************/
  572. static inline int
  573. multidict_tp_init(MultiDictObject *self, PyObject *args, PyObject *kwds)
  574. {
  575. if (pair_list_init(&self->pairs) < 0) {
  576. return -1;
  577. }
  578. if (_multidict_extend(self, args, kwds, "MultiDict", 1) < 0) {
  579. return -1;
  580. }
  581. return 0;
  582. }
  583. static inline PyObject *
  584. multidict_add(MultiDictObject *self, PyObject *args, PyObject *kwds)
  585. {
  586. PyObject *key = NULL,
  587. *val = NULL;
  588. static char *kwlist[] = {"key", "value", NULL};
  589. if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO:add",
  590. kwlist, &key, &val))
  591. {
  592. return NULL;
  593. }
  594. if (pair_list_add(&self->pairs, key, val) < 0) {
  595. return NULL;
  596. }
  597. Py_RETURN_NONE;
  598. }
  599. static inline PyObject *
  600. multidict_copy(MultiDictObject *self)
  601. {
  602. return _multidict_copy(self, &multidict_type);
  603. }
  604. static inline PyObject *
  605. multidict_extend(MultiDictObject *self, PyObject *args, PyObject *kwds)
  606. {
  607. if (_multidict_extend(self, args, kwds, "extend", 1) < 0) {
  608. return NULL;
  609. }
  610. Py_RETURN_NONE;
  611. }
  612. static inline PyObject *
  613. multidict_clear(MultiDictObject *self)
  614. {
  615. if (pair_list_clear(&self->pairs) < 0) {
  616. return NULL;
  617. }
  618. Py_RETURN_NONE;
  619. }
  620. static inline PyObject *
  621. multidict_setdefault(MultiDictObject *self, PyObject *args, PyObject *kwds)
  622. {
  623. PyObject *key = NULL,
  624. *_default = NULL;
  625. static char *setdefault_keywords[] = {"key", "default", NULL};
  626. if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:setdefault",
  627. setdefault_keywords, &key, &_default))
  628. {
  629. return NULL;
  630. }
  631. return pair_list_set_default(&self->pairs, key, _default);
  632. }
  633. static inline PyObject *
  634. multidict_popone(MultiDictObject *self, PyObject *args, PyObject *kwds)
  635. {
  636. PyObject *key = NULL,
  637. *_default = NULL,
  638. *ret_val = NULL;
  639. static char *popone_keywords[] = {"key", "default", NULL};
  640. if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:popone",
  641. popone_keywords, &key, &_default))
  642. {
  643. return NULL;
  644. }
  645. ret_val = pair_list_pop_one(&self->pairs, key);
  646. if (ret_val == NULL &&
  647. PyErr_ExceptionMatches(PyExc_KeyError) &&
  648. _default != NULL)
  649. {
  650. PyErr_Clear();
  651. Py_INCREF(_default);
  652. return _default;
  653. }
  654. return ret_val;
  655. }
  656. static inline PyObject *
  657. multidict_popall(MultiDictObject *self, PyObject *args, PyObject *kwds)
  658. {
  659. PyObject *key = NULL,
  660. *_default = NULL,
  661. *ret_val = NULL;
  662. static char *popall_keywords[] = {"key", "default", NULL};
  663. if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:popall",
  664. popall_keywords, &key, &_default))
  665. {
  666. return NULL;
  667. }
  668. ret_val = pair_list_pop_all(&self->pairs, key);
  669. if (ret_val == NULL &&
  670. PyErr_ExceptionMatches(PyExc_KeyError) &&
  671. _default != NULL)
  672. {
  673. PyErr_Clear();
  674. Py_INCREF(_default);
  675. return _default;
  676. }
  677. return ret_val;
  678. }
  679. static inline PyObject *
  680. multidict_popitem(MultiDictObject *self)
  681. {
  682. return pair_list_pop_item(&self->pairs);
  683. }
  684. static inline PyObject *
  685. multidict_update(MultiDictObject *self, PyObject *args, PyObject *kwds)
  686. {
  687. if (_multidict_extend(self, args, kwds, "update", 0) < 0) {
  688. return NULL;
  689. }
  690. Py_RETURN_NONE;
  691. }
  692. PyDoc_STRVAR(multidict_add_doc,
  693. "Add the key and value, not overwriting any previous value.");
  694. PyDoc_STRVAR(multidict_copy_doc,
  695. "Return a copy of itself.");
  696. PyDoc_STRVAR(multdicit_method_extend_doc,
  697. "Extend current MultiDict with more values.\n\
  698. This method must be used instead of update.");
  699. PyDoc_STRVAR(multidict_clear_doc,
  700. "Remove all items from MultiDict");
  701. PyDoc_STRVAR(multidict_setdefault_doc,
  702. "Return value for key, set value to default if key is not present.");
  703. PyDoc_STRVAR(multidict_popone_doc,
  704. "Remove the last occurrence of key and return the corresponding value.\n\n\
  705. If key is not found, default is returned if given, otherwise KeyError is \
  706. raised.\n");
  707. PyDoc_STRVAR(multidict_popall_doc,
  708. "Remove all occurrences of key and return the list of corresponding values.\n\n\
  709. If key is not found, default is returned if given, otherwise KeyError is \
  710. raised.\n");
  711. PyDoc_STRVAR(multidict_popitem_doc,
  712. "Remove and return an arbitrary (key, value) pair.");
  713. PyDoc_STRVAR(multidict_update_doc,
  714. "Update the dictionary from *other*, overwriting existing keys.");
  715. #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 9
  716. #define multidict_class_getitem Py_GenericAlias
  717. #else
  718. static inline PyObject *
  719. multidict_class_getitem(PyObject *self, PyObject *arg)
  720. {
  721. Py_INCREF(self);
  722. return self;
  723. }
  724. #endif
  725. PyDoc_STRVAR(sizeof__doc__,
  726. "D.__sizeof__() -> size of D in memory, in bytes");
  727. static inline PyObject *
  728. _multidict_sizeof(MultiDictObject *self)
  729. {
  730. Py_ssize_t size = sizeof(MultiDictObject);
  731. if (self->pairs.pairs != self->pairs.buffer) {
  732. size += (Py_ssize_t)sizeof(pair_t) * self->pairs.capacity;
  733. }
  734. return PyLong_FromSsize_t(size);
  735. }
  736. static PySequenceMethods multidict_sequence = {
  737. .sq_contains = (objobjproc)multidict_sq_contains,
  738. };
  739. static PyMappingMethods multidict_mapping = {
  740. .mp_length = (lenfunc)multidict_mp_len,
  741. .mp_subscript = (binaryfunc)multidict_mp_subscript,
  742. .mp_ass_subscript = (objobjargproc)multidict_mp_as_subscript,
  743. };
  744. static PyMethodDef multidict_methods[] = {
  745. {
  746. "getall",
  747. (PyCFunction)multidict_getall,
  748. METH_VARARGS | METH_KEYWORDS,
  749. multidict_getall_doc
  750. },
  751. {
  752. "getone",
  753. (PyCFunction)multidict_getone,
  754. METH_VARARGS | METH_KEYWORDS,
  755. multidict_getone_doc
  756. },
  757. {
  758. "get",
  759. (PyCFunction)multidict_get,
  760. METH_VARARGS | METH_KEYWORDS,
  761. multidict_get_doc
  762. },
  763. {
  764. "keys",
  765. (PyCFunction)multidict_keys,
  766. METH_NOARGS,
  767. multidict_keys_doc
  768. },
  769. {
  770. "items",
  771. (PyCFunction)multidict_items,
  772. METH_NOARGS,
  773. multidict_items_doc
  774. },
  775. {
  776. "values",
  777. (PyCFunction)multidict_values,
  778. METH_NOARGS,
  779. multidict_values_doc
  780. },
  781. {
  782. "add",
  783. (PyCFunction)multidict_add,
  784. METH_VARARGS | METH_KEYWORDS,
  785. multidict_add_doc
  786. },
  787. {
  788. "copy",
  789. (PyCFunction)multidict_copy,
  790. METH_NOARGS,
  791. multidict_copy_doc
  792. },
  793. {
  794. "extend",
  795. (PyCFunction)multidict_extend,
  796. METH_VARARGS | METH_KEYWORDS,
  797. multdicit_method_extend_doc
  798. },
  799. {
  800. "clear",
  801. (PyCFunction)multidict_clear,
  802. METH_NOARGS,
  803. multidict_clear_doc
  804. },
  805. {
  806. "setdefault",
  807. (PyCFunction)multidict_setdefault,
  808. METH_VARARGS | METH_KEYWORDS,
  809. multidict_setdefault_doc
  810. },
  811. {
  812. "popone",
  813. (PyCFunction)multidict_popone,
  814. METH_VARARGS | METH_KEYWORDS,
  815. multidict_popone_doc
  816. },
  817. {
  818. "pop",
  819. (PyCFunction)multidict_popone,
  820. METH_VARARGS | METH_KEYWORDS,
  821. multidict_popone_doc
  822. },
  823. {
  824. "popall",
  825. (PyCFunction)multidict_popall,
  826. METH_VARARGS | METH_KEYWORDS,
  827. multidict_popall_doc
  828. },
  829. {
  830. "popitem",
  831. (PyCFunction)multidict_popitem,
  832. METH_NOARGS,
  833. multidict_popitem_doc
  834. },
  835. {
  836. "update",
  837. (PyCFunction)multidict_update,
  838. METH_VARARGS | METH_KEYWORDS,
  839. multidict_update_doc
  840. },
  841. {
  842. "__reduce__",
  843. (PyCFunction)multidict_reduce,
  844. METH_NOARGS,
  845. NULL,
  846. },
  847. {
  848. "__class_getitem__",
  849. (PyCFunction)multidict_class_getitem,
  850. METH_O | METH_CLASS,
  851. NULL
  852. },
  853. {
  854. "__sizeof__",
  855. (PyCFunction)_multidict_sizeof,
  856. METH_NOARGS,
  857. sizeof__doc__,
  858. },
  859. {
  860. NULL,
  861. NULL
  862. } /* sentinel */
  863. };
  864. PyDoc_STRVAR(MultDict_doc,
  865. "Dictionary with the support for duplicate keys.");
  866. static PyTypeObject multidict_type = {
  867. PyVarObject_HEAD_INIT(NULL, 0)
  868. "multidict._multidict.MultiDict", /* tp_name */
  869. sizeof(MultiDictObject), /* tp_basicsize */
  870. .tp_dealloc = (destructor)multidict_tp_dealloc,
  871. .tp_repr = (reprfunc)multidict_repr,
  872. .tp_as_sequence = &multidict_sequence,
  873. .tp_as_mapping = &multidict_mapping,
  874. .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
  875. .tp_doc = MultDict_doc,
  876. .tp_traverse = (traverseproc)multidict_tp_traverse,
  877. .tp_clear = (inquiry)multidict_tp_clear,
  878. .tp_richcompare = (richcmpfunc)multidict_tp_richcompare,
  879. .tp_weaklistoffset = offsetof(MultiDictObject, weaklist),
  880. .tp_iter = (getiterfunc)multidict_tp_iter,
  881. .tp_methods = multidict_methods,
  882. .tp_init = (initproc)multidict_tp_init,
  883. .tp_alloc = PyType_GenericAlloc,
  884. .tp_new = PyType_GenericNew,
  885. .tp_free = PyObject_GC_Del,
  886. };
  887. /******************** CIMultiDict ********************/
  888. static inline int
  889. cimultidict_tp_init(MultiDictObject *self, PyObject *args, PyObject *kwds)
  890. {
  891. if (ci_pair_list_init(&self->pairs) < 0) {
  892. return -1;
  893. }
  894. if (_multidict_extend(self, args, kwds, "CIMultiDict", 1) < 0) {
  895. return -1;
  896. }
  897. return 0;
  898. }
  899. static inline PyObject *
  900. cimultidict_copy(MultiDictObject *self)
  901. {
  902. return _multidict_copy(self, &cimultidict_type);
  903. }
  904. PyDoc_STRVAR(cimultidict_copy_doc,
  905. "Return a copy of itself.");
  906. static PyMethodDef cimultidict_methods[] = {
  907. {
  908. "copy",
  909. (PyCFunction)cimultidict_copy,
  910. METH_NOARGS,
  911. cimultidict_copy_doc
  912. },
  913. {
  914. NULL,
  915. NULL
  916. } /* sentinel */
  917. };
  918. PyDoc_STRVAR(CIMultDict_doc,
  919. "Dictionary with the support for duplicate case-insensitive keys.");
  920. static PyTypeObject cimultidict_type = {
  921. PyVarObject_HEAD_INIT(NULL, 0)
  922. "multidict._multidict.CIMultiDict", /* tp_name */
  923. sizeof(MultiDictObject), /* tp_basicsize */
  924. .tp_dealloc = (destructor)multidict_tp_dealloc,
  925. .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
  926. .tp_doc = CIMultDict_doc,
  927. .tp_traverse = (traverseproc)multidict_tp_traverse,
  928. .tp_clear = (inquiry)multidict_tp_clear,
  929. .tp_weaklistoffset = offsetof(MultiDictObject, weaklist),
  930. .tp_methods = cimultidict_methods,
  931. .tp_base = &multidict_type,
  932. .tp_init = (initproc)cimultidict_tp_init,
  933. .tp_alloc = PyType_GenericAlloc,
  934. .tp_new = PyType_GenericNew,
  935. .tp_free = PyObject_GC_Del,
  936. };
  937. /******************** MultiDictProxy ********************/
  938. static inline int
  939. multidict_proxy_tp_init(MultiDictProxyObject *self, PyObject *args,
  940. PyObject *kwds)
  941. {
  942. PyObject *arg = NULL;
  943. MultiDictObject *md = NULL;
  944. if (!PyArg_UnpackTuple(args, "multidict._multidict.MultiDictProxy",
  945. 0, 1, &arg))
  946. {
  947. return -1;
  948. }
  949. if (arg == NULL) {
  950. PyErr_Format(
  951. PyExc_TypeError,
  952. "__init__() missing 1 required positional argument: 'arg'"
  953. );
  954. return -1;
  955. }
  956. if (!MultiDictProxy_CheckExact(arg) &&
  957. !CIMultiDict_CheckExact(arg) &&
  958. !MultiDict_CheckExact(arg))
  959. {
  960. PyErr_Format(
  961. PyExc_TypeError,
  962. "ctor requires MultiDict or MultiDictProxy instance, "
  963. "not <classs '%s'>",
  964. Py_TYPE(arg)->tp_name
  965. );
  966. return -1;
  967. }
  968. md = (MultiDictObject*)arg;
  969. if (MultiDictProxy_CheckExact(arg)) {
  970. md = ((MultiDictProxyObject*)arg)->md;
  971. }
  972. Py_INCREF(md);
  973. self->md = md;
  974. return 0;
  975. }
  976. static inline PyObject *
  977. multidict_proxy_getall(MultiDictProxyObject *self, PyObject *args,
  978. PyObject *kwds)
  979. {
  980. return multidict_getall(self->md, args, kwds);
  981. }
  982. static inline PyObject *
  983. multidict_proxy_getone(MultiDictProxyObject *self, PyObject *args,
  984. PyObject *kwds)
  985. {
  986. return multidict_getone(self->md, args, kwds);
  987. }
  988. static inline PyObject *
  989. multidict_proxy_get(MultiDictProxyObject *self, PyObject *args,
  990. PyObject *kwds)
  991. {
  992. return multidict_get(self->md, args, kwds);
  993. }
  994. static inline PyObject *
  995. multidict_proxy_keys(MultiDictProxyObject *self)
  996. {
  997. return multidict_keys(self->md);
  998. }
  999. static inline PyObject *
  1000. multidict_proxy_items(MultiDictProxyObject *self)
  1001. {
  1002. return multidict_items(self->md);
  1003. }
  1004. static inline PyObject *
  1005. multidict_proxy_values(MultiDictProxyObject *self)
  1006. {
  1007. return multidict_values(self->md);
  1008. }
  1009. static inline PyObject *
  1010. multidict_proxy_copy(MultiDictProxyObject *self)
  1011. {
  1012. return _multidict_proxy_copy(self, &multidict_type);
  1013. }
  1014. static inline PyObject *
  1015. multidict_proxy_reduce(MultiDictProxyObject *self)
  1016. {
  1017. PyErr_Format(
  1018. PyExc_TypeError,
  1019. "can't pickle %s objects", Py_TYPE(self)->tp_name
  1020. );
  1021. return NULL;
  1022. }
  1023. static inline Py_ssize_t
  1024. multidict_proxy_mp_len(MultiDictProxyObject *self)
  1025. {
  1026. return multidict_mp_len(self->md);
  1027. }
  1028. static inline PyObject *
  1029. multidict_proxy_mp_subscript(MultiDictProxyObject *self, PyObject *key)
  1030. {
  1031. return multidict_mp_subscript(self->md, key);
  1032. }
  1033. static inline int
  1034. multidict_proxy_sq_contains(MultiDictProxyObject *self, PyObject *key)
  1035. {
  1036. return multidict_sq_contains(self->md, key);
  1037. }
  1038. static inline PyObject *
  1039. multidict_proxy_tp_iter(MultiDictProxyObject *self)
  1040. {
  1041. return multidict_tp_iter(self->md);
  1042. }
  1043. static inline PyObject *
  1044. multidict_proxy_tp_richcompare(MultiDictProxyObject *self, PyObject *other,
  1045. int op)
  1046. {
  1047. return multidict_tp_richcompare((PyObject*)self->md, other, op);
  1048. }
  1049. static inline void
  1050. multidict_proxy_tp_dealloc(MultiDictProxyObject *self)
  1051. {
  1052. PyObject_GC_UnTrack(self);
  1053. if (self->weaklist != NULL) {
  1054. PyObject_ClearWeakRefs((PyObject *)self);
  1055. };
  1056. Py_XDECREF(self->md);
  1057. Py_TYPE(self)->tp_free((PyObject *)self);
  1058. }
  1059. static inline int
  1060. multidict_proxy_tp_traverse(MultiDictProxyObject *self, visitproc visit,
  1061. void *arg)
  1062. {
  1063. Py_VISIT(self->md);
  1064. return 0;
  1065. }
  1066. static inline int
  1067. multidict_proxy_tp_clear(MultiDictProxyObject *self)
  1068. {
  1069. Py_CLEAR(self->md);
  1070. return 0;
  1071. }
  1072. static PySequenceMethods multidict_proxy_sequence = {
  1073. .sq_contains = (objobjproc)multidict_proxy_sq_contains,
  1074. };
  1075. static PyMappingMethods multidict_proxy_mapping = {
  1076. .mp_length = (lenfunc)multidict_proxy_mp_len,
  1077. .mp_subscript = (binaryfunc)multidict_proxy_mp_subscript,
  1078. };
  1079. static PyMethodDef multidict_proxy_methods[] = {
  1080. {
  1081. "getall",
  1082. (PyCFunction)multidict_proxy_getall,
  1083. METH_VARARGS | METH_KEYWORDS,
  1084. multidict_getall_doc
  1085. },
  1086. {
  1087. "getone",
  1088. (PyCFunction)multidict_proxy_getone,
  1089. METH_VARARGS | METH_KEYWORDS,
  1090. multidict_getone_doc
  1091. },
  1092. {
  1093. "get",
  1094. (PyCFunction)multidict_proxy_get,
  1095. METH_VARARGS | METH_KEYWORDS,
  1096. multidict_get_doc
  1097. },
  1098. {
  1099. "keys",
  1100. (PyCFunction)multidict_proxy_keys,
  1101. METH_NOARGS,
  1102. multidict_keys_doc
  1103. },
  1104. {
  1105. "items",
  1106. (PyCFunction)multidict_proxy_items,
  1107. METH_NOARGS,
  1108. multidict_items_doc
  1109. },
  1110. {
  1111. "values",
  1112. (PyCFunction)multidict_proxy_values,
  1113. METH_NOARGS,
  1114. multidict_values_doc
  1115. },
  1116. {
  1117. "copy",
  1118. (PyCFunction)multidict_proxy_copy,
  1119. METH_NOARGS,
  1120. multidict_copy_doc
  1121. },
  1122. {
  1123. "__reduce__",
  1124. (PyCFunction)multidict_proxy_reduce,
  1125. METH_NOARGS,
  1126. NULL
  1127. },
  1128. {
  1129. "__class_getitem__",
  1130. (PyCFunction)multidict_class_getitem,
  1131. METH_O | METH_CLASS,
  1132. NULL
  1133. },
  1134. {
  1135. NULL,
  1136. NULL
  1137. } /* sentinel */
  1138. };
  1139. PyDoc_STRVAR(MultDictProxy_doc,
  1140. "Read-only proxy for MultiDict instance.");
  1141. static PyTypeObject multidict_proxy_type = {
  1142. PyVarObject_HEAD_INIT(NULL, 0)
  1143. "multidict._multidict.MultiDictProxy", /* tp_name */
  1144. sizeof(MultiDictProxyObject), /* tp_basicsize */
  1145. .tp_dealloc = (destructor)multidict_proxy_tp_dealloc,
  1146. .tp_repr = (reprfunc)multidict_repr,
  1147. .tp_as_sequence = &multidict_proxy_sequence,
  1148. .tp_as_mapping = &multidict_proxy_mapping,
  1149. .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
  1150. .tp_doc = MultDictProxy_doc,
  1151. .tp_traverse = (traverseproc)multidict_proxy_tp_traverse,
  1152. .tp_clear = (inquiry)multidict_proxy_tp_clear,
  1153. .tp_richcompare = (richcmpfunc)multidict_proxy_tp_richcompare,
  1154. .tp_weaklistoffset = offsetof(MultiDictProxyObject, weaklist),
  1155. .tp_iter = (getiterfunc)multidict_proxy_tp_iter,
  1156. .tp_methods = multidict_proxy_methods,
  1157. .tp_init = (initproc)multidict_proxy_tp_init,
  1158. .tp_alloc = PyType_GenericAlloc,
  1159. .tp_new = PyType_GenericNew,
  1160. .tp_free = PyObject_GC_Del,
  1161. };
  1162. /******************** CIMultiDictProxy ********************/
  1163. static inline int
  1164. cimultidict_proxy_tp_init(MultiDictProxyObject *self, PyObject *args,
  1165. PyObject *kwds)
  1166. {
  1167. PyObject *arg = NULL;
  1168. MultiDictObject *md = NULL;
  1169. if (!PyArg_UnpackTuple(args, "multidict._multidict.CIMultiDictProxy",
  1170. 1, 1, &arg))
  1171. {
  1172. return -1;
  1173. }
  1174. if (arg == NULL) {
  1175. PyErr_Format(
  1176. PyExc_TypeError,
  1177. "__init__() missing 1 required positional argument: 'arg'"
  1178. );
  1179. return -1;
  1180. }
  1181. if (!CIMultiDictProxy_CheckExact(arg) && !CIMultiDict_CheckExact(arg)) {
  1182. PyErr_Format(
  1183. PyExc_TypeError,
  1184. "ctor requires CIMultiDict or CIMultiDictProxy instance, "
  1185. "not <class '%s'>",
  1186. Py_TYPE(arg)->tp_name
  1187. );
  1188. return -1;
  1189. }
  1190. md = (MultiDictObject*)arg;
  1191. if (CIMultiDictProxy_CheckExact(arg)) {
  1192. md = ((MultiDictProxyObject*)arg)->md;
  1193. }
  1194. Py_INCREF(md);
  1195. self->md = md;
  1196. return 0;
  1197. }
  1198. static inline PyObject *
  1199. cimultidict_proxy_copy(MultiDictProxyObject *self)
  1200. {
  1201. return _multidict_proxy_copy(self, &cimultidict_type);
  1202. }
  1203. PyDoc_STRVAR(CIMultDictProxy_doc,
  1204. "Read-only proxy for CIMultiDict instance.");
  1205. PyDoc_STRVAR(cimultidict_proxy_copy_doc,
  1206. "Return copy of itself");
  1207. static PyMethodDef cimultidict_proxy_methods[] = {
  1208. {
  1209. "copy",
  1210. (PyCFunction)cimultidict_proxy_copy,
  1211. METH_NOARGS,
  1212. cimultidict_proxy_copy_doc
  1213. },
  1214. {
  1215. NULL,
  1216. NULL
  1217. } /* sentinel */
  1218. };
  1219. static PyTypeObject cimultidict_proxy_type = {
  1220. PyVarObject_HEAD_INIT(NULL, 0)
  1221. "multidict._multidict.CIMultiDictProxy", /* tp_name */
  1222. sizeof(MultiDictProxyObject), /* tp_basicsize */
  1223. .tp_dealloc = (destructor)multidict_proxy_tp_dealloc,
  1224. .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
  1225. .tp_doc = CIMultDictProxy_doc,
  1226. .tp_traverse = (traverseproc)multidict_proxy_tp_traverse,
  1227. .tp_clear = (inquiry)multidict_proxy_tp_clear,
  1228. .tp_richcompare = (richcmpfunc)multidict_proxy_tp_richcompare,
  1229. .tp_weaklistoffset = offsetof(MultiDictProxyObject, weaklist),
  1230. .tp_methods = cimultidict_proxy_methods,
  1231. .tp_base = &multidict_proxy_type,
  1232. .tp_init = (initproc)cimultidict_proxy_tp_init,
  1233. .tp_alloc = PyType_GenericAlloc,
  1234. .tp_new = PyType_GenericNew,
  1235. .tp_free = PyObject_GC_Del,
  1236. };
  1237. /******************** Other functions ********************/
  1238. static inline PyObject *
  1239. getversion(PyObject *self, PyObject *md)
  1240. {
  1241. pair_list_t *pairs = NULL;
  1242. if (MultiDict_CheckExact(md) || CIMultiDict_CheckExact(md)) {
  1243. pairs = &((MultiDictObject*)md)->pairs;
  1244. } else if (MultiDictProxy_CheckExact(md) || CIMultiDictProxy_CheckExact(md)) {
  1245. pairs = &((MultiDictProxyObject*)md)->md->pairs;
  1246. } else {
  1247. PyErr_Format(PyExc_TypeError, "unexpected type");
  1248. return NULL;
  1249. }
  1250. return PyLong_FromUnsignedLong(pair_list_version(pairs));
  1251. }
  1252. /******************** Module ********************/
  1253. static inline void
  1254. module_free(void *m)
  1255. {
  1256. Py_CLEAR(collections_abc_mapping);
  1257. Py_CLEAR(collections_abc_mut_mapping);
  1258. Py_CLEAR(collections_abc_mut_multi_mapping);
  1259. }
  1260. static PyMethodDef multidict_module_methods[] = {
  1261. {
  1262. "getversion",
  1263. (PyCFunction)getversion,
  1264. METH_O
  1265. },
  1266. {
  1267. NULL,
  1268. NULL
  1269. } /* sentinel */
  1270. };
  1271. static PyModuleDef multidict_module = {
  1272. PyModuleDef_HEAD_INIT, /* m_base */
  1273. "_multidict", /* m_name */
  1274. .m_size = -1,
  1275. .m_methods = multidict_module_methods,
  1276. .m_free = (freefunc)module_free,
  1277. };
  1278. PyMODINIT_FUNC
  1279. PyInit__multidict()
  1280. {
  1281. PyObject *module = NULL,
  1282. *reg_func_call_result = NULL;
  1283. #define WITH_MOD(NAME) \
  1284. Py_CLEAR(module); \
  1285. module = PyImport_ImportModule(NAME); \
  1286. if (module == NULL) { \
  1287. goto fail; \
  1288. }
  1289. #define GET_MOD_ATTR(VAR, NAME) \
  1290. VAR = PyObject_GetAttrString(module, NAME); \
  1291. if (VAR == NULL) { \
  1292. goto fail; \
  1293. }
  1294. if (multidict_views_init() < 0) {
  1295. goto fail;
  1296. }
  1297. if (multidict_iter_init() < 0) {
  1298. goto fail;
  1299. }
  1300. if (istr_init() < 0) {
  1301. goto fail;
  1302. }
  1303. if (PyType_Ready(&multidict_type) < 0 ||
  1304. PyType_Ready(&cimultidict_type) < 0 ||
  1305. PyType_Ready(&multidict_proxy_type) < 0 ||
  1306. PyType_Ready(&cimultidict_proxy_type) < 0)
  1307. {
  1308. goto fail;
  1309. }
  1310. WITH_MOD("collections.abc");
  1311. GET_MOD_ATTR(collections_abc_mapping, "Mapping");
  1312. WITH_MOD("multidict._abc");
  1313. GET_MOD_ATTR(collections_abc_mut_mapping, "MultiMapping");
  1314. WITH_MOD("multidict._abc");
  1315. GET_MOD_ATTR(collections_abc_mut_multi_mapping, "MutableMultiMapping");
  1316. WITH_MOD("multidict._multidict_base");
  1317. GET_MOD_ATTR(repr_func, "_mdrepr");
  1318. /* Register in _abc mappings (CI)MultiDict and (CI)MultiDictProxy */
  1319. reg_func_call_result = PyObject_CallMethod(
  1320. collections_abc_mut_mapping,
  1321. "register", "O",
  1322. (PyObject*)&multidict_proxy_type
  1323. );
  1324. if (reg_func_call_result == NULL) {
  1325. goto fail;
  1326. }
  1327. Py_DECREF(reg_func_call_result);
  1328. reg_func_call_result = PyObject_CallMethod(
  1329. collections_abc_mut_mapping,
  1330. "register", "O",
  1331. (PyObject*)&cimultidict_proxy_type
  1332. );
  1333. if (reg_func_call_result == NULL) {
  1334. goto fail;
  1335. }
  1336. Py_DECREF(reg_func_call_result);
  1337. reg_func_call_result = PyObject_CallMethod(
  1338. collections_abc_mut_multi_mapping,
  1339. "register", "O",
  1340. (PyObject*)&multidict_type
  1341. );
  1342. if (reg_func_call_result == NULL) {
  1343. goto fail;
  1344. }
  1345. Py_DECREF(reg_func_call_result);
  1346. reg_func_call_result = PyObject_CallMethod(
  1347. collections_abc_mut_multi_mapping,
  1348. "register", "O",
  1349. (PyObject*)&cimultidict_type
  1350. );
  1351. if (reg_func_call_result == NULL) {
  1352. goto fail;
  1353. }
  1354. Py_DECREF(reg_func_call_result);
  1355. /* Instantiate this module */
  1356. module = PyModule_Create(&multidict_module);
  1357. Py_INCREF(&istr_type);
  1358. if (PyModule_AddObject(
  1359. module, "istr", (PyObject*)&istr_type) < 0)
  1360. {
  1361. goto fail;
  1362. }
  1363. Py_INCREF(&multidict_type);
  1364. if (PyModule_AddObject(
  1365. module, "MultiDict", (PyObject*)&multidict_type) < 0)
  1366. {
  1367. goto fail;
  1368. }
  1369. Py_INCREF(&cimultidict_type);
  1370. if (PyModule_AddObject(
  1371. module, "CIMultiDict", (PyObject*)&cimultidict_type) < 0)
  1372. {
  1373. goto fail;
  1374. }
  1375. Py_INCREF(&multidict_proxy_type);
  1376. if (PyModule_AddObject(
  1377. module, "MultiDictProxy", (PyObject*)&multidict_proxy_type) < 0)
  1378. {
  1379. goto fail;
  1380. }
  1381. Py_INCREF(&cimultidict_proxy_type);
  1382. if (PyModule_AddObject(
  1383. module, "CIMultiDictProxy", (PyObject*)&cimultidict_proxy_type) < 0)
  1384. {
  1385. goto fail;
  1386. }
  1387. return module;
  1388. fail:
  1389. Py_XDECREF(collections_abc_mapping);
  1390. Py_XDECREF(collections_abc_mut_mapping);
  1391. Py_XDECREF(collections_abc_mut_multi_mapping);
  1392. return NULL;
  1393. #undef WITH_MOD
  1394. #undef GET_MOD_ATTR
  1395. }