Merge pull request #285 from madhavajay/madhava/python_310
Add Python 3.10 support
This commit is contained in:
4
.github/workflows/manylinux2010.yml
vendored
4
.github/workflows/manylinux2010.yml
vendored
@@ -9,7 +9,7 @@ jobs:
|
||||
container: ${{ matrix.container-image }}
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ['cp37-cp37m', 'cp38-cp38', 'cp39-cp39']
|
||||
python-version: ['cp37-cp37m', 'cp38-cp38', 'cp39-cp39', 'cp310-cp310']
|
||||
container-image: ['quay.io/pypa/manylinux2010_x86_64', 'quay.io/pypa/manylinux2010_i686']
|
||||
|
||||
steps:
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ['cp37-cp37m', 'cp38-cp38', 'cp39-cp39']
|
||||
python-version: ['cp37-cp37m', 'cp38-cp38', 'cp39-cp39', 'cp310-cp310']
|
||||
fail-fast: false
|
||||
env:
|
||||
py: /opt/python/${{ matrix.python-version }}/bin/python
|
||||
|
||||
2
.github/workflows/packagingtest.yml
vendored
2
.github/workflows/packagingtest.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
matrix:
|
||||
# Some asyncio commands require 3.7+
|
||||
# It may be possible to use 3.6 and maybe 3.5; however, this will take some patching to get examples to work
|
||||
python-version: [3.7, 3.8, 3.9]
|
||||
python-version: [3.7, 3.8, 3.9, "3.10"]
|
||||
os: [ubuntu-latest, macOS-latest, windows-latest]
|
||||
|
||||
steps:
|
||||
|
||||
@@ -35,8 +35,7 @@ def writeAddressBook():
|
||||
|
||||
|
||||
def printAddressBook(msg_bytes):
|
||||
addressBook = addressbook.AddressBook.from_bytes(msg_bytes)
|
||||
|
||||
with addressbook.AddressBook.from_bytes(msg_bytes) as addressBook:
|
||||
for person in addressBook.people:
|
||||
print(person.name, ":", person.email)
|
||||
for phone in person.phones:
|
||||
|
||||
@@ -40,8 +40,7 @@ def writeAddressBook():
|
||||
|
||||
@profile
|
||||
def printAddressBook(msg_bytes):
|
||||
addressBook = addressbook.AddressBook.from_bytes(msg_bytes)
|
||||
|
||||
with addressbook.AddressBook.from_bytes(msg_bytes) as addressBook:
|
||||
for person in addressBook.people:
|
||||
person.name, person.email
|
||||
for phone in person.phones:
|
||||
|
||||
@@ -22,6 +22,7 @@ from libc.string cimport memcpy
|
||||
import array
|
||||
import asyncio
|
||||
import collections as _collections
|
||||
import contextlib
|
||||
import enum as _enum
|
||||
import inspect as _inspect
|
||||
import os as _os
|
||||
@@ -1098,7 +1099,8 @@ if getattr(_sys, 'subversion', [''])[0] == 'PyPy':
|
||||
from pickle_helper import _struct_reducer
|
||||
else:
|
||||
def _struct_reducer(schema_id, data):
|
||||
return _global_schema_parser.modules_by_id[schema_id].from_bytes(data)
|
||||
with _global_schema_parser.modules_by_id[schema_id].from_bytes(data) as msg:
|
||||
return msg
|
||||
|
||||
|
||||
cdef class _DynamicStructReader:
|
||||
@@ -3320,6 +3322,7 @@ class _StructModule(object):
|
||||
reader = _MultipleBytesPackedMessageReader(buf, self.schema, traversal_limit_in_words, nesting_limit)
|
||||
return reader
|
||||
|
||||
@contextlib.contextmanager
|
||||
def from_bytes(self, buf, traversal_limit_in_words=None, nesting_limit=None, builder=False):
|
||||
"""Returns a Reader for the unpacked object in buf.
|
||||
|
||||
@@ -3340,13 +3343,18 @@ class _StructModule(object):
|
||||
|
||||
:rtype: :class:`_DynamicStructReader` or :class:`_DynamicStructBuilder`
|
||||
"""
|
||||
message = None
|
||||
try:
|
||||
if builder:
|
||||
# message = _FlatMessageBuilder(buf)
|
||||
message = _FlatArrayMessageReader(buf, traversal_limit_in_words, nesting_limit)
|
||||
return message.get_root(self.schema).as_builder()
|
||||
yield message.get_root(self.schema).as_builder()
|
||||
else:
|
||||
message = _FlatArrayMessageReader(buf, traversal_limit_in_words, nesting_limit)
|
||||
return message.get_root(self.schema)
|
||||
yield message.get_root(self.schema)
|
||||
finally:
|
||||
if message:
|
||||
message.close()
|
||||
|
||||
def from_segments(self, segments, traversal_limit_in_words=None, nesting_limit=None):
|
||||
"""Returns a Reader for a list of segment bytes.
|
||||
@@ -4088,15 +4096,22 @@ cdef class _AlignedBuffer:
|
||||
cdef class _BufferView:
|
||||
cdef Py_buffer view
|
||||
cdef char * buf
|
||||
cdef int closed
|
||||
|
||||
def __init__(self, other):
|
||||
cdef int ret = PyObject_GetBuffer(other, &self.view, PyBUF_SIMPLE)
|
||||
if ret < 0:
|
||||
raise ValueError("Invalid buffer passed to BufferView")
|
||||
self.buf = <char*>self.view.buf
|
||||
self.closed = False
|
||||
|
||||
def close(self):
|
||||
if not self.closed:
|
||||
PyBuffer_Release(&self.view)
|
||||
self.closed = True
|
||||
|
||||
def __dealloc__(self):
|
||||
PyBuffer_Release(&self.view)
|
||||
self.close()
|
||||
|
||||
|
||||
@cython.internal
|
||||
@@ -4133,6 +4148,7 @@ cdef class _FlatArrayMessageReaderAligned(_MessageReader):
|
||||
@cython.internal
|
||||
cdef class _FlatArrayMessageReader(_MessageReader):
|
||||
cdef object _object_to_pin
|
||||
cdef _BufferView _buffer_view
|
||||
|
||||
def __init__(self, buf, traversal_limit_in_words=None, nesting_limit=None):
|
||||
cdef schema_cpp.ReaderOptions opts = make_reader_opts(traversal_limit_in_words, nesting_limit)
|
||||
@@ -4151,10 +4167,12 @@ cdef class _FlatArrayMessageReader(_MessageReader):
|
||||
self._object_to_pin = aligned
|
||||
else:
|
||||
self._object_to_pin = buf
|
||||
self._buffer_view = None
|
||||
elif PyObject_CheckBuffer(buf):
|
||||
view = _BufferView(buf)
|
||||
ptr = view.buf
|
||||
self._object_to_pin = view
|
||||
self._buffer_view = view
|
||||
else:
|
||||
raise TypeError('expected buffer-like object in FlatArrayMessageReader')
|
||||
|
||||
@@ -4162,7 +4180,12 @@ cdef class _FlatArrayMessageReader(_MessageReader):
|
||||
schema_cpp.WordArrayPtr(<schema_cpp.word*>ptr, sz//8),
|
||||
opts)
|
||||
|
||||
def close(self):
|
||||
if self._buffer_view:
|
||||
self._buffer_view.close()
|
||||
|
||||
def __dealloc__(self):
|
||||
self.close()
|
||||
del self.thisptr
|
||||
|
||||
|
||||
|
||||
@@ -3,4 +3,5 @@ import capnp
|
||||
|
||||
def _struct_reducer(schema_id, data):
|
||||
'Hack to deal with pypy not allowing reduce functions to be "built-in" methods (ie. compiled from a .pyx)'
|
||||
return capnp._global_schema_parser.modules_by_id[schema_id].from_bytes(data)
|
||||
with capnp._global_schema_parser.modules_by_id[schema_id].from_bytes(data) as msg:
|
||||
return msg
|
||||
|
||||
20
docs/conf.py
20
docs/conf.py
@@ -51,8 +51,8 @@ source_suffix = ".rst"
|
||||
master_doc = "index"
|
||||
|
||||
# General information about the project.
|
||||
project = u"capnp"
|
||||
copyright = u"2013-2019 (Jason Paryani), 2019-2020 (Jacob Alexander)"
|
||||
project = "capnp"
|
||||
copyright = "2013-2019 (Jason Paryani), 2019-2020 (Jacob Alexander)"
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
@@ -204,7 +204,7 @@ latex_elements = {}
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
("index", "capnp.tex", u"capnp Documentation", u"Author", "manual"),
|
||||
("index", "capnp.tex", "capnp Documentation", "Author", "manual"),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
@@ -232,7 +232,7 @@ latex_documents = [
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [("index", "capnp", u"capnp Documentation", [u"Author"], 1)]
|
||||
man_pages = [("index", "capnp", "capnp Documentation", ["Author"], 1)]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
# man_show_urls = False
|
||||
@@ -247,8 +247,8 @@ texinfo_documents = [
|
||||
(
|
||||
"index",
|
||||
"capnp",
|
||||
u"capnp Documentation",
|
||||
u"Author",
|
||||
"capnp Documentation",
|
||||
"Author",
|
||||
"capnp",
|
||||
"One line description of project.",
|
||||
"Miscellaneous",
|
||||
@@ -268,10 +268,10 @@ texinfo_documents = [
|
||||
# -- Options for Epub output ---------------------------------------------------
|
||||
|
||||
# Bibliographic Dublin Core info.
|
||||
epub_title = u"capnp"
|
||||
epub_author = u"Author"
|
||||
epub_publisher = u"Author"
|
||||
epub_copyright = u"2013, Author"
|
||||
epub_title = "capnp"
|
||||
epub_author = "Author"
|
||||
epub_publisher = "Author"
|
||||
epub_copyright = "2013, Author"
|
||||
|
||||
# The language of the text. It defaults to the language option
|
||||
# or en if the language is not set.
|
||||
|
||||
@@ -13,7 +13,8 @@ import test_capnp # noqa: E402
|
||||
|
||||
def decode(name):
|
||||
class_name = name[0].upper() + name[1:]
|
||||
print(getattr(test_capnp, class_name).from_bytes(sys.stdin.read())._short_str())
|
||||
with getattr(test_capnp, class_name).from_bytes(sys.stdin.read()) as msg:
|
||||
print(msg._short_str())
|
||||
|
||||
|
||||
def encode(name):
|
||||
|
||||
@@ -46,7 +46,7 @@ def test_roundtrip_bytes(all_types):
|
||||
test_regression.init_all_types(msg)
|
||||
message_bytes = msg.to_bytes()
|
||||
|
||||
msg = all_types.TestAllTypes.from_bytes(message_bytes)
|
||||
with all_types.TestAllTypes.from_bytes(message_bytes) as msg:
|
||||
test_regression.check_all_types(msg)
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ def test_roundtrip_bytes_mmap(all_types):
|
||||
f.seek(0)
|
||||
memory = mmap.mmap(f.fileno(), length)
|
||||
|
||||
msg = all_types.TestAllTypes.from_bytes(memory)
|
||||
with all_types.TestAllTypes.from_bytes(memory) as msg:
|
||||
test_regression.check_all_types(msg)
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ def test_roundtrip_bytes_buffer(all_types):
|
||||
b = msg.to_bytes()
|
||||
v = memoryview(b)
|
||||
try:
|
||||
msg = all_types.TestAllTypes.from_bytes(v)
|
||||
with all_types.TestAllTypes.from_bytes(v) as msg:
|
||||
test_regression.check_all_types(msg)
|
||||
finally:
|
||||
v.release()
|
||||
@@ -99,7 +99,8 @@ def test_roundtrip_bytes_buffer(all_types):
|
||||
|
||||
def test_roundtrip_bytes_fail(all_types):
|
||||
with pytest.raises(TypeError):
|
||||
all_types.TestAllTypes.from_bytes(42)
|
||||
with all_types.TestAllTypes.from_bytes(42) as _:
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
@@ -232,12 +233,14 @@ def test_from_bytes_traversal_limit(all_types):
|
||||
bld.init("structList", size)
|
||||
data = bld.to_bytes()
|
||||
|
||||
msg = all_types.TestAllTypes.from_bytes(data)
|
||||
with all_types.TestAllTypes.from_bytes(data) as msg:
|
||||
with pytest.raises(capnp.KjException):
|
||||
for i in range(0, size):
|
||||
msg.structList[i].uInt8Field == 0
|
||||
|
||||
msg = all_types.TestAllTypes.from_bytes(data, traversal_limit_in_words=2 ** 62)
|
||||
with all_types.TestAllTypes.from_bytes(
|
||||
data, traversal_limit_in_words=2**62
|
||||
) as msg:
|
||||
for i in range(0, size):
|
||||
assert msg.structList[i].uInt8Field == 0
|
||||
|
||||
|
||||
@@ -150,9 +150,9 @@ def test_unicode_str(all_types):
|
||||
msg = all_types.TestAllTypes.new_message()
|
||||
|
||||
if sys.version_info[0] == 2:
|
||||
msg.textField = u"f\u00e6oo".encode("utf-8")
|
||||
msg.textField = "f\u00e6oo".encode("utf-8")
|
||||
|
||||
assert msg.textField.decode("utf-8") == u"f\u00e6oo"
|
||||
assert msg.textField.decode("utf-8") == "f\u00e6oo"
|
||||
else:
|
||||
msg.textField = "f\u00e6oo"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user