upb/python/protobuf.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009-2021, Google LLC
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of Google LLC nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "python/protobuf.h"
29 
30 #include "python/descriptor.h"
32 #include "python/descriptor_pool.h"
33 #include "python/extension_dict.h"
34 #include "python/map.h"
35 #include "python/message.h"
36 #include "python/repeated.h"
37 
38 static void PyUpb_ModuleDealloc(void* module) {
39  PyUpb_ModuleState* s = PyModule_GetState(module);
40  PyUpb_WeakMap_Free(s->obj_cache);
41  if (s->c_descriptor_symtab) {
42  upb_DefPool_Free(s->c_descriptor_symtab);
43  }
44 }
45 
46 PyObject* PyUpb_SetAllowOversizeProtos(PyObject* m, PyObject* arg) {
47  if (!arg || !PyBool_Check(arg)) {
48  PyErr_SetString(PyExc_TypeError,
49  "Argument to SetAllowOversizeProtos must be boolean");
50  return NULL;
51  }
53  state->allow_oversize_protos = PyObject_IsTrue(arg);
54  Py_INCREF(arg);
55  return arg;
56 }
57 
58 static PyMethodDef PyUpb_ModuleMethods[] = {
59  {"SetAllowOversizeProtos", PyUpb_SetAllowOversizeProtos, METH_O,
60  "Enable/disable oversize proto parsing."},
61  {NULL, NULL}};
62 
63 static struct PyModuleDef module_def = {PyModuleDef_HEAD_INIT,
65  "Protobuf Module",
66  sizeof(PyUpb_ModuleState),
67  PyUpb_ModuleMethods, // m_methods
68  NULL, // m_slots
69  NULL, // m_traverse
70  NULL, // m_clear
72 
73 // -----------------------------------------------------------------------------
74 // ModuleState
75 // -----------------------------------------------------------------------------
76 
78  PyObject* module = PyState_FindModule(&module_def);
79  return module ? PyModule_GetState(module) : NULL;
80 }
81 
83  PyUpb_ModuleState* state = PyModule_GetState(module);
84  assert(state);
85  assert(PyModule_GetDef(module) == &module_def);
86  return state;
87 }
88 
90  PyObject* module = PyState_FindModule(&module_def);
91  assert(module);
93 }
94 
96  if (!state->wkt_bases) {
97  PyObject* wkt_module = PyImport_ImportModule(PYUPB_PROTOBUF_INTERNAL_PACKAGE
98  ".well_known_types");
99 
100  if (wkt_module == NULL) {
101  return false;
102  }
103 
104  state->wkt_bases = PyObject_GetAttrString(wkt_module, "WKTBASES");
105  PyObject* m = PyState_FindModule(&module_def);
106  // Reparent ownership to m.
107  PyModule_AddObject(m, "__internal_wktbases", state->wkt_bases);
108  Py_DECREF(wkt_module);
109  }
110 
111  return state->wkt_bases;
112 }
113 
114 // -----------------------------------------------------------------------------
115 // WeakMap
116 // -----------------------------------------------------------------------------
117 
121 };
122 
126  map->arena = arena;
127  upb_inttable_init(&map->table, map->arena);
128  return map;
129 }
130 
132 
135  assert((n & 7) == 0);
136  return n >> 3;
137 }
138 
139 void PyUpb_WeakMap_Add(PyUpb_WeakMap* map, const void* key, PyObject* py_obj) {
141  upb_value_ptr(py_obj), map->arena);
142 }
143 
145  upb_value val;
146  bool removed =
148  (void)removed;
149  assert(removed);
150 }
151 
154 }
155 
156 PyObject* PyUpb_WeakMap_Get(PyUpb_WeakMap* map, const void* key) {
157  upb_value val;
158  if (upb_inttable_lookup(&map->table, PyUpb_WeakMap_GetKey(key), &val)) {
159  PyObject* ret = upb_value_getptr(val);
160  Py_INCREF(ret);
161  return ret;
162  } else {
163  return NULL;
164  }
165 }
166 
167 bool PyUpb_WeakMap_Next(PyUpb_WeakMap* map, const void** key, PyObject** obj,
168  intptr_t* iter) {
169  uintptr_t u_key;
170  upb_value val;
171  if (!upb_inttable_next2(&map->table, &u_key, &val, iter)) return false;
172  *key = (void*)(u_key << 3);
173  *obj = upb_value_getptr(val);
174  return true;
175 }
176 
178  upb_inttable_removeiter(&map->table, iter);
179 }
180 
181 // -----------------------------------------------------------------------------
182 // ObjCache
183 // -----------------------------------------------------------------------------
184 
187  return state->obj_cache;
188 }
189 
190 void PyUpb_ObjCache_Add(const void* key, PyObject* py_obj) {
192 }
193 
194 void PyUpb_ObjCache_Delete(const void* key) {
196  if (!state) {
197  // During the shutdown sequence, our object's Dealloc() methods can be
198  // called *after* our module Dealloc() method has been called. At that
199  // point our state will be NULL and there is nothing to delete out of the
200  // map.
201  return;
202  }
203  PyUpb_WeakMap_Delete(state->obj_cache, key);
204 }
205 
206 PyObject* PyUpb_ObjCache_Get(const void* key) {
208 }
209 
210 // -----------------------------------------------------------------------------
211 // Arena
212 // -----------------------------------------------------------------------------
213 
214 typedef struct {
217 } PyUpb_Arena;
218 
219 PyObject* PyUpb_Arena_New(void) {
221  PyUpb_Arena* arena = (void*)PyType_GenericAlloc(state->arena_type, 0);
222  arena->arena = upb_Arena_New();
223  return &arena->ob_base;
224 }
225 
226 static void PyUpb_Arena_Dealloc(PyObject* self) {
228  PyUpb_Dealloc(self);
229 }
230 
232  return ((PyUpb_Arena*)arena)->arena;
233 }
234 
235 static PyType_Slot PyUpb_Arena_Slots[] = {
236  {Py_tp_dealloc, PyUpb_Arena_Dealloc},
237  {0, NULL},
238 };
239 
240 static PyType_Spec PyUpb_Arena_Spec = {
241  PYUPB_MODULE_NAME ".Arena",
242  sizeof(PyUpb_Arena),
243  0, // itemsize
244  Py_TPFLAGS_DEFAULT,
246 };
247 
248 static bool PyUpb_InitArena(PyObject* m) {
250  state->arena_type = PyUpb_AddClass(m, &PyUpb_Arena_Spec);
251  return state->arena_type;
252 }
253 
254 // -----------------------------------------------------------------------------
255 // Utilities
256 // -----------------------------------------------------------------------------
257 
258 PyTypeObject* AddObject(PyObject* m, const char* name, PyType_Spec* spec) {
259  PyObject* type = PyType_FromSpec(spec);
260  return type && PyModule_AddObject(m, name, type) == 0 ? (PyTypeObject*)type
261  : NULL;
262 }
263 
264 static const char* PyUpb_GetClassName(PyType_Spec* spec) {
265  // spec->name contains a fully-qualified name, like:
266  // google.protobuf.pyext._message.FooBar
267  //
268  // Find the rightmost '.' to get "FooBar".
269  const char* name = strrchr(spec->name, '.');
270  assert(name);
271  return name + 1;
272 }
273 
274 PyTypeObject* PyUpb_AddClass(PyObject* m, PyType_Spec* spec) {
275  PyObject* type = PyType_FromSpec(spec);
276  const char* name = PyUpb_GetClassName(spec);
277  if (PyModule_AddObject(m, name, type) < 0) {
278  Py_XDECREF(type);
279  return NULL;
280  }
281  return (PyTypeObject*)type;
282 }
283 
284 PyTypeObject* PyUpb_AddClassWithBases(PyObject* m, PyType_Spec* spec,
285  PyObject* bases) {
286  PyObject* type = PyType_FromSpecWithBases(spec, bases);
287  const char* name = PyUpb_GetClassName(spec);
288  if (PyModule_AddObject(m, name, type) < 0) {
289  Py_XDECREF(type);
290  return NULL;
291  }
292  return (PyTypeObject*)type;
293 }
294 
295 const char* PyUpb_GetStrData(PyObject* obj) {
296  if (PyUnicode_Check(obj)) {
297  return PyUnicode_AsUTF8AndSize(obj, NULL);
298  } else if (PyBytes_Check(obj)) {
299  return PyBytes_AsString(obj);
300  } else {
301  return NULL;
302  }
303 }
304 
305 const char* PyUpb_VerifyStrData(PyObject* obj) {
306  const char* ret = PyUpb_GetStrData(obj);
307  if (ret) return ret;
308  PyErr_Format(PyExc_TypeError, "Expected string: %S", obj);
309  return NULL;
310 }
311 
312 PyObject* PyUpb_Forbidden_New(PyObject* cls, PyObject* args, PyObject* kwds) {
313  PyObject* name = PyObject_GetAttrString(cls, "__name__");
314  PyErr_Format(PyExc_RuntimeError,
315  "Objects of type %U may not be created directly.", name);
316  Py_XDECREF(name);
317  return NULL;
318 }
319 
320 // -----------------------------------------------------------------------------
321 // Module Entry Point
322 // -----------------------------------------------------------------------------
323 
324 PyMODINIT_FUNC PyInit__message(void) {
325  PyObject* m = PyModule_Create(&module_def);
326  if (!m) return NULL;
327 
329 
330  state->allow_oversize_protos = false;
331  state->wkt_bases = NULL;
332  state->obj_cache = PyUpb_WeakMap_New();
333  state->c_descriptor_symtab = NULL;
334 
339  Py_DECREF(m);
340  return NULL;
341  }
342 
343  // Temporary: an cookie we can use in the tests to ensure we are testing upb
344  // and not another protobuf library on the system.
345  PyModule_AddIntConstant(m, "_IS_UPB", 1);
346 
347  return m;
348 }
PyUpb_WeakMap
Definition: upb/python/protobuf.c:118
PyUpb_GetStrData
const char * PyUpb_GetStrData(PyObject *obj)
Definition: upb/python/protobuf.c:295
obj
OPENSSL_EXPORT const ASN1_OBJECT * obj
Definition: x509.h:1671
upb_inttable_removeiter
void upb_inttable_removeiter(upb_inttable *t, intptr_t *iter)
Definition: table.c:827
PyUpb_WeakMap_Delete
void PyUpb_WeakMap_Delete(PyUpb_WeakMap *map, const void *key)
Definition: upb/python/protobuf.c:144
upb_inttable_insert
UPB_INLINE bool upb_inttable_insert(upb_inttable *t, uintptr_t key, upb_value val)
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.h:942
PyUpb_InitExtensionDict
bool PyUpb_InitExtensionDict(PyObject *m)
Definition: extension_dict.c:240
module_def
static struct PyModuleDef module_def
Definition: upb/python/protobuf.c:63
PyUpb_Map_Init
bool PyUpb_Map_Init(PyObject *m)
Definition: upb/python/map.c:491
upb_value
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.h:681
PyUpb_InitDescriptorPool
bool PyUpb_InitDescriptorPool(PyObject *m)
Definition: descriptor_pool.c:632
PyUpb_ModuleState_GetFromModule
PyUpb_ModuleState * PyUpb_ModuleState_GetFromModule(PyObject *module)
Definition: upb/python/protobuf.c:82
PyUpb_SetAllowOversizeProtos
PyObject * PyUpb_SetAllowOversizeProtos(PyObject *m, PyObject *arg)
Definition: upb/python/protobuf.c:46
PyUpb_Arena_Spec
static PyType_Spec PyUpb_Arena_Spec
Definition: upb/python/protobuf.c:240
setup.name
name
Definition: setup.py:542
PyUpb_Arena
Definition: upb/python/protobuf.c:214
PyUpb_GetWktBases
PyObject * PyUpb_GetWktBases(PyUpb_ModuleState *state)
Definition: upb/python/protobuf.c:95
map
zval * map
Definition: php/ext/google/protobuf/encode_decode.c:480
upb_Arena_New
UPB_INLINE upb_Arena * upb_Arena_New(void)
Definition: upb/upb/upb.h:267
run_interop_tests.spec
def spec
Definition: run_interop_tests.py:1394
arena
grpc_core::ScopedArenaPtr arena
Definition: binder_transport_test.cc:237
PyUpb_AddClassWithBases
PyTypeObject * PyUpb_AddClassWithBases(PyObject *m, PyType_Spec *spec, PyObject *bases)
Definition: upb/python/protobuf.c:284
PyUpb_InitArena
static bool PyUpb_InitArena(PyObject *m)
Definition: upb/python/protobuf.c:248
upb_inttable_next2
bool upb_inttable_next2(const upb_inttable *t, uintptr_t *key, upb_value *val, intptr_t *iter)
Definition: table.c:800
PyUpb_Repeated_Init
bool PyUpb_Repeated_Init(PyObject *m)
Definition: repeated.c:805
PyUpb_WeakMap_TryDelete
void PyUpb_WeakMap_TryDelete(PyUpb_WeakMap *map, const void *key)
Definition: upb/python/protobuf.c:152
PyUpb_Arena_Slots
static PyType_Slot PyUpb_Arena_Slots[]
Definition: upb/python/protobuf.c:235
asyncio_get_stats.args
args
Definition: asyncio_get_stats.py:40
PyUpb_InitDescriptorContainers
bool PyUpb_InitDescriptorContainers(PyObject *m)
Definition: descriptor_containers.c:693
PyUpb_Dealloc
static void PyUpb_Dealloc(void *self)
Definition: upb/python/protobuf.h:208
PyUpb_ModuleMethods
static PyMethodDef PyUpb_ModuleMethods[]
Definition: upb/python/protobuf.c:58
descriptor_containers.h
PYUPB_PROTOBUF_INTERNAL_PACKAGE
#define PYUPB_PROTOBUF_INTERNAL_PACKAGE
Definition: upb/python/protobuf.h:40
descriptor.h
upb_Arena_Malloc
UPB_INLINE void * upb_Arena_Malloc(upb_Arena *a, size_t size)
Definition: upb/upb/upb.h:222
upb_inttable_init
UPB_INLINE bool upb_inttable_init(upb_inttable *table, upb_ctype_t ctype)
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.h:901
upb_inttable
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.h:848
PyUpb_Arena_Dealloc
static void PyUpb_Arena_Dealloc(PyObject *self)
Definition: upb/python/protobuf.c:226
extension_dict.h
arg
Definition: cmdline.cc:40
PyUpb_AddClass
PyTypeObject * PyUpb_AddClass(PyObject *m, PyType_Spec *spec)
Definition: upb/python/protobuf.c:274
intptr_t
_W64 signed int intptr_t
Definition: stdint-msvc2008.h:118
PyUpb_WeakMap::arena
upb_Arena * arena
Definition: upb/python/protobuf.c:120
PyUpb_VerifyStrData
const char * PyUpb_VerifyStrData(PyObject *obj)
Definition: upb/python/protobuf.c:305
uintptr_t
_W64 unsigned int uintptr_t
Definition: stdint-msvc2008.h:119
PyUpb_Forbidden_New
PyObject * PyUpb_Forbidden_New(PyObject *cls, PyObject *args, PyObject *kwds)
Definition: upb/python/protobuf.c:312
PyUpb_ObjCache_Instance
PyUpb_WeakMap * PyUpb_ObjCache_Instance(void)
Definition: upb/python/protobuf.c:185
PyUpb_WeakMap_DeleteIter
void PyUpb_WeakMap_DeleteIter(PyUpb_WeakMap *map, intptr_t *iter)
Definition: upb/python/protobuf.c:177
protobuf.h
PyUpb_WeakMap_Get
PyObject * PyUpb_WeakMap_Get(PyUpb_WeakMap *map, const void *key)
Definition: upb/python/protobuf.c:156
n
int n
Definition: abseil-cpp/absl/container/btree_test.cc:1080
PyUpb_WeakMap_Add
void PyUpb_WeakMap_Add(PyUpb_WeakMap *map, const void *key, PyObject *py_obj)
Definition: upb/python/protobuf.c:139
PyUpb_ObjCache_Get
PyObject * PyUpb_ObjCache_Get(const void *key)
Definition: upb/python/protobuf.c:206
PyUpb_ModuleState_Get
PyUpb_ModuleState * PyUpb_ModuleState_Get(void)
Definition: upb/python/protobuf.c:89
message.h
PyUpb_Arena_Get
upb_Arena * PyUpb_Arena_Get(PyObject *arena)
Definition: upb/python/protobuf.c:231
AddObject
PyTypeObject * AddObject(PyObject *m, const char *name, PyType_Spec *spec)
Definition: upb/python/protobuf.c:258
PyUpb_Arena::arena
upb_Arena * arena
Definition: upb/python/protobuf.c:216
key
const char * key
Definition: hpack_parser_table.cc:164
PyUpb_InitDescriptor
bool PyUpb_InitDescriptor(PyObject *m)
Definition: descriptor.c:1654
PyUpb_Arena_New
PyObject * PyUpb_Arena_New(void)
Definition: upb/python/protobuf.c:219
PYUPB_MODULE_NAME
#define PYUPB_MODULE_NAME
Definition: upb/python/protobuf.h:43
upb_DefPool_Free
void upb_DefPool_Free(upb_DefPool *s)
Definition: upb/upb/def.c:1081
upb_inttable_lookup
bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v)
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:1803
PyInit__message
PyMODINIT_FUNC PyInit__message(void)
Definition: upb/python/protobuf.c:324
PyUpb_WeakMap_New
PyUpb_WeakMap * PyUpb_WeakMap_New(void)
Definition: upb/python/protobuf.c:123
upb_inttable_remove
bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val)
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:1817
PyUpb_ModuleState
Definition: upb/python/protobuf.h:66
PyUpb_ObjCache_Add
void PyUpb_ObjCache_Add(const void *key, PyObject *py_obj)
Definition: upb/python/protobuf.c:190
ret
UniquePtr< SSL_SESSION > ret
Definition: ssl_x509.cc:1029
PyUpb_InitMessage
bool PyUpb_InitMessage(PyObject *m)
Definition: upb/python/message.c:1823
descriptor_database_test_wrapper.module
module
Definition: descriptor_database_test_wrapper.py:30
PyUpb_ModuleDealloc
static void PyUpb_ModuleDealloc(void *module)
Definition: upb/python/protobuf.c:38
arg
struct arg arg
state
Definition: bloaty/third_party/zlib/contrib/blast/blast.c:41
PyUpb_WeakMap::table
upb_inttable table
Definition: upb/python/protobuf.c:119
PyUpb_Arena::PyObject_HEAD
PyObject_HEAD
Definition: upb/python/protobuf.c:215
iter
Definition: test_winkernel.cpp:47
asyncio_get_stats.type
type
Definition: asyncio_get_stats.py:37
descriptor_pool.h
PyUpb_WeakMap_Free
void PyUpb_WeakMap_Free(PyUpb_WeakMap *map)
Definition: upb/python/protobuf.c:131
PyUpb_GetClassName
static const char * PyUpb_GetClassName(PyType_Spec *spec)
Definition: upb/python/protobuf.c:264
regress.m
m
Definition: regress/regress.py:25
PyUpb_ObjCache_Delete
void PyUpb_ObjCache_Delete(const void *key)
Definition: upb/python/protobuf.c:194
PyUpb_WeakMap_GetKey
uintptr_t PyUpb_WeakMap_GetKey(const void *key)
Definition: upb/python/protobuf.c:133
map.h
upb_Arena
Definition: upb_internal.h:36
upb_Arena_Free
void upb_Arena_Free(upb_Arena *a)
Definition: upb/upb/upb.c:273
PyUpb_ModuleState_MaybeGet
PyUpb_ModuleState * PyUpb_ModuleState_MaybeGet(void)
Definition: upb/python/protobuf.c:77
state
static struct rpc_state state
Definition: bad_server_response_test.cc:87
repeated.h
PyUpb_WeakMap_Next
bool PyUpb_WeakMap_Next(PyUpb_WeakMap *map, const void **key, PyObject **obj, intptr_t *iter)
Definition: upb/python/protobuf.c:167


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:00:56