pycapnp 2.2.2__cp39-cp39-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
capnp/__init__.pxd ADDED
File without changes
capnp/__init__.py ADDED
@@ -0,0 +1,62 @@
1
+ """A python library wrapping the Cap'n Proto C++ library
2
+
3
+ Example Usage::
4
+
5
+ import capnp
6
+
7
+ addressbook = capnp.load('addressbook.capnp')
8
+
9
+ # Building
10
+ addresses = addressbook.AddressBook.newMessage()
11
+ people = addresses.init('people', 1)
12
+
13
+ alice = people[0]
14
+ alice.id = 123
15
+ alice.name = 'Alice'
16
+ alice.email = 'alice@example.com'
17
+ alicePhone = alice.init('phones', 1)[0]
18
+ alicePhone.type = 'mobile'
19
+
20
+ f = open('example.bin', 'w')
21
+ addresses.write(f)
22
+ f.close()
23
+
24
+ # Reading
25
+ f = open('example.bin')
26
+
27
+ addresses = addressbook.AddressBook.read(f)
28
+
29
+ for person in addresses.people:
30
+ print(person.name, ':', person.email)
31
+ for phone in person.phones:
32
+ print(phone.type, ':', phone.number)
33
+ """
34
+
35
+ # flake8: noqa F401 F403 F405
36
+ from .version import version as __version__
37
+ from .lib.capnp import *
38
+ from .lib.capnp import (
39
+ _CapabilityClient,
40
+ _DynamicCapabilityClient,
41
+ _DynamicListBuilder,
42
+ _DynamicListReader,
43
+ _DynamicOrphan,
44
+ _DynamicResizableListBuilder,
45
+ _DynamicStructBuilder,
46
+ _DynamicStructReader,
47
+ _EventLoop,
48
+ _InterfaceModule,
49
+ _ListSchema,
50
+ _MallocMessageBuilder,
51
+ _PyCustomMessageBuilder,
52
+ _PackedFdMessageReader,
53
+ _StreamFdMessageReader,
54
+ _StructModule,
55
+ _write_message_to_fd,
56
+ _write_packed_message_to_fd,
57
+ _AsyncIoStream as AsyncIoStream,
58
+ _init_capnp_api,
59
+ )
60
+
61
+ _init_capnp_api()
62
+ add_import_hook() # enable import hook by default
capnp/_gen.py ADDED
@@ -0,0 +1,80 @@
1
+ import os
2
+ import sys
3
+
4
+ from jinja2 import Environment, PackageLoader
5
+
6
+ import capnp
7
+ import schema_capnp
8
+
9
+
10
+ def find_type(code, id):
11
+ for node in code["nodes"]:
12
+ if node["id"] == id:
13
+ return node
14
+
15
+ return None
16
+
17
+
18
+ def main():
19
+ env = Environment(loader=PackageLoader("capnp", "templates"))
20
+ env.filters["format_name"] = lambda name: name[name.find(":") + 1 :]
21
+
22
+ code = schema_capnp.CodeGeneratorRequest.read(sys.stdin)
23
+ code = code.to_dict()
24
+ code["nodes"] = [
25
+ node for node in code["nodes"] if "struct" in node and node["scopeId"] != 0
26
+ ]
27
+ for node in code["nodes"]:
28
+ displayName = node["displayName"]
29
+ parent, path = displayName.split(":")
30
+ node["module_path"] = (
31
+ parent.replace(".", "_")
32
+ + "."
33
+ + ".".join([x[0].upper() + x[1:] for x in path.split(".")])
34
+ )
35
+ node["module_name"] = path.replace(".", "_")
36
+ node["c_module_path"] = "::".join(
37
+ [x[0].upper() + x[1:] for x in path.split(".")]
38
+ )
39
+ node["schema"] = "_{}_Schema".format(node["module_name"])
40
+ is_union = False
41
+ for field in node["struct"]["fields"]:
42
+ if field["discriminantValue"] != 65535:
43
+ is_union = True
44
+ field["c_name"] = field["name"][0].upper() + field["name"][1:]
45
+ if "slot" in field:
46
+ field["type"] = list(field["slot"]["type"].keys())[0]
47
+ if not isinstance(field["slot"]["type"][field["type"]], dict):
48
+ continue
49
+ sub_type = field["slot"]["type"][field["type"]].get("typeId", None)
50
+ if sub_type:
51
+ field["sub_type"] = find_type(code, sub_type)
52
+ sub_type = field["slot"]["type"][field["type"]].get("elementType", None)
53
+ if sub_type:
54
+ field["sub_type"] = sub_type
55
+ else:
56
+ field["type"] = find_type(code, field["group"]["typeId"])
57
+ node["is_union"] = is_union
58
+
59
+ include_dir = os.path.abspath(os.path.join(os.path.dirname(capnp.__file__), ".."))
60
+ module = env.get_template("module.pyx")
61
+
62
+ for f in code["requestedFiles"]:
63
+ filename = f["filename"].replace(".", "_") + "_cython.pyx"
64
+
65
+ file_code = dict(code)
66
+ file_code["nodes"] = [
67
+ node
68
+ for node in file_code["nodes"]
69
+ if node["displayName"].startswith(f["filename"])
70
+ ]
71
+ with open(filename, "w") as out:
72
+ out.write(module.render(code=file_code, file=f, include_dir=include_dir))
73
+
74
+ setup = env.get_template("setup.py.tmpl")
75
+ with open("setup_capnp.py", "w") as out:
76
+ out.write(setup.render(code=code))
77
+ print(
78
+ "You now need to build the cython module by running `python setup_capnp.py build_ext --inplace`."
79
+ )
80
+ print()
capnp/c++.capnp ADDED
@@ -0,0 +1,48 @@
1
+ # Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
2
+ # Licensed under the MIT License:
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+
22
+ @0xbdf87d7bb8304e81;
23
+ $namespace("capnp::annotations");
24
+
25
+ annotation namespace(file): Text;
26
+ annotation name(field, enumerant, struct, enum, interface, method, param, group, union): Text;
27
+
28
+ annotation allowCancellation(interface, method, file) :Void;
29
+ # Indicates that the server-side implementation of a method is allowed to be canceled when the
30
+ # client requests cancellation. Without this annotation, once a method call has been delivered to
31
+ # the server-side application code, any requests by the client to cancel it will be ignored, and
32
+ # the method will run to completion anyway. This applies even for local in-process calls.
33
+ #
34
+ # This behavior applies specifically to implementations that inherit from the C++ `Foo::Server`
35
+ # interface. The annotation won't affect DynamicCapability::Server implementations; they must set
36
+ # the cancellation mode at runtime.
37
+ #
38
+ # When applied to an interface rather than an individual method, the annotation applies to all
39
+ # methods in the interface. When applied to a file, it applies to all methods defined in the file.
40
+ #
41
+ # It's generally recommended that this annotation be applied to all methods. However, when doing
42
+ # so, it is important that the server implementation use cancellation-safe code. See:
43
+ #
44
+ # https://github.com/capnproto/capnproto/blob/master/kjdoc/tour.md#cancellation
45
+ #
46
+ # If your code is not cancellation-safe, then allowing cancellation might give a malicious client
47
+ # an easy way to induce use-after-free or other bugs in your server, by requesting cancellation
48
+ # when not expected.
File without changes
@@ -0,0 +1,139 @@
1
+ #pragma once
2
+
3
+ #include "capnp/dynamic.h"
4
+ #include <kj/async-io.h>
5
+ #include <capnp/serialize-async.h>
6
+ #include <stdexcept>
7
+ #include "Python.h"
8
+
9
+ class GILAcquire {
10
+ public:
11
+ GILAcquire() : gstate(PyGILState_Ensure()) {}
12
+ ~GILAcquire() {
13
+ PyGILState_Release(gstate);
14
+ }
15
+
16
+ PyGILState_STATE gstate;
17
+ };
18
+
19
+ class GILRelease {
20
+ public:
21
+ GILRelease() {
22
+ Py_UNBLOCK_THREADS
23
+ }
24
+ ~GILRelease() {
25
+ Py_BLOCK_THREADS
26
+ }
27
+
28
+ PyThreadState *_save; // The macros above read/write from this variable
29
+ };
30
+
31
+ class PyRefCounter {
32
+ public:
33
+ PyObject * obj;
34
+
35
+ PyRefCounter(PyObject * o) : obj(o) {
36
+ GILAcquire gil;
37
+ Py_INCREF(obj);
38
+ }
39
+
40
+ PyRefCounter(const PyRefCounter & ref) : obj(ref.obj) {
41
+ GILAcquire gil;
42
+ Py_INCREF(obj);
43
+ }
44
+
45
+ ~PyRefCounter() {
46
+ GILAcquire gil;
47
+ Py_DECREF(obj);
48
+ }
49
+ };
50
+
51
+ inline kj::Own<PyRefCounter> stealPyRef(PyObject* o) {
52
+ auto ret = kj::heap<PyRefCounter>(o);
53
+ Py_DECREF(o);
54
+ return ret;
55
+ }
56
+
57
+ ::kj::Promise<kj::Own<PyRefCounter>> convert_to_pypromise(capnp::RemotePromise<capnp::DynamicStruct> promise);
58
+
59
+ inline ::kj::Promise<kj::Own<PyRefCounter>> convert_to_pypromise(kj::Promise<void> promise) {
60
+ return promise.then([]() {
61
+ GILAcquire gil;
62
+ return kj::heap<PyRefCounter>(Py_None);
63
+ });
64
+ }
65
+
66
+ void c_reraise_kj_exception();
67
+
68
+ void check_py_error();
69
+
70
+ ::kj::Promise<kj::Own<PyRefCounter>> then(kj::Promise<kj::Own<PyRefCounter>> promise,
71
+ kj::Own<PyRefCounter> func, kj::Own<PyRefCounter> error_func);
72
+
73
+ class PythonInterfaceDynamicImpl final: public capnp::DynamicCapability::Server {
74
+ public:
75
+ kj::Own<PyRefCounter> py_server;
76
+ kj::Own<PyRefCounter> kj_loop;
77
+
78
+ #if (CAPNP_VERSION_MAJOR < 1)
79
+ PythonInterfaceDynamicImpl(capnp::InterfaceSchema & schema,
80
+ kj::Own<PyRefCounter> _py_server,
81
+ kj::Own<PyRefCounter> kj_loop)
82
+ : capnp::DynamicCapability::Server(schema),
83
+ py_server(kj::mv(_py_server)), kj_loop(kj::mv(kj_loop)) { }
84
+ #else
85
+ PythonInterfaceDynamicImpl(capnp::InterfaceSchema & schema,
86
+ kj::Own<PyRefCounter> _py_server,
87
+ kj::Own<PyRefCounter> kj_loop)
88
+ : capnp::DynamicCapability::Server(schema, { true }),
89
+ py_server(kj::mv(_py_server)), kj_loop(kj::mv(kj_loop)) { }
90
+ #endif
91
+
92
+ ~PythonInterfaceDynamicImpl() {
93
+ }
94
+
95
+ kj::Promise<void> call(capnp::InterfaceSchema::Method method,
96
+ capnp::CallContext< capnp::DynamicStruct, capnp::DynamicStruct> context);
97
+ };
98
+
99
+ inline void allowCancellation(capnp::CallContext<capnp::DynamicStruct, capnp::DynamicStruct> context) {
100
+ #if (CAPNP_VERSION_MAJOR < 1)
101
+ context.allowCancellation();
102
+ #endif
103
+ }
104
+
105
+ class PyAsyncIoStream: public kj::AsyncIoStream {
106
+ public:
107
+ kj::Own<PyRefCounter> protocol;
108
+
109
+ PyAsyncIoStream(kj::Own<PyRefCounter> protocol) : protocol(kj::mv(protocol)) {}
110
+ ~PyAsyncIoStream();
111
+
112
+ kj::Promise<size_t> tryRead(void* buffer, size_t minBytes, size_t maxBytes);
113
+
114
+ kj::Promise<void> write(const void* buffer, size_t size);
115
+
116
+ kj::Promise<void> write(kj::ArrayPtr<const kj::ArrayPtr<const kj::byte>> pieces);
117
+
118
+ kj::Promise<void> whenWriteDisconnected();
119
+
120
+ void shutdownWrite();
121
+ };
122
+
123
+ template <typename T>
124
+ inline void rejectDisconnected(kj::PromiseFulfiller<T>& fulfiller, kj::StringPtr message) {
125
+ fulfiller.reject(KJ_EXCEPTION(DISCONNECTED, message));
126
+ }
127
+ inline void rejectVoidDisconnected(kj::PromiseFulfiller<void>& fulfiller, kj::StringPtr message) {
128
+ fulfiller.reject(KJ_EXCEPTION(DISCONNECTED, message));
129
+ }
130
+
131
+ inline kj::Exception makeException(kj::StringPtr message) {
132
+ return KJ_EXCEPTION(FAILED, message);
133
+ }
134
+
135
+ kj::Promise<void> taskToPromise(kj::Own<PyRefCounter> coroutine, PyObject* callback);
136
+
137
+ ::kj::Promise<kj::Own<PyRefCounter>> tryReadMessage(kj::AsyncIoStream& stream, capnp::ReaderOptions opts);
138
+
139
+ void init_capnp_api();
@@ -0,0 +1,8 @@
1
+ #ifdef _MSC_VER
2
+ #pragma comment(lib, "Ws2_32.lib")
3
+ #pragma comment(lib, "advapi32.lib")
4
+ #endif
5
+
6
+ #include "capnp/dynamic.h"
7
+
8
+ static_assert(CAPNP_VERSION >= 8000, "Version of Cap'n Proto C++ Library is too old. Please upgrade to a version >= 0.8 and then re-install this python library");
@@ -0,0 +1,12 @@
1
+ #pragma once
2
+
3
+ #include "capnp/dynamic.h"
4
+ #include "capnp/schema.capnp.h"
5
+
6
+ /// @brief Convert the dynamic struct to a Node::Reader
7
+ ::capnp::schema::Node::Reader toReader(capnp::DynamicStruct::Reader reader)
8
+ {
9
+ // requires an intermediate step to AnyStruct before going directly to Node::Reader,
10
+ // since there exists no direct conversion from DynamicStruct::Reader to Node::Reader.
11
+ return reader.as<capnp::AnyStruct>().as<capnp::schema::Node>();
12
+ }
@@ -0,0 +1,11 @@
1
+ #include "kj/common.h"
2
+ #include <stdexcept>
3
+
4
+ template<typename T>
5
+ T fixMaybe(::kj::Maybe<T> val) {
6
+ KJ_IF_MAYBE(new_val, val) {
7
+ return *new_val;
8
+ } else {
9
+ throw std::invalid_argument("Member was null.");
10
+ }
11
+ }
@@ -0,0 +1,34 @@
1
+ from capnp.includes.capnp_cpp cimport (
2
+ Maybe, PyPromise, VoidPromise, RemotePromise,
3
+ DynamicCapability, InterfaceSchema, EnumSchema, StructSchema, DynamicValue, Capability,
4
+ RpcSystem, MessageBuilder, Own, PyRefCounter, Node, DynamicStruct, CallContext
5
+ )
6
+
7
+ from capnp.includes.schema_cpp cimport ByteArray
8
+
9
+ from non_circular cimport c_reraise_kj_exception as reraise_kj_exception
10
+
11
+ from cpython.ref cimport PyObject
12
+
13
+ cdef extern from "capnp/helpers/fixMaybe.h":
14
+ EnumSchema.Enumerant fixMaybe(Maybe[EnumSchema.Enumerant]) except +reraise_kj_exception
15
+ StructSchema.Field fixMaybe(Maybe[StructSchema.Field]) except +reraise_kj_exception
16
+
17
+ cdef extern from "capnp/helpers/capabilityHelper.h":
18
+ PyPromise then(PyPromise promise, Own[PyRefCounter] func, Own[PyRefCounter] error_func)
19
+ PyPromise convert_to_pypromise(RemotePromise)
20
+ PyPromise convert_to_pypromise(VoidPromise)
21
+ VoidPromise taskToPromise(Own[PyRefCounter] coroutine, PyObject* callback)
22
+ void allowCancellation(CallContext context) except +reraise_kj_exception nogil
23
+ void init_capnp_api()
24
+
25
+ cdef extern from "capnp/helpers/rpcHelper.h":
26
+ Own[Capability.Client] bootstrapHelper(RpcSystem&) except +reraise_kj_exception
27
+ Own[Capability.Client] bootstrapHelperServer(RpcSystem&) except +reraise_kj_exception
28
+
29
+ cdef extern from "capnp/helpers/serialize.h":
30
+ ByteArray messageToPackedBytes(MessageBuilder &, size_t wordCount) except +reraise_kj_exception
31
+
32
+ cdef extern from "capnp/helpers/deserialize.h":
33
+ Node.Reader toReader(DynamicStruct.Reader reader) except +reraise_kj_exception
34
+
@@ -0,0 +1,8 @@
1
+ from cpython.ref cimport PyObject
2
+ from libcpp cimport bool
3
+
4
+ cdef extern from "capnp/helpers/capabilityHelper.h":
5
+ void c_reraise_kj_exception()
6
+ cdef cppclass PyRefCounter:
7
+ PyRefCounter(PyObject *)
8
+ PyObject * obj
@@ -0,0 +1,21 @@
1
+ #pragma once
2
+
3
+ #include "capnp/dynamic.h"
4
+ #include <capnp/rpc.capnp.h>
5
+ #include "capnp/rpc-twoparty.h"
6
+ #include "Python.h"
7
+ #include "capabilityHelper.h"
8
+
9
+ kj::Own<capnp::Capability::Client> bootstrapHelper(capnp::RpcSystem<capnp::rpc::twoparty::SturdyRefHostId>& client) {
10
+ capnp::MallocMessageBuilder hostIdMessage(8);
11
+ auto hostId = hostIdMessage.initRoot<capnp::rpc::twoparty::SturdyRefHostId>();
12
+ hostId.setSide(capnp::rpc::twoparty::Side::SERVER);
13
+ return kj::heap<capnp::Capability::Client>(client.bootstrap(hostId));
14
+ }
15
+
16
+ kj::Own<capnp::Capability::Client> bootstrapHelperServer(capnp::RpcSystem<capnp::rpc::twoparty::SturdyRefHostId>& client) {
17
+ capnp::MallocMessageBuilder hostIdMessage(8);
18
+ auto hostId = hostIdMessage.initRoot<capnp::rpc::twoparty::SturdyRefHostId>();
19
+ hostId.setSide(capnp::rpc::twoparty::Side::CLIENT);
20
+ return kj::heap<capnp::Capability::Client>(client.bootstrap(hostId));
21
+ }
@@ -0,0 +1,14 @@
1
+ #pragma once
2
+
3
+ #include "kj/io.h"
4
+ #include "capnp/dynamic.h"
5
+ #include "capnp/serialize-packed.h"
6
+
7
+ kj::Array< ::capnp::byte> messageToPackedBytes(capnp::MessageBuilder & message, size_t wordCount)
8
+ {
9
+
10
+ kj::Array<capnp::byte> result = kj::heapArray<capnp::byte>(wordCount * 8);
11
+ kj::ArrayOutputStream out(result.asPtr());
12
+ capnp::writePackedMessage(out, message);
13
+ return heapArray(out.getArray()); // TODO: make this non-copying somehow
14
+ }
@@ -0,0 +1,28 @@
1
+ #pragma once
2
+
3
+ #include "Python.h"
4
+ #include <capnp/message.h>
5
+ #include <capnp/serialize.h>
6
+ #include <vector>
7
+
8
+ namespace capnp {
9
+
10
+ class PyCustomMessageBuilder : public capnp::MessageBuilder {
11
+ public:
12
+ explicit PyCustomMessageBuilder(PyObject* allocateSegmentCallable,
13
+ uint firstSegmentWords = capnp::SUGGESTED_FIRST_SEGMENT_WORDS);
14
+
15
+ ~PyCustomMessageBuilder() noexcept(false) override;
16
+
17
+ kj::ArrayPtr<capnp::word> allocateSegment(capnp::uint minimumSize) override;
18
+
19
+ private:
20
+ PyObject* allocateSegmentCallable;
21
+
22
+ uint firstSize;
23
+ uint curSize = 0;
24
+
25
+ std::vector<PyObject*> allocatedBuffers;
26
+ };
27
+
28
+ }
File without changes