店播爬取Python脚本

repeated_scalar_container.cc 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // https://developers.google.com/protocol-buffers/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. // Author: anuraag@google.com (Anuraag Agrawal)
  31. // Author: tibell@google.com (Johan Tibell)
  32. #include <google/protobuf/pyext/repeated_scalar_container.h>
  33. #include <cstdint>
  34. #include <memory>
  35. #include <google/protobuf/stubs/common.h>
  36. #include <google/protobuf/stubs/logging.h>
  37. #include <google/protobuf/descriptor.h>
  38. #include <google/protobuf/dynamic_message.h>
  39. #include <google/protobuf/message.h>
  40. #include <google/protobuf/pyext/descriptor.h>
  41. #include <google/protobuf/pyext/descriptor_pool.h>
  42. #include <google/protobuf/pyext/message.h>
  43. #include <google/protobuf/pyext/scoped_pyobject_ptr.h>
  44. #if PY_MAJOR_VERSION >= 3
  45. #define PyInt_FromLong PyLong_FromLong
  46. #if PY_VERSION_HEX < 0x03030000
  47. #error "Python 3.0 - 3.2 are not supported."
  48. #else
  49. #define PyString_AsString(ob) \
  50. (PyUnicode_Check(ob) ? PyUnicode_AsUTF8(ob) : PyBytes_AsString(ob))
  51. #endif
  52. #endif
  53. namespace google {
  54. namespace protobuf {
  55. namespace python {
  56. namespace repeated_scalar_container {
  57. static int InternalAssignRepeatedField(RepeatedScalarContainer* self,
  58. PyObject* list) {
  59. Message* message = self->parent->message;
  60. message->GetReflection()->ClearField(message, self->parent_field_descriptor);
  61. for (Py_ssize_t i = 0; i < PyList_GET_SIZE(list); ++i) {
  62. PyObject* value = PyList_GET_ITEM(list, i);
  63. if (ScopedPyObjectPtr(Append(self, value)) == nullptr) {
  64. return -1;
  65. }
  66. }
  67. return 0;
  68. }
  69. static Py_ssize_t Len(PyObject* pself) {
  70. RepeatedScalarContainer* self =
  71. reinterpret_cast<RepeatedScalarContainer*>(pself);
  72. Message* message = self->parent->message;
  73. return message->GetReflection()->FieldSize(*message,
  74. self->parent_field_descriptor);
  75. }
  76. static int AssignItem(PyObject* pself, Py_ssize_t index, PyObject* arg) {
  77. RepeatedScalarContainer* self =
  78. reinterpret_cast<RepeatedScalarContainer*>(pself);
  79. cmessage::AssureWritable(self->parent);
  80. Message* message = self->parent->message;
  81. const FieldDescriptor* field_descriptor = self->parent_field_descriptor;
  82. const Reflection* reflection = message->GetReflection();
  83. int field_size = reflection->FieldSize(*message, field_descriptor);
  84. if (index < 0) {
  85. index = field_size + index;
  86. }
  87. if (index < 0 || index >= field_size) {
  88. PyErr_Format(PyExc_IndexError, "list assignment index (%d) out of range",
  89. static_cast<int>(index));
  90. return -1;
  91. }
  92. if (arg == nullptr) {
  93. ScopedPyObjectPtr py_index(PyLong_FromLong(index));
  94. return cmessage::DeleteRepeatedField(self->parent, field_descriptor,
  95. py_index.get());
  96. }
  97. if (PySequence_Check(arg) && !(PyBytes_Check(arg) || PyUnicode_Check(arg))) {
  98. PyErr_SetString(PyExc_TypeError, "Value must be scalar");
  99. return -1;
  100. }
  101. switch (field_descriptor->cpp_type()) {
  102. case FieldDescriptor::CPPTYPE_INT32: {
  103. GOOGLE_CHECK_GET_INT32(arg, value, -1);
  104. reflection->SetRepeatedInt32(message, field_descriptor, index, value);
  105. break;
  106. }
  107. case FieldDescriptor::CPPTYPE_INT64: {
  108. GOOGLE_CHECK_GET_INT64(arg, value, -1);
  109. reflection->SetRepeatedInt64(message, field_descriptor, index, value);
  110. break;
  111. }
  112. case FieldDescriptor::CPPTYPE_UINT32: {
  113. GOOGLE_CHECK_GET_UINT32(arg, value, -1);
  114. reflection->SetRepeatedUInt32(message, field_descriptor, index, value);
  115. break;
  116. }
  117. case FieldDescriptor::CPPTYPE_UINT64: {
  118. GOOGLE_CHECK_GET_UINT64(arg, value, -1);
  119. reflection->SetRepeatedUInt64(message, field_descriptor, index, value);
  120. break;
  121. }
  122. case FieldDescriptor::CPPTYPE_FLOAT: {
  123. GOOGLE_CHECK_GET_FLOAT(arg, value, -1);
  124. reflection->SetRepeatedFloat(message, field_descriptor, index, value);
  125. break;
  126. }
  127. case FieldDescriptor::CPPTYPE_DOUBLE: {
  128. GOOGLE_CHECK_GET_DOUBLE(arg, value, -1);
  129. reflection->SetRepeatedDouble(message, field_descriptor, index, value);
  130. break;
  131. }
  132. case FieldDescriptor::CPPTYPE_BOOL: {
  133. GOOGLE_CHECK_GET_BOOL(arg, value, -1);
  134. reflection->SetRepeatedBool(message, field_descriptor, index, value);
  135. break;
  136. }
  137. case FieldDescriptor::CPPTYPE_STRING: {
  138. if (!CheckAndSetString(arg, message, field_descriptor, reflection, false,
  139. index)) {
  140. return -1;
  141. }
  142. break;
  143. }
  144. case FieldDescriptor::CPPTYPE_ENUM: {
  145. GOOGLE_CHECK_GET_INT32(arg, value, -1);
  146. if (reflection->SupportsUnknownEnumValues()) {
  147. reflection->SetRepeatedEnumValue(message, field_descriptor, index,
  148. value);
  149. } else {
  150. const EnumDescriptor* enum_descriptor = field_descriptor->enum_type();
  151. const EnumValueDescriptor* enum_value =
  152. enum_descriptor->FindValueByNumber(value);
  153. if (enum_value != nullptr) {
  154. reflection->SetRepeatedEnum(message, field_descriptor, index,
  155. enum_value);
  156. } else {
  157. ScopedPyObjectPtr s(PyObject_Str(arg));
  158. if (s != nullptr) {
  159. PyErr_Format(PyExc_ValueError, "Unknown enum value: %s",
  160. PyString_AsString(s.get()));
  161. }
  162. return -1;
  163. }
  164. }
  165. break;
  166. }
  167. default:
  168. PyErr_Format(PyExc_SystemError,
  169. "Adding value to a field of unknown type %d",
  170. field_descriptor->cpp_type());
  171. return -1;
  172. }
  173. return 0;
  174. }
  175. static PyObject* Item(PyObject* pself, Py_ssize_t index) {
  176. RepeatedScalarContainer* self =
  177. reinterpret_cast<RepeatedScalarContainer*>(pself);
  178. Message* message = self->parent->message;
  179. const FieldDescriptor* field_descriptor = self->parent_field_descriptor;
  180. const Reflection* reflection = message->GetReflection();
  181. int field_size = reflection->FieldSize(*message, field_descriptor);
  182. if (index < 0) {
  183. index = field_size + index;
  184. }
  185. if (index < 0 || index >= field_size) {
  186. PyErr_Format(PyExc_IndexError, "list index (%zd) out of range", index);
  187. return nullptr;
  188. }
  189. PyObject* result = nullptr;
  190. switch (field_descriptor->cpp_type()) {
  191. case FieldDescriptor::CPPTYPE_INT32: {
  192. int32_t value =
  193. reflection->GetRepeatedInt32(*message, field_descriptor, index);
  194. result = PyInt_FromLong(value);
  195. break;
  196. }
  197. case FieldDescriptor::CPPTYPE_INT64: {
  198. int64_t value =
  199. reflection->GetRepeatedInt64(*message, field_descriptor, index);
  200. result = PyLong_FromLongLong(value);
  201. break;
  202. }
  203. case FieldDescriptor::CPPTYPE_UINT32: {
  204. uint32_t value =
  205. reflection->GetRepeatedUInt32(*message, field_descriptor, index);
  206. result = PyLong_FromLongLong(value);
  207. break;
  208. }
  209. case FieldDescriptor::CPPTYPE_UINT64: {
  210. uint64_t value =
  211. reflection->GetRepeatedUInt64(*message, field_descriptor, index);
  212. result = PyLong_FromUnsignedLongLong(value);
  213. break;
  214. }
  215. case FieldDescriptor::CPPTYPE_FLOAT: {
  216. float value =
  217. reflection->GetRepeatedFloat(*message, field_descriptor, index);
  218. result = PyFloat_FromDouble(value);
  219. break;
  220. }
  221. case FieldDescriptor::CPPTYPE_DOUBLE: {
  222. double value =
  223. reflection->GetRepeatedDouble(*message, field_descriptor, index);
  224. result = PyFloat_FromDouble(value);
  225. break;
  226. }
  227. case FieldDescriptor::CPPTYPE_BOOL: {
  228. bool value =
  229. reflection->GetRepeatedBool(*message, field_descriptor, index);
  230. result = PyBool_FromLong(value ? 1 : 0);
  231. break;
  232. }
  233. case FieldDescriptor::CPPTYPE_ENUM: {
  234. const EnumValueDescriptor* enum_value =
  235. message->GetReflection()->GetRepeatedEnum(*message, field_descriptor,
  236. index);
  237. result = PyInt_FromLong(enum_value->number());
  238. break;
  239. }
  240. case FieldDescriptor::CPPTYPE_STRING: {
  241. std::string scratch;
  242. const std::string& value = reflection->GetRepeatedStringReference(
  243. *message, field_descriptor, index, &scratch);
  244. result = ToStringObject(field_descriptor, value);
  245. break;
  246. }
  247. default:
  248. PyErr_Format(PyExc_SystemError,
  249. "Getting value from a repeated field of unknown type %d",
  250. field_descriptor->cpp_type());
  251. }
  252. return result;
  253. }
  254. static PyObject* Subscript(PyObject* pself, PyObject* slice) {
  255. Py_ssize_t from;
  256. Py_ssize_t to;
  257. Py_ssize_t step;
  258. Py_ssize_t length;
  259. Py_ssize_t slicelength;
  260. bool return_list = false;
  261. #if PY_MAJOR_VERSION < 3
  262. if (PyInt_Check(slice)) {
  263. from = to = PyInt_AsLong(slice);
  264. } else // NOLINT
  265. #endif
  266. if (PyLong_Check(slice)) {
  267. from = to = PyLong_AsLong(slice);
  268. } else if (PySlice_Check(slice)) {
  269. length = Len(pself);
  270. #if PY_MAJOR_VERSION >= 3
  271. if (PySlice_GetIndicesEx(slice, length, &from, &to, &step, &slicelength) ==
  272. -1) {
  273. #else
  274. if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice), length,
  275. &from, &to, &step, &slicelength) == -1) {
  276. #endif
  277. return nullptr;
  278. }
  279. return_list = true;
  280. } else {
  281. PyErr_SetString(PyExc_TypeError, "list indices must be integers");
  282. return nullptr;
  283. }
  284. if (!return_list) {
  285. return Item(pself, from);
  286. }
  287. PyObject* list = PyList_New(0);
  288. if (list == nullptr) {
  289. return nullptr;
  290. }
  291. if (from <= to) {
  292. if (step < 0) {
  293. return list;
  294. }
  295. for (Py_ssize_t index = from; index < to; index += step) {
  296. if (index < 0 || index >= length) {
  297. break;
  298. }
  299. ScopedPyObjectPtr s(Item(pself, index));
  300. PyList_Append(list, s.get());
  301. }
  302. } else {
  303. if (step > 0) {
  304. return list;
  305. }
  306. for (Py_ssize_t index = from; index > to; index += step) {
  307. if (index < 0 || index >= length) {
  308. break;
  309. }
  310. ScopedPyObjectPtr s(Item(pself, index));
  311. PyList_Append(list, s.get());
  312. }
  313. }
  314. return list;
  315. }
  316. PyObject* Append(RepeatedScalarContainer* self, PyObject* item) {
  317. cmessage::AssureWritable(self->parent);
  318. Message* message = self->parent->message;
  319. const FieldDescriptor* field_descriptor = self->parent_field_descriptor;
  320. const Reflection* reflection = message->GetReflection();
  321. switch (field_descriptor->cpp_type()) {
  322. case FieldDescriptor::CPPTYPE_INT32: {
  323. GOOGLE_CHECK_GET_INT32(item, value, nullptr);
  324. reflection->AddInt32(message, field_descriptor, value);
  325. break;
  326. }
  327. case FieldDescriptor::CPPTYPE_INT64: {
  328. GOOGLE_CHECK_GET_INT64(item, value, nullptr);
  329. reflection->AddInt64(message, field_descriptor, value);
  330. break;
  331. }
  332. case FieldDescriptor::CPPTYPE_UINT32: {
  333. GOOGLE_CHECK_GET_UINT32(item, value, nullptr);
  334. reflection->AddUInt32(message, field_descriptor, value);
  335. break;
  336. }
  337. case FieldDescriptor::CPPTYPE_UINT64: {
  338. GOOGLE_CHECK_GET_UINT64(item, value, nullptr);
  339. reflection->AddUInt64(message, field_descriptor, value);
  340. break;
  341. }
  342. case FieldDescriptor::CPPTYPE_FLOAT: {
  343. GOOGLE_CHECK_GET_FLOAT(item, value, nullptr);
  344. reflection->AddFloat(message, field_descriptor, value);
  345. break;
  346. }
  347. case FieldDescriptor::CPPTYPE_DOUBLE: {
  348. GOOGLE_CHECK_GET_DOUBLE(item, value, nullptr);
  349. reflection->AddDouble(message, field_descriptor, value);
  350. break;
  351. }
  352. case FieldDescriptor::CPPTYPE_BOOL: {
  353. GOOGLE_CHECK_GET_BOOL(item, value, nullptr);
  354. reflection->AddBool(message, field_descriptor, value);
  355. break;
  356. }
  357. case FieldDescriptor::CPPTYPE_STRING: {
  358. if (!CheckAndSetString(item, message, field_descriptor, reflection, true,
  359. -1)) {
  360. return nullptr;
  361. }
  362. break;
  363. }
  364. case FieldDescriptor::CPPTYPE_ENUM: {
  365. GOOGLE_CHECK_GET_INT32(item, value, nullptr);
  366. if (reflection->SupportsUnknownEnumValues()) {
  367. reflection->AddEnumValue(message, field_descriptor, value);
  368. } else {
  369. const EnumDescriptor* enum_descriptor = field_descriptor->enum_type();
  370. const EnumValueDescriptor* enum_value =
  371. enum_descriptor->FindValueByNumber(value);
  372. if (enum_value != nullptr) {
  373. reflection->AddEnum(message, field_descriptor, enum_value);
  374. } else {
  375. ScopedPyObjectPtr s(PyObject_Str(item));
  376. if (s != nullptr) {
  377. PyErr_Format(PyExc_ValueError, "Unknown enum value: %s",
  378. PyString_AsString(s.get()));
  379. }
  380. return nullptr;
  381. }
  382. }
  383. break;
  384. }
  385. default:
  386. PyErr_Format(PyExc_SystemError,
  387. "Adding value to a field of unknown type %d",
  388. field_descriptor->cpp_type());
  389. return nullptr;
  390. }
  391. Py_RETURN_NONE;
  392. }
  393. static PyObject* AppendMethod(PyObject* self, PyObject* item) {
  394. return Append(reinterpret_cast<RepeatedScalarContainer*>(self), item);
  395. }
  396. static int AssSubscript(PyObject* pself, PyObject* slice, PyObject* value) {
  397. RepeatedScalarContainer* self =
  398. reinterpret_cast<RepeatedScalarContainer*>(pself);
  399. Py_ssize_t from;
  400. Py_ssize_t to;
  401. Py_ssize_t step;
  402. Py_ssize_t length;
  403. Py_ssize_t slicelength;
  404. bool create_list = false;
  405. cmessage::AssureWritable(self->parent);
  406. Message* message = self->parent->message;
  407. const FieldDescriptor* field_descriptor = self->parent_field_descriptor;
  408. #if PY_MAJOR_VERSION < 3
  409. if (PyInt_Check(slice)) {
  410. from = to = PyInt_AsLong(slice);
  411. } else // NOLINT
  412. #endif
  413. if (PyLong_Check(slice)) {
  414. from = to = PyLong_AsLong(slice);
  415. } else if (PySlice_Check(slice)) {
  416. const Reflection* reflection = message->GetReflection();
  417. length = reflection->FieldSize(*message, field_descriptor);
  418. #if PY_MAJOR_VERSION >= 3
  419. if (PySlice_GetIndicesEx(slice, length, &from, &to, &step, &slicelength) ==
  420. -1) {
  421. #else
  422. if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice), length,
  423. &from, &to, &step, &slicelength) == -1) {
  424. #endif
  425. return -1;
  426. }
  427. create_list = true;
  428. } else {
  429. PyErr_SetString(PyExc_TypeError, "list indices must be integers");
  430. return -1;
  431. }
  432. if (value == nullptr) {
  433. return cmessage::DeleteRepeatedField(self->parent, field_descriptor, slice);
  434. }
  435. if (!create_list) {
  436. return AssignItem(pself, from, value);
  437. }
  438. ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr));
  439. if (full_slice == nullptr) {
  440. return -1;
  441. }
  442. ScopedPyObjectPtr new_list(Subscript(pself, full_slice.get()));
  443. if (new_list == nullptr) {
  444. return -1;
  445. }
  446. if (PySequence_SetSlice(new_list.get(), from, to, value) < 0) {
  447. return -1;
  448. }
  449. return InternalAssignRepeatedField(self, new_list.get());
  450. }
  451. PyObject* Extend(RepeatedScalarContainer* self, PyObject* value) {
  452. cmessage::AssureWritable(self->parent);
  453. // TODO(ptucker): Deprecate this behavior. b/18413862
  454. if (value == Py_None) {
  455. Py_RETURN_NONE;
  456. }
  457. if ((Py_TYPE(value)->tp_as_sequence == nullptr) && PyObject_Not(value)) {
  458. Py_RETURN_NONE;
  459. }
  460. ScopedPyObjectPtr iter(PyObject_GetIter(value));
  461. if (iter == nullptr) {
  462. PyErr_SetString(PyExc_TypeError, "Value must be iterable");
  463. return nullptr;
  464. }
  465. ScopedPyObjectPtr next;
  466. while ((next.reset(PyIter_Next(iter.get()))) != nullptr) {
  467. if (ScopedPyObjectPtr(Append(self, next.get())) == nullptr) {
  468. return nullptr;
  469. }
  470. }
  471. if (PyErr_Occurred()) {
  472. return nullptr;
  473. }
  474. Py_RETURN_NONE;
  475. }
  476. static PyObject* Insert(PyObject* pself, PyObject* args) {
  477. RepeatedScalarContainer* self =
  478. reinterpret_cast<RepeatedScalarContainer*>(pself);
  479. Py_ssize_t index;
  480. PyObject* value;
  481. if (!PyArg_ParseTuple(args, "lO", &index, &value)) {
  482. return nullptr;
  483. }
  484. ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr));
  485. ScopedPyObjectPtr new_list(Subscript(pself, full_slice.get()));
  486. if (PyList_Insert(new_list.get(), index, value) < 0) {
  487. return nullptr;
  488. }
  489. int ret = InternalAssignRepeatedField(self, new_list.get());
  490. if (ret < 0) {
  491. return nullptr;
  492. }
  493. Py_RETURN_NONE;
  494. }
  495. static PyObject* Remove(PyObject* pself, PyObject* value) {
  496. Py_ssize_t match_index = -1;
  497. for (Py_ssize_t i = 0; i < Len(pself); ++i) {
  498. ScopedPyObjectPtr elem(Item(pself, i));
  499. if (PyObject_RichCompareBool(elem.get(), value, Py_EQ)) {
  500. match_index = i;
  501. break;
  502. }
  503. }
  504. if (match_index == -1) {
  505. PyErr_SetString(PyExc_ValueError, "remove(x): x not in container");
  506. return nullptr;
  507. }
  508. if (AssignItem(pself, match_index, nullptr) < 0) {
  509. return nullptr;
  510. }
  511. Py_RETURN_NONE;
  512. }
  513. static PyObject* ExtendMethod(PyObject* self, PyObject* value) {
  514. return Extend(reinterpret_cast<RepeatedScalarContainer*>(self), value);
  515. }
  516. static PyObject* RichCompare(PyObject* pself, PyObject* other, int opid) {
  517. if (opid != Py_EQ && opid != Py_NE) {
  518. Py_INCREF(Py_NotImplemented);
  519. return Py_NotImplemented;
  520. }
  521. // Copy the contents of this repeated scalar container, and other if it is
  522. // also a repeated scalar container, into Python lists so we can delegate
  523. // to the list's compare method.
  524. ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr));
  525. if (full_slice == nullptr) {
  526. return nullptr;
  527. }
  528. ScopedPyObjectPtr other_list_deleter;
  529. if (PyObject_TypeCheck(other, &RepeatedScalarContainer_Type)) {
  530. other_list_deleter.reset(Subscript(other, full_slice.get()));
  531. other = other_list_deleter.get();
  532. }
  533. ScopedPyObjectPtr list(Subscript(pself, full_slice.get()));
  534. if (list == nullptr) {
  535. return nullptr;
  536. }
  537. return PyObject_RichCompare(list.get(), other, opid);
  538. }
  539. PyObject* Reduce(PyObject* unused_self, PyObject* unused_other) {
  540. PyErr_Format(PickleError_class,
  541. "can't pickle repeated message fields, convert to list first");
  542. return nullptr;
  543. }
  544. static PyObject* Sort(PyObject* pself, PyObject* args, PyObject* kwds) {
  545. // Support the old sort_function argument for backwards
  546. // compatibility.
  547. if (kwds != nullptr) {
  548. PyObject* sort_func = PyDict_GetItemString(kwds, "sort_function");
  549. if (sort_func != nullptr) {
  550. // Must set before deleting as sort_func is a borrowed reference
  551. // and kwds might be the only thing keeping it alive.
  552. if (PyDict_SetItemString(kwds, "cmp", sort_func) == -1) return nullptr;
  553. if (PyDict_DelItemString(kwds, "sort_function") == -1) return nullptr;
  554. }
  555. }
  556. ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr));
  557. if (full_slice == nullptr) {
  558. return nullptr;
  559. }
  560. ScopedPyObjectPtr list(Subscript(pself, full_slice.get()));
  561. if (list == nullptr) {
  562. return nullptr;
  563. }
  564. ScopedPyObjectPtr m(PyObject_GetAttrString(list.get(), "sort"));
  565. if (m == nullptr) {
  566. return nullptr;
  567. }
  568. ScopedPyObjectPtr res(PyObject_Call(m.get(), args, kwds));
  569. if (res == nullptr) {
  570. return nullptr;
  571. }
  572. int ret = InternalAssignRepeatedField(
  573. reinterpret_cast<RepeatedScalarContainer*>(pself), list.get());
  574. if (ret < 0) {
  575. return nullptr;
  576. }
  577. Py_RETURN_NONE;
  578. }
  579. static PyObject* Reverse(PyObject* pself) {
  580. ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr));
  581. if (full_slice == nullptr) {
  582. return nullptr;
  583. }
  584. ScopedPyObjectPtr list(Subscript(pself, full_slice.get()));
  585. if (list == nullptr) {
  586. return nullptr;
  587. }
  588. ScopedPyObjectPtr res(PyObject_CallMethod(list.get(), "reverse", nullptr));
  589. if (res == nullptr) {
  590. return nullptr;
  591. }
  592. int ret = InternalAssignRepeatedField(
  593. reinterpret_cast<RepeatedScalarContainer*>(pself), list.get());
  594. if (ret < 0) {
  595. return nullptr;
  596. }
  597. Py_RETURN_NONE;
  598. }
  599. static PyObject* Pop(PyObject* pself, PyObject* args) {
  600. Py_ssize_t index = -1;
  601. if (!PyArg_ParseTuple(args, "|n", &index)) {
  602. return nullptr;
  603. }
  604. PyObject* item = Item(pself, index);
  605. if (item == nullptr) {
  606. PyErr_Format(PyExc_IndexError, "list index (%zd) out of range", index);
  607. return nullptr;
  608. }
  609. if (AssignItem(pself, index, nullptr) < 0) {
  610. return nullptr;
  611. }
  612. return item;
  613. }
  614. static PyObject* ToStr(PyObject* pself) {
  615. ScopedPyObjectPtr full_slice(PySlice_New(nullptr, nullptr, nullptr));
  616. if (full_slice == nullptr) {
  617. return nullptr;
  618. }
  619. ScopedPyObjectPtr list(Subscript(pself, full_slice.get()));
  620. if (list == nullptr) {
  621. return nullptr;
  622. }
  623. return PyObject_Repr(list.get());
  624. }
  625. static PyObject* MergeFrom(PyObject* pself, PyObject* arg) {
  626. return Extend(reinterpret_cast<RepeatedScalarContainer*>(pself), arg);
  627. }
  628. // The private constructor of RepeatedScalarContainer objects.
  629. RepeatedScalarContainer* NewContainer(
  630. CMessage* parent, const FieldDescriptor* parent_field_descriptor) {
  631. if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) {
  632. return nullptr;
  633. }
  634. RepeatedScalarContainer* self = reinterpret_cast<RepeatedScalarContainer*>(
  635. PyType_GenericAlloc(&RepeatedScalarContainer_Type, 0));
  636. if (self == nullptr) {
  637. return nullptr;
  638. }
  639. Py_INCREF(parent);
  640. self->parent = parent;
  641. self->parent_field_descriptor = parent_field_descriptor;
  642. return self;
  643. }
  644. PyObject* DeepCopy(PyObject* pself, PyObject* arg) {
  645. return reinterpret_cast<RepeatedScalarContainer*>(pself)->DeepCopy();
  646. }
  647. static void Dealloc(PyObject* pself) {
  648. reinterpret_cast<RepeatedScalarContainer*>(pself)->RemoveFromParentCache();
  649. Py_TYPE(pself)->tp_free(pself);
  650. }
  651. static PySequenceMethods SqMethods = {
  652. Len, /* sq_length */
  653. nullptr, /* sq_concat */
  654. nullptr, /* sq_repeat */
  655. Item, /* sq_item */
  656. nullptr, /* sq_slice */
  657. AssignItem /* sq_ass_item */
  658. };
  659. static PyMappingMethods MpMethods = {
  660. Len, /* mp_length */
  661. Subscript, /* mp_subscript */
  662. AssSubscript, /* mp_ass_subscript */
  663. };
  664. static PyMethodDef Methods[] = {
  665. {"__deepcopy__", DeepCopy, METH_VARARGS, "Makes a deep copy of the class."},
  666. {"__reduce__", Reduce, METH_NOARGS,
  667. "Outputs picklable representation of the repeated field."},
  668. {"append", AppendMethod, METH_O,
  669. "Appends an object to the repeated container."},
  670. {"extend", ExtendMethod, METH_O,
  671. "Appends objects to the repeated container."},
  672. {"insert", Insert, METH_VARARGS,
  673. "Inserts an object at the specified position in the container."},
  674. {"pop", Pop, METH_VARARGS,
  675. "Removes an object from the repeated container and returns it."},
  676. {"remove", Remove, METH_O,
  677. "Removes an object from the repeated container."},
  678. {"sort", reinterpret_cast<PyCFunction>(Sort), METH_VARARGS | METH_KEYWORDS,
  679. "Sorts the repeated container."},
  680. {"reverse", reinterpret_cast<PyCFunction>(Reverse), METH_NOARGS,
  681. "Reverses elements order of the repeated container."},
  682. {"MergeFrom", static_cast<PyCFunction>(MergeFrom), METH_O,
  683. "Merges a repeated container into the current container."},
  684. {nullptr, nullptr}};
  685. } // namespace repeated_scalar_container
  686. PyTypeObject RepeatedScalarContainer_Type = {
  687. PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME
  688. ".RepeatedScalarContainer", // tp_name
  689. sizeof(RepeatedScalarContainer), // tp_basicsize
  690. 0, // tp_itemsize
  691. repeated_scalar_container::Dealloc, // tp_dealloc
  692. #if PY_VERSION_HEX >= 0x03080000
  693. 0, // tp_vectorcall_offset
  694. #else
  695. nullptr, // tp_print
  696. #endif
  697. nullptr, // tp_getattr
  698. nullptr, // tp_setattr
  699. nullptr, // tp_compare
  700. repeated_scalar_container::ToStr, // tp_repr
  701. nullptr, // tp_as_number
  702. &repeated_scalar_container::SqMethods, // tp_as_sequence
  703. &repeated_scalar_container::MpMethods, // tp_as_mapping
  704. PyObject_HashNotImplemented, // tp_hash
  705. nullptr, // tp_call
  706. nullptr, // tp_str
  707. nullptr, // tp_getattro
  708. nullptr, // tp_setattro
  709. nullptr, // tp_as_buffer
  710. Py_TPFLAGS_DEFAULT, // tp_flags
  711. "A Repeated scalar container", // tp_doc
  712. nullptr, // tp_traverse
  713. nullptr, // tp_clear
  714. repeated_scalar_container::RichCompare, // tp_richcompare
  715. 0, // tp_weaklistoffset
  716. nullptr, // tp_iter
  717. nullptr, // tp_iternext
  718. repeated_scalar_container::Methods, // tp_methods
  719. nullptr, // tp_members
  720. nullptr, // tp_getset
  721. nullptr, // tp_base
  722. nullptr, // tp_dict
  723. nullptr, // tp_descr_get
  724. nullptr, // tp_descr_set
  725. 0, // tp_dictoffset
  726. nullptr, // tp_init
  727. };
  728. } // namespace python
  729. } // namespace protobuf
  730. } // namespace google