parent
7092e60341
commit
94ece04552
10 changed files with 833 additions and 1 deletions
@ -0,0 +1,28 @@ |
|||||||
|
|
||||||
|
_build_file = """ |
||||||
|
cc_library( |
||||||
|
name = "python_headers", |
||||||
|
hdrs = glob(["python/**/*.h"]), |
||||||
|
includes = ["python"], |
||||||
|
visibility = ["//visibility:public"], |
||||||
|
) |
||||||
|
""" |
||||||
|
|
||||||
|
def _find_python_dir(repository_ctx): |
||||||
|
versions = ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11"] |
||||||
|
for version in versions: |
||||||
|
path = "/usr/include/python" + version |
||||||
|
if repository_ctx.path(path + "/" + "Python.h").exists: |
||||||
|
return path |
||||||
|
fail("No Python headers found in /usr/include/python3.* (require 3.6 or newer)") |
||||||
|
|
||||||
|
def _python_headers_impl(repository_ctx): |
||||||
|
path = _find_python_dir(repository_ctx) |
||||||
|
repository_ctx.symlink(path, "python") |
||||||
|
repository_ctx.file("BUILD.bazel", _build_file) |
||||||
|
|
||||||
|
|
||||||
|
python_headers = repository_rule( |
||||||
|
implementation = _python_headers_impl, |
||||||
|
local = True, |
||||||
|
) |
@ -0,0 +1,30 @@ |
|||||||
|
load( |
||||||
|
"//bazel:build_defs.bzl", |
||||||
|
"UPB_DEFAULT_COPTS", |
||||||
|
) |
||||||
|
|
||||||
|
cc_binary( |
||||||
|
name = "message", |
||||||
|
srcs = [ |
||||||
|
"descriptor.c", |
||||||
|
"descriptor.h", |
||||||
|
"descriptor_pool.c", |
||||||
|
"descriptor_pool.h", |
||||||
|
"protobuf.c", |
||||||
|
"protobuf.h", |
||||||
|
], |
||||||
|
copts = UPB_DEFAULT_COPTS + [ |
||||||
|
# The Python API requires patterns that are ISO C incompatible, like |
||||||
|
# casts between function pointers and object pointers. |
||||||
|
"-Wno-pedantic", |
||||||
|
], |
||||||
|
linkopts = ["-Wl,--version-script,$(location :version_script.lds)"], |
||||||
|
linkshared = True, |
||||||
|
linkstatic = True, |
||||||
|
deps = [ |
||||||
|
":version_script.lds", |
||||||
|
"//:reflection", |
||||||
|
"//:upb", |
||||||
|
"@python_headers", |
||||||
|
], |
||||||
|
) |
@ -0,0 +1,249 @@ |
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2021, Google LLC |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are met: |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* * Neither the name of Google LLC nor the |
||||||
|
* names of its contributors may be used to endorse or promote products |
||||||
|
* derived from this software without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||||||
|
* DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY |
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "python/descriptor.h" |
||||||
|
|
||||||
|
#include "python/protobuf.h" |
||||||
|
#include "upb/def.h" |
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// DescriptorBase
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// This representation is used by all concrete descriptors.
|
||||||
|
|
||||||
|
typedef struct { |
||||||
|
PyObject_HEAD |
||||||
|
PyObject *pool; // We own a ref.
|
||||||
|
const void *def; // Type depends on the class. Kept alive by "pool".
|
||||||
|
} PyUpb_DescriptorBase; |
||||||
|
|
||||||
|
PyObject *PyUpb_AnyDescriptor_GetPool(PyObject *desc) { |
||||||
|
PyUpb_DescriptorBase *base = (void*)desc; |
||||||
|
return base->pool; |
||||||
|
} |
||||||
|
|
||||||
|
static PyObject *PyUpb_DescriptorBase_New(PyTypeObject *subtype, PyObject *args, |
||||||
|
PyObject *kwds) { |
||||||
|
return PyErr_Format(PyExc_RuntimeError, |
||||||
|
"Creating descriptors directly is not allowed."); |
||||||
|
} |
||||||
|
|
||||||
|
static PyObject *PyUpb_DescriptorBase_NewInternal(PyTypeObject *type, |
||||||
|
const void *def, |
||||||
|
PyObject *pool) { |
||||||
|
PyUpb_DescriptorBase *base = PyObject_New(PyUpb_DescriptorBase, type); |
||||||
|
base->pool = pool; |
||||||
|
base->def = def; |
||||||
|
Py_INCREF(pool); |
||||||
|
PyUpb_ObjCache_Add(def, &base->ob_base); |
||||||
|
return &base->ob_base; |
||||||
|
} |
||||||
|
|
||||||
|
static void PyUpb_DescriptorBase_Dealloc(PyUpb_DescriptorBase *self) { |
||||||
|
PyUpb_DescriptorBase *base = (PyUpb_DescriptorBase*)self; |
||||||
|
PyUpb_ObjCache_Delete(base->def); |
||||||
|
Py_CLEAR(base->pool); |
||||||
|
PyObject_Del(self); |
||||||
|
} |
||||||
|
|
||||||
|
#define DESCRIPTOR_BASE_SLOTS \ |
||||||
|
{Py_tp_new, (void*)&PyUpb_DescriptorBase_New}, \
|
||||||
|
{Py_tp_dealloc, (void*)&PyUpb_DescriptorBase_Dealloc} |
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// FieldDescriptor
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
typedef struct { |
||||||
|
PyObject_HEAD |
||||||
|
upb_fielddef *fielddef; |
||||||
|
} PyUpb_FieldDescriptor; |
||||||
|
|
||||||
|
static PyObject *PyUpb_FieldDescriptor_GetType(PyUpb_DescriptorBase *self, |
||||||
|
void *closure) { |
||||||
|
return PyLong_FromLong(upb_fielddef_descriptortype(self->def)); |
||||||
|
} |
||||||
|
|
||||||
|
static PyObject *PyUpb_FieldDescriptor_GetLabel(PyUpb_DescriptorBase *self, |
||||||
|
void *closure) { |
||||||
|
return PyLong_FromLong(upb_fielddef_label(self->def)); |
||||||
|
} |
||||||
|
|
||||||
|
static PyGetSetDef PyUpb_FieldDescriptor_Getters[] = { |
||||||
|
/*
|
||||||
|
{ "full_name", (getter)GetFullName, NULL, "Full name"}, |
||||||
|
{ "name", (getter)GetName, NULL, "Unqualified name"}, |
||||||
|
{ "camelcase_name", (getter)GetCamelcaseName, NULL, "Camelcase name"}, |
||||||
|
{ "json_name", (getter)GetJsonName, NULL, "Json name"}, |
||||||
|
{ "file", (getter)GetFile, NULL, "File Descriptor"}, |
||||||
|
*/ |
||||||
|
{ "type", (getter)PyUpb_FieldDescriptor_GetType, NULL, "Type"}, |
||||||
|
/*
|
||||||
|
{ "cpp_type", (getter)PyUpb_FieldDescriptor_GetCppType, NULL, "C++ Type"}, |
||||||
|
*/ |
||||||
|
{ "label", (getter)PyUpb_FieldDescriptor_GetLabel, NULL, "Label"}, |
||||||
|
/*
|
||||||
|
{ "number", (getter)GetNumber, NULL, "Number"}, |
||||||
|
{ "index", (getter)GetIndex, NULL, "Index"}, |
||||||
|
{ "default_value", (getter)GetDefaultValue, NULL, "Default Value"}, |
||||||
|
{ "has_default_value", (getter)HasDefaultValue}, |
||||||
|
{ "is_extension", (getter)IsExtension, NULL, "ID"}, |
||||||
|
{ "id", (getter)GetID, NULL, "ID"}, |
||||||
|
{ "_cdescriptor", (getter)GetCDescriptor, NULL, "HAACK REMOVE ME"}, |
||||||
|
|
||||||
|
{ "message_type", (getter)GetMessageType, (setter)SetMessageType, |
||||||
|
"Message type"}, |
||||||
|
{ "enum_type", (getter)GetEnumType, (setter)SetEnumType, "Enum type"}, |
||||||
|
{ "containing_type", (getter)GetContainingType, (setter)SetContainingType, |
||||||
|
"Containing type"}, |
||||||
|
{ "extension_scope", (getter)GetExtensionScope, (setter)NULL, |
||||||
|
"Extension scope"}, |
||||||
|
{ "containing_oneof", (getter)GetContainingOneof, (setter)SetContainingOneof, |
||||||
|
"Containing oneof"}, |
||||||
|
{ "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"}, |
||||||
|
{ "_options", (getter)NULL, (setter)SetOptions, "Options"}, |
||||||
|
{ "_serialized_options", (getter)NULL, (setter)SetSerializedOptions, |
||||||
|
"Serialized Options"}, |
||||||
|
*/ |
||||||
|
{NULL} |
||||||
|
}; |
||||||
|
|
||||||
|
static PyMethodDef PyUpb_FieldDescriptor_Methods[] = { |
||||||
|
/*
|
||||||
|
{ "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, }, |
||||||
|
*/ |
||||||
|
{NULL} |
||||||
|
}; |
||||||
|
|
||||||
|
static PyType_Slot PyUpb_FieldDescriptor_Slots[] = { |
||||||
|
DESCRIPTOR_BASE_SLOTS, |
||||||
|
{Py_tp_methods, PyUpb_FieldDescriptor_Methods}, |
||||||
|
{Py_tp_getset, PyUpb_FieldDescriptor_Getters}, |
||||||
|
{0, NULL} |
||||||
|
}; |
||||||
|
|
||||||
|
static PyType_Spec PyUpb_FieldDescriptor_Spec = { |
||||||
|
PYUPB_MODULE_NAME ".FieldDescriptor", // tp_name
|
||||||
|
sizeof(PyUpb_FieldDescriptor), // tp_basicsize
|
||||||
|
0, // tp_itemsize
|
||||||
|
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||||
|
PyUpb_FieldDescriptor_Slots, |
||||||
|
}; |
||||||
|
|
||||||
|
PyObject *PyUpb_FieldDescriptor_GetOrCreateWrapper(const upb_fielddef *field, |
||||||
|
PyObject *pool) { |
||||||
|
PyUpb_ModuleState *state = PyUpb_ModuleState_Get(); |
||||||
|
return PyUpb_DescriptorBase_NewInternal(state->field_descriptor_type, field, |
||||||
|
pool); |
||||||
|
} |
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// FileDescriptor
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
static PyObject *PyUpb_FileDescriptor_GetName(PyUpb_DescriptorBase *self, |
||||||
|
void *closure) { |
||||||
|
return PyUnicode_FromString(upb_filedef_name(self->def)); |
||||||
|
} |
||||||
|
|
||||||
|
static PyGetSetDef PyUpb_FileDescriptor_Getters[] = { |
||||||
|
/*
|
||||||
|
{ "pool", (getter)GetPool, NULL, "pool"}, |
||||||
|
*/ |
||||||
|
{ "name", (getter)PyUpb_FileDescriptor_GetName, NULL, "name"}, |
||||||
|
/*
|
||||||
|
{ "package", (getter)GetPackage, NULL, "package"}, |
||||||
|
{ "serialized_pb", (getter)GetSerializedPb}, |
||||||
|
{ "message_types_by_name", PyUpb_FileDescriptor_GetMessageTypesByName, NULL, |
||||||
|
"Messages by name"}, |
||||||
|
{ "enum_types_by_name", PyUpb_FileDescriptor_GetEnumTypesByName, NULL, |
||||||
|
"Enums by name"}, |
||||||
|
{ "extensions_by_name", (getter)GetExtensionsByName, NULL, |
||||||
|
"Extensions by name"}, |
||||||
|
{ "services_by_name", (getter)GetServicesByName, NULL, "Services by name"}, |
||||||
|
{ "dependencies", (getter)GetDependencies, NULL, "Dependencies"}, |
||||||
|
{ "public_dependencies", (getter)GetPublicDependencies, NULL, "Dependencies"}, |
||||||
|
|
||||||
|
{ "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"}, |
||||||
|
{ "_options", (getter)NULL, (setter)SetOptions, "Options"}, |
||||||
|
{ "_serialized_options", (getter)NULL, (setter)SetSerializedOptions, |
||||||
|
"Serialized Options"}, |
||||||
|
{ "syntax", (getter)GetSyntax, (setter)NULL, "Syntax"}, |
||||||
|
*/ |
||||||
|
{NULL} |
||||||
|
}; |
||||||
|
|
||||||
|
static PyMethodDef PyUpb_FileDescriptor_Methods[] = { |
||||||
|
/*
|
||||||
|
{ "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, }, |
||||||
|
{ "CopyToProto", (PyCFunction)CopyToProto, METH_O, }, |
||||||
|
*/ |
||||||
|
{NULL} |
||||||
|
}; |
||||||
|
|
||||||
|
static PyType_Slot PyUpb_FileDescriptor_Slots[] = { |
||||||
|
DESCRIPTOR_BASE_SLOTS, |
||||||
|
{Py_tp_methods, PyUpb_FileDescriptor_Methods}, |
||||||
|
{Py_tp_getset, PyUpb_FileDescriptor_Getters}, |
||||||
|
{0, NULL} |
||||||
|
}; |
||||||
|
|
||||||
|
static PyType_Spec PyUpb_FileDescriptor_Spec = { |
||||||
|
PYUPB_MODULE_NAME ".FileDescriptor", // tp_name
|
||||||
|
sizeof(PyUpb_DescriptorBase), // tp_basicsize
|
||||||
|
0, // tp_itemsize
|
||||||
|
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||||
|
PyUpb_FileDescriptor_Slots, |
||||||
|
}; |
||||||
|
|
||||||
|
PyObject *PyUpb_FileDescriptor_GetOrCreateWrapper(const upb_filedef *file, |
||||||
|
PyObject *pool) { |
||||||
|
PyUpb_ModuleState *state = PyUpb_ModuleState_Get(); |
||||||
|
return PyUpb_DescriptorBase_NewInternal(state->file_descriptor_type, file, |
||||||
|
pool); |
||||||
|
} |
||||||
|
|
||||||
|
const upb_filedef *PyUpb_FileDescriptor_GetDef(PyObject *_self) { |
||||||
|
PyUpb_DescriptorBase *self = (void*)_self; |
||||||
|
return self->def; |
||||||
|
} |
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Top Level
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool PyUpb_InitDescriptor(PyObject* m) { |
||||||
|
PyUpb_ModuleState *s = PyUpb_ModuleState_Get(); |
||||||
|
|
||||||
|
s->field_descriptor_type = |
||||||
|
AddObject(m, "FieldDescriptor", &PyUpb_FieldDescriptor_Spec); |
||||||
|
s->file_descriptor_type = |
||||||
|
AddObject(m, "FileDescriptor", &PyUpb_FileDescriptor_Spec); |
||||||
|
|
||||||
|
return s->field_descriptor_type && s->file_descriptor_type; |
||||||
|
} |
@ -0,0 +1,46 @@ |
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2021, Google LLC |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are met: |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* * Neither the name of Google LLC nor the |
||||||
|
* names of its contributors may be used to endorse or promote products |
||||||
|
* derived from this software without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||||||
|
* DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY |
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef PYPB_DESCRIPTOR_H__ |
||||||
|
#define PYPB_DESCRIPTOR_H__ |
||||||
|
|
||||||
|
#include <stdbool.h> |
||||||
|
|
||||||
|
#include "upb/def.h" |
||||||
|
|
||||||
|
#include "protobuf.h" |
||||||
|
|
||||||
|
PyObject *PyUpb_FieldDescriptor_GetOrCreateWrapper(const upb_fielddef *field, |
||||||
|
PyObject *pool); |
||||||
|
PyObject *PyUpb_FileDescriptor_GetOrCreateWrapper(const upb_filedef *file, |
||||||
|
PyObject *pool); |
||||||
|
|
||||||
|
const upb_filedef *PyUpb_FileDescriptor_GetDef(PyObject *file); |
||||||
|
|
||||||
|
bool PyUpb_InitDescriptor(PyObject* m); |
||||||
|
|
||||||
|
#endif // PYPB_DESCRIPTOR_H__
|
@ -0,0 +1,215 @@ |
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2021, Google LLC |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are met: |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* * Neither the name of Google LLC nor the |
||||||
|
* names of its contributors may be used to endorse or promote products |
||||||
|
* derived from this software without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT, |
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "python/descriptor_pool.h" |
||||||
|
|
||||||
|
#include "python/descriptor.h" |
||||||
|
#include "python/protobuf.h" |
||||||
|
#include "upb/def.h" |
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// DescriptorPool
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
typedef struct { |
||||||
|
PyObject_HEAD |
||||||
|
upb_symtab* symtab; |
||||||
|
PyObject* db; |
||||||
|
} PyUpb_DescriptorPool; |
||||||
|
|
||||||
|
static PyObject* PyUpb_DescriptorPool_DoCreate(PyTypeObject* type, PyObject* db) { |
||||||
|
PyUpb_DescriptorPool* pool = PyObject_New(PyUpb_DescriptorPool, type); |
||||||
|
pool->symtab = upb_symtab_new(); |
||||||
|
pool->db = db; |
||||||
|
return &pool->ob_base; |
||||||
|
} |
||||||
|
|
||||||
|
static void PyUpb_DescriptorPool_Dealloc(PyUpb_DescriptorPool *self) { |
||||||
|
upb_symtab_free(self->symtab); |
||||||
|
Py_CLEAR(self->db); |
||||||
|
PyObject_Del(self); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* DescriptorPool.__new__() |
||||||
|
* |
||||||
|
* Implements: |
||||||
|
* DescriptorPool(descriptor_db=None) |
||||||
|
*/ |
||||||
|
static PyObject* PyUpb_DescriptorPool_New(PyTypeObject* type, PyObject* args, |
||||||
|
PyObject* kwargs) { |
||||||
|
char* kwlist[] = {"descriptor_db", 0}; |
||||||
|
PyObject* db = NULL; |
||||||
|
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &db)) { |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
return PyUpb_DescriptorPool_DoCreate(type, db); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* PyUpb_DescriptorPool_AddSerializedFile() |
||||||
|
* |
||||||
|
* Implements: |
||||||
|
* DescriptorPool.AddSerializedFile(self, serialized_file_descriptor) |
||||||
|
* |
||||||
|
* Adds the given serialized FileDescriptorProto to the pool. |
||||||
|
*/ |
||||||
|
static PyObject* PyUpb_DescriptorPool_AddSerializedFile( |
||||||
|
PyObject* _self, PyObject* serialized_pb) { |
||||||
|
PyUpb_DescriptorPool* self = (PyUpb_DescriptorPool*)_self; |
||||||
|
char* buf; |
||||||
|
Py_ssize_t size; |
||||||
|
upb_arena* arena = upb_arena_new(); |
||||||
|
PyObject* result = NULL; |
||||||
|
|
||||||
|
if (self->db) { |
||||||
|
PyErr_SetString( |
||||||
|
PyExc_ValueError, |
||||||
|
"Cannot call Add on a DescriptorPool that uses a DescriptorDatabase. " |
||||||
|
"Add your file to the underlying database."); |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
if (PyBytes_AsStringAndSize(serialized_pb, &buf, &size) < 0) { |
||||||
|
goto done; |
||||||
|
} |
||||||
|
|
||||||
|
google_protobuf_FileDescriptorProto* proto = |
||||||
|
google_protobuf_FileDescriptorProto_parse(buf, size, arena); |
||||||
|
if (!proto) { |
||||||
|
PyErr_SetString(PyExc_TypeError, "Couldn't parse file content!"); |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
upb_status status; |
||||||
|
upb_status_clear(&status); |
||||||
|
|
||||||
|
const upb_filedef* filedef = upb_symtab_addfile(self->symtab, proto, &status); |
||||||
|
if (!filedef) { |
||||||
|
PyErr_Format(PyExc_TypeError, |
||||||
|
"Couldn't build proto file into descriptor pool: %s", |
||||||
|
upb_status_errmsg(&status)); |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
result = PyUpb_FileDescriptor_GetOrCreateWrapper(filedef, _self); |
||||||
|
|
||||||
|
done: |
||||||
|
upb_arena_free(arena); |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* PyUpb_DescriptorPool_FindExtensionByName() |
||||||
|
* |
||||||
|
* Implements: |
||||||
|
* DescriptorPool.FindExtensionByName(self, name) |
||||||
|
*/ |
||||||
|
static PyObject* PyUpb_DescriptorPool_FindExtensionByName(PyObject* _self, |
||||||
|
PyObject* arg) { |
||||||
|
PyUpb_DescriptorPool* self = (PyUpb_DescriptorPool*)_self; |
||||||
|
|
||||||
|
const char* name = PyUpb_GetStrData(arg); |
||||||
|
if (!name) { |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
const upb_fielddef* field = upb_symtab_lookupext(self->symtab, name); |
||||||
|
if (field == NULL) { |
||||||
|
return PyErr_Format(PyExc_KeyError, "Couldn't find extension %.200s", name); |
||||||
|
} |
||||||
|
|
||||||
|
return PyUpb_FieldDescriptor_GetOrCreateWrapper(field, _self); |
||||||
|
} |
||||||
|
|
||||||
|
static PyMethodDef PyUpb_DescriptorPool_Methods[] = { |
||||||
|
/*
|
||||||
|
TODO: implement remaining methods. |
||||||
|
{ "Add", Add, METH_O, |
||||||
|
"Adds the FileDescriptorProto and its types to this pool." }, |
||||||
|
*/ |
||||||
|
{"AddSerializedFile", PyUpb_DescriptorPool_AddSerializedFile, METH_O, |
||||||
|
"Adds a serialized FileDescriptorProto to this pool."}, |
||||||
|
/*
|
||||||
|
{ "FindFileByName", FindFileByName, METH_O, |
||||||
|
"Searches for a file descriptor by its .proto name." }, |
||||||
|
{ "FindMessageTypeByName", FindMessageByName, METH_O, |
||||||
|
"Searches for a message descriptor by full name." }, |
||||||
|
{ "FindFieldByName", FindFieldByNameMethod, METH_O, |
||||||
|
"Searches for a field descriptor by full name." }, |
||||||
|
*/ |
||||||
|
{"FindExtensionByName", PyUpb_DescriptorPool_FindExtensionByName, METH_O, |
||||||
|
"Searches for extension descriptor by full name."}, |
||||||
|
/*
|
||||||
|
{ "FindEnumTypeByName", FindEnumTypeByNameMethod, METH_O, |
||||||
|
"Searches for enum type descriptor by full name." }, |
||||||
|
{ "FindOneofByName", FindOneofByNameMethod, METH_O, |
||||||
|
"Searches for oneof descriptor by full name." }, |
||||||
|
{ "FindServiceByName", FindServiceByName, METH_O, |
||||||
|
"Searches for service descriptor by full name." }, |
||||||
|
{ "FindMethodByName", FindMethodByName, METH_O, |
||||||
|
"Searches for method descriptor by full name." }, |
||||||
|
{ "FindFileContainingSymbol", FindFileContainingSymbol, METH_O, |
||||||
|
"Gets the FileDescriptor containing the specified symbol." }, |
||||||
|
{ "FindExtensionByNumber", FindExtensionByNumber, METH_VARARGS, |
||||||
|
"Gets the extension descriptor for the given number." }, |
||||||
|
{ "FindAllExtensions", FindAllExtensions, METH_O, |
||||||
|
"Gets all known extensions of the given message descriptor." }, |
||||||
|
*/ |
||||||
|
{NULL}}; |
||||||
|
|
||||||
|
static PyType_Slot PyUpb_DescriptorPool_Slots[] = { |
||||||
|
{Py_tp_new, PyUpb_DescriptorPool_New}, |
||||||
|
{Py_tp_dealloc, PyUpb_DescriptorPool_Dealloc}, |
||||||
|
{Py_tp_methods, PyUpb_DescriptorPool_Methods}, |
||||||
|
{0, NULL}}; |
||||||
|
|
||||||
|
static PyType_Spec PyUpb_DescriptorPool_Spec = { |
||||||
|
PYUPB_MODULE_NAME ".DescriptorPool", // tp_name
|
||||||
|
sizeof(PyUpb_DescriptorPool), // tp_basicsize
|
||||||
|
0, // tp_itemsize
|
||||||
|
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||||
|
PyUpb_DescriptorPool_Slots, |
||||||
|
}; |
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Top Level
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool PyUpb_InitDescriptorPool(PyObject* m) { |
||||||
|
PyTypeObject* descriptor_pool_type = |
||||||
|
AddObject(m, "DescriptorPool", &PyUpb_DescriptorPool_Spec); |
||||||
|
|
||||||
|
if (!descriptor_pool_type) return false; |
||||||
|
|
||||||
|
PyObject* default_pool = |
||||||
|
PyUpb_DescriptorPool_DoCreate(descriptor_pool_type, NULL); |
||||||
|
return default_pool && |
||||||
|
PyModule_AddObject(m, "default_pool", default_pool) == 0; |
||||||
|
} |
@ -0,0 +1,37 @@ |
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2021, Google LLC |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are met: |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* * Neither the name of Google LLC nor the |
||||||
|
* names of its contributors may be used to endorse or promote products |
||||||
|
* derived from this software without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||||||
|
* DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY |
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef PYUPB_DESCRIPTOR_POOL_H__ |
||||||
|
#define PYUPB_DESCRIPTOR_POOL_H__ |
||||||
|
|
||||||
|
#include <stdbool.h> |
||||||
|
|
||||||
|
#include "protobuf.h" |
||||||
|
|
||||||
|
bool PyUpb_InitDescriptorPool(PyObject* m); |
||||||
|
|
||||||
|
#endif // PYUPB_DESCRIPTOR_POOL_H__
|
@ -0,0 +1,123 @@ |
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2021, Google LLC |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are met: |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* * Neither the name of Google LLC nor the |
||||||
|
* names of its contributors may be used to endorse or promote products |
||||||
|
* derived from this software without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT, |
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "protobuf.h" |
||||||
|
|
||||||
|
#include "descriptor_pool.h" |
||||||
|
|
||||||
|
static void PyUpb_ModuleDealloc(void *_s) { |
||||||
|
PyUpb_ModuleState *s = _s; |
||||||
|
upb_arena_free(s->obj_cache_arena); |
||||||
|
} |
||||||
|
|
||||||
|
static struct PyModuleDef module_def = {PyModuleDef_HEAD_INIT, |
||||||
|
PYUPB_MODULE_NAME, |
||||||
|
"Protobuf Module", |
||||||
|
sizeof(PyUpb_ModuleState), |
||||||
|
NULL, // m_methods
|
||||||
|
NULL, // m_slots
|
||||||
|
NULL, // m_traverse
|
||||||
|
NULL, // m_clear
|
||||||
|
PyUpb_ModuleDealloc}; |
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// ModuleState
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
PyUpb_ModuleState *PyUpb_ModuleState_Get() { |
||||||
|
PyObject *module = PyState_FindModule(&module_def); |
||||||
|
return PyModule_GetState(module); |
||||||
|
} |
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// ObjectCache
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void PyUpb_ObjCache_Add(const void *key, PyObject *py_obj) { |
||||||
|
PyUpb_ModuleState *s = PyUpb_ModuleState_Get(); |
||||||
|
upb_inttable_insert(&s->obj_cache, (uintptr_t)key, upb_value_ptr(py_obj), |
||||||
|
s->obj_cache_arena); |
||||||
|
} |
||||||
|
|
||||||
|
void PyUpb_ObjCache_Delete(const void *key) { |
||||||
|
PyUpb_ModuleState *s = PyUpb_ModuleState_Get(); |
||||||
|
upb_value val; |
||||||
|
upb_inttable_remove(&s->obj_cache, (uintptr_t)key, &val); |
||||||
|
assert(upb_value_getptr(val)); |
||||||
|
} |
||||||
|
|
||||||
|
PyObject *PyUpb_ObjCache_Get(const void *key) { |
||||||
|
PyUpb_ModuleState *s = PyUpb_ModuleState_Get(); |
||||||
|
upb_value val; |
||||||
|
if (upb_inttable_lookup(&s->obj_cache, (uintptr_t)key, &val)) { |
||||||
|
PyObject *ret = upb_value_getptr(val); |
||||||
|
Py_INCREF(ret); |
||||||
|
return ret; |
||||||
|
} else { |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Utilities
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
PyTypeObject *AddObject(PyObject *m, const char *name, PyType_Spec *spec) { |
||||||
|
PyObject *type = PyType_FromSpec(spec); |
||||||
|
return type && PyModule_AddObject(m, name, type) == 0 ? (PyTypeObject *)type |
||||||
|
: NULL; |
||||||
|
} |
||||||
|
|
||||||
|
const char *PyUpb_GetStrData(PyObject *obj) { |
||||||
|
if (PyUnicode_Check(obj)) { |
||||||
|
return PyUnicode_AsUTF8AndSize(obj, NULL); |
||||||
|
} else if (PyBytes_Check(obj)) { |
||||||
|
return PyBytes_AsString(obj); |
||||||
|
} else { |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Module Entry Point
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
PyMODINIT_FUNC PyInit__message(void) { |
||||||
|
PyObject *m = PyModule_Create(&module_def); |
||||||
|
PyState_AddModule(m, &module_def); |
||||||
|
PyUpb_ModuleState *state = PyUpb_ModuleState_Get(); |
||||||
|
|
||||||
|
state->obj_cache_arena = upb_arena_new(); |
||||||
|
upb_inttable_init(&state->obj_cache, state->obj_cache_arena); |
||||||
|
|
||||||
|
if (!PyUpb_InitDescriptorPool(m)) { |
||||||
|
Py_DECREF(m); |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
return m; |
||||||
|
} |
@ -0,0 +1,94 @@ |
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2021, Google LLC |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are met: |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* * Neither the name of Google LLC nor the |
||||||
|
* names of its contributors may be used to endorse or promote products |
||||||
|
* derived from this software without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||||||
|
* DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY |
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef PYUPB_PROTOBUF_H__ |
||||||
|
#define PYUPB_PROTOBUF_H__ |
||||||
|
|
||||||
|
#include <stdbool.h> |
||||||
|
|
||||||
|
#define Py_LIMITED_API 0x03060000 |
||||||
|
#include <Python.h> |
||||||
|
|
||||||
|
// This function was not officially added to the limited API until Python 3.10.
|
||||||
|
// But in practice it has been stable since Python 3.1. See:
|
||||||
|
// https://bugs.python.org/issue41784
|
||||||
|
PyAPI_FUNC(const char *) PyUnicode_AsUTF8AndSize( |
||||||
|
PyObject *unicode, |
||||||
|
Py_ssize_t *size); |
||||||
|
|
||||||
|
#include "upb/table_internal.h" |
||||||
|
|
||||||
|
#define PYUPB_MODULE_NAME "google.protobuf.pyext._message" |
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// ModuleState
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// We store all "global" state in this struct instead of using (C) global
|
||||||
|
// variables. This makes this extension compatible with sub-interpreters.
|
||||||
|
|
||||||
|
typedef struct { |
||||||
|
// From descriptor.c
|
||||||
|
PyTypeObject *field_descriptor_type; |
||||||
|
PyTypeObject *file_descriptor_type; |
||||||
|
|
||||||
|
// From descriptor_pool.c
|
||||||
|
PyTypeObject *descriptor_pool_type; |
||||||
|
|
||||||
|
// From protobuf.c
|
||||||
|
upb_arena *obj_cache_arena; |
||||||
|
upb_inttable obj_cache; |
||||||
|
} PyUpb_ModuleState; |
||||||
|
|
||||||
|
// Returns the global state object from the current interpreter. The current
|
||||||
|
// interpreter is looked up from thread-local state.
|
||||||
|
PyUpb_ModuleState *PyUpb_ModuleState_Get(void); |
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// ObjectCache
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// The ObjectCache is a weak map that maps C pointers to the corresponding
|
||||||
|
// Python wrapper object. We want a consistent Python wrapper object for each
|
||||||
|
// C object, both to save memory and to provide object stability (ie. x is x).
|
||||||
|
//
|
||||||
|
// Each wrapped object should add itself to the map when it is constructed and
|
||||||
|
// remove itself from the map when it is destroyed. The map is weak so it does
|
||||||
|
// not take references to the cached objects.
|
||||||
|
|
||||||
|
void PyUpb_ObjCache_Add(const void *key, PyObject *py_obj); |
||||||
|
void PyUpb_ObjCache_Delete(const void *key); |
||||||
|
PyObject *PyUpb_ObjCache_Get(const void *key); // returns NULL if not present.
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Utilities
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
PyTypeObject *AddObject(PyObject *m, const char* name, PyType_Spec* spec); |
||||||
|
const char *PyUpb_GetStrData(PyObject *obj); |
||||||
|
|
||||||
|
#endif // PYUPB_PROTOBUF_H__
|
@ -0,0 +1,6 @@ |
|||||||
|
message { |
||||||
|
global: |
||||||
|
PyInit__message; |
||||||
|
local: |
||||||
|
*; |
||||||
|
}; |
Loading…
Reference in new issue