Add back "set_timezone"
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -0,0 +1,20 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: flatbuffers
|
||||
Version: 25.9.23
|
||||
Summary: The FlatBuffers serialization format for Python
|
||||
Home-page: https://google.github.io/flatbuffers/
|
||||
Author: Derek Bailey
|
||||
Author-email: derekbailey@google.com
|
||||
License: Apache 2.0
|
||||
Project-URL: Documentation, https://google.github.io/flatbuffers/
|
||||
Project-URL: Source, https://github.com/google/flatbuffers
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: Apache Software License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||
License-File: ../LICENSE
|
||||
|
||||
Python runtime library for use with the `Flatbuffers <https://google.github.io/flatbuffers/>`_ serialization format.
|
||||
@@ -0,0 +1,15 @@
|
||||
flatbuffers/__init__.py,sha256=vJZrqZOOTKdBNMa_iTKUA6WJG_c_NzKGpFXOe1Igtiw,751
|
||||
flatbuffers/_version.py,sha256=GVL6M_yJfoAklDfbfTYFV72LDbIU-YgRXL4d1yX3EVw,695
|
||||
flatbuffers/builder.py,sha256=uusDhSDKpnLLz6KR4vflC7T74VNwQew9QRkRuxGZTDg,25048
|
||||
flatbuffers/compat.py,sha256=ihBSpWDCSL-vgLSyZtcu8LX3ZI3wz9LhtqItY2GQZgg,2373
|
||||
flatbuffers/encode.py,sha256=2Or3mgWRAkJiWg-GgYasDU4zIHpQU3W06fmIhwbz5uM,1550
|
||||
flatbuffers/flexbuffers.py,sha256=yF8Wr4Lo8WJb-pj9NNaIYxLwzlHHyTroM0iO8fyDwbU,44454
|
||||
flatbuffers/number_types.py,sha256=ijO0QcJiuxlQegoBOed0v9m0DdzTZHWxpTBZUqzsWHA,3762
|
||||
flatbuffers/packer.py,sha256=LNWym8YgFRqHjcPeGpYY3inCGWH6XnbkQKtAPtFEVas,1164
|
||||
flatbuffers/table.py,sha256=ciYTmq_CzAuYpb3KAVnl75M84ieChfbyKne-dFHzwwU,4818
|
||||
flatbuffers/util.py,sha256=mRVQ1VoHp0MJMNtRTUGVzALwN4T_C-U14tMbj99py2A,1608
|
||||
flatbuffers-25.9.23.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
||||
flatbuffers-25.9.23.dist-info/METADATA,sha256=tTKSAMim3fxiII0atPOplikAqxp8vZwSsKE-vUlqFcE,875
|
||||
flatbuffers-25.9.23.dist-info/WHEEL,sha256=Kh9pAotZVRFj97E15yTA4iADqXdQfIVTHcNaZTjxeGM,110
|
||||
flatbuffers-25.9.23.dist-info/top_level.txt,sha256=UXVWLA8ys6HeqTz6rfKesocUq6ln-ZL8mhZC_cq5BEc,12
|
||||
flatbuffers-25.9.23.dist-info/RECORD,,
|
||||
+3
-1
@@ -1,4 +1,6 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: poetry-core 2.2.1
|
||||
Generator: bdist_wheel (0.45.1)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py2-none-any
|
||||
Tag: py3-none-any
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
flatbuffers
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
# Copyright 2014 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from . import util
|
||||
from ._version import __version__
|
||||
from .builder import Builder
|
||||
from .compat import range_func as compat_range
|
||||
from .table import Table
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
# Copyright 2019 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Placeholder, to be updated during the release process
|
||||
# by the setup.py
|
||||
__version__ = "25.9.23"
|
||||
+870
@@ -0,0 +1,870 @@
|
||||
# Copyright 2014 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import warnings
|
||||
|
||||
from . import compat
|
||||
from . import encode
|
||||
from . import number_types as N
|
||||
from . import packer
|
||||
from .compat import memoryview_type
|
||||
from .compat import NumpyRequiredForThisFeature, import_numpy
|
||||
from .compat import range_func
|
||||
from .number_types import (SOffsetTFlags, UOffsetTFlags, VOffsetTFlags)
|
||||
|
||||
np = import_numpy()
|
||||
## @file
|
||||
## @addtogroup flatbuffers_python_api
|
||||
## @{
|
||||
|
||||
|
||||
## @cond FLATBUFFERS_INTERNAL
|
||||
class OffsetArithmeticError(RuntimeError):
|
||||
"""Error caused by an Offset arithmetic error.
|
||||
|
||||
Probably caused by bad writing of fields. This is considered an unreachable
|
||||
situation in normal circumstances.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class IsNotNestedError(RuntimeError):
|
||||
"""Error caused by using a Builder to write Object data when not inside
|
||||
|
||||
an Object.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class IsNestedError(RuntimeError):
|
||||
"""Error caused by using a Builder to begin an Object when an Object is
|
||||
|
||||
already being built.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class StructIsNotInlineError(RuntimeError):
|
||||
"""Error caused by using a Builder to write a Struct at a location that
|
||||
|
||||
is not the current Offset.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class BuilderSizeError(RuntimeError):
|
||||
"""Error caused by causing a Builder to exceed the hardcoded limit of 2
|
||||
|
||||
gigabytes.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class BuilderNotFinishedError(RuntimeError):
|
||||
"""Error caused by not calling `Finish` before calling `Output`."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class EndVectorLengthMismatched(RuntimeError):
|
||||
"""The number of elements passed to EndVector does not match the number
|
||||
|
||||
specified in StartVector.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
# VtableMetadataFields is the count of metadata fields in each vtable.
|
||||
VtableMetadataFields = 2
|
||||
## @endcond
|
||||
|
||||
|
||||
class Builder(object):
|
||||
"""A Builder is used to construct one or more FlatBuffers.
|
||||
|
||||
Typically, Builder objects will be used from code generated by the `flatc`
|
||||
compiler.
|
||||
|
||||
A Builder constructs byte buffers in a last-first manner for simplicity and
|
||||
performance during reading.
|
||||
|
||||
Internally, a Builder is a state machine for creating FlatBuffer objects.
|
||||
|
||||
It holds the following internal state:
|
||||
- Bytes: an array of bytes.
|
||||
- current_vtable: a list of integers.
|
||||
- vtables: a hash of vtable entries.
|
||||
|
||||
Attributes:
|
||||
Bytes: The internal `bytearray` for the Builder.
|
||||
finished: A boolean determining if the Builder has been finalized.
|
||||
"""
|
||||
|
||||
## @cond FLATBUFFERS_INTENRAL
|
||||
__slots__ = (
|
||||
"Bytes",
|
||||
"current_vtable",
|
||||
"head",
|
||||
"minalign",
|
||||
"objectEnd",
|
||||
"vtables",
|
||||
"nested",
|
||||
"forceDefaults",
|
||||
"finished",
|
||||
"vectorNumElems",
|
||||
"sharedStrings",
|
||||
)
|
||||
|
||||
"""Maximum buffer size constant, in bytes.
|
||||
|
||||
Builder will never allow it's buffer grow over this size.
|
||||
Currently equals 2Gb.
|
||||
"""
|
||||
MAX_BUFFER_SIZE = 2**31
|
||||
## @endcond
|
||||
|
||||
def __init__(self, initialSize=1024):
|
||||
"""Initializes a Builder of size `initial_size`.
|
||||
|
||||
The internal buffer is grown as needed.
|
||||
"""
|
||||
|
||||
if not (0 <= initialSize <= Builder.MAX_BUFFER_SIZE):
|
||||
msg = "flatbuffers: Cannot create Builder larger than 2 gigabytes."
|
||||
raise BuilderSizeError(msg)
|
||||
|
||||
self.Bytes = bytearray(initialSize)
|
||||
## @cond FLATBUFFERS_INTERNAL
|
||||
self.current_vtable = None
|
||||
self.head = UOffsetTFlags.py_type(initialSize)
|
||||
self.minalign = 1
|
||||
self.objectEnd = None
|
||||
self.vtables = {}
|
||||
self.nested = False
|
||||
self.forceDefaults = False
|
||||
self.sharedStrings = {}
|
||||
## @endcond
|
||||
self.finished = False
|
||||
|
||||
def Clear(self) -> None:
|
||||
## @cond FLATBUFFERS_INTERNAL
|
||||
self.current_vtable = None
|
||||
self.head = UOffsetTFlags.py_type(len(self.Bytes))
|
||||
self.minalign = 1
|
||||
self.objectEnd = None
|
||||
self.vtables = {}
|
||||
self.nested = False
|
||||
self.forceDefaults = False
|
||||
self.sharedStrings = {}
|
||||
self.vectorNumElems = None
|
||||
## @endcond
|
||||
self.finished = False
|
||||
|
||||
def Output(self):
|
||||
"""Return the portion of the buffer that has been used for writing data.
|
||||
|
||||
This is the typical way to access the FlatBuffer data inside the
|
||||
builder. If you try to access `Builder.Bytes` directly, you would need
|
||||
to manually index it with `Head()`, since the buffer is constructed
|
||||
backwards.
|
||||
|
||||
It raises BuilderNotFinishedError if the buffer has not been finished
|
||||
with `Finish`.
|
||||
"""
|
||||
|
||||
if not self.finished:
|
||||
raise BuilderNotFinishedError()
|
||||
|
||||
return self.Bytes[self.Head() :]
|
||||
|
||||
## @cond FLATBUFFERS_INTERNAL
|
||||
def StartObject(self, numfields):
|
||||
"""StartObject initializes bookkeeping for writing a new object."""
|
||||
|
||||
self.assertNotNested()
|
||||
|
||||
# use 32-bit offsets so that arithmetic doesn't overflow.
|
||||
self.current_vtable = [0 for _ in range_func(numfields)]
|
||||
self.objectEnd = self.Offset()
|
||||
self.nested = True
|
||||
|
||||
def WriteVtable(self):
|
||||
"""WriteVtable serializes the vtable for the current object, if needed.
|
||||
|
||||
Before writing out the vtable, this checks pre-existing vtables for
|
||||
equality to this one. If an equal vtable is found, point the object to
|
||||
the existing vtable and return.
|
||||
|
||||
Because vtable values are sensitive to alignment of object data, not
|
||||
all logically-equal vtables will be deduplicated.
|
||||
|
||||
A vtable has the following format:
|
||||
<VOffsetT: size of the vtable in bytes, including this value>
|
||||
<VOffsetT: size of the object in bytes, including the vtable offset>
|
||||
<VOffsetT: offset for a field> * N, where N is the number of fields
|
||||
in the schema for this type. Includes deprecated fields.
|
||||
Thus, a vtable is made of 2 + N elements, each VOffsetT bytes wide.
|
||||
|
||||
An object has the following format:
|
||||
<SOffsetT: offset to this object's vtable (may be negative)>
|
||||
<byte: data>+
|
||||
"""
|
||||
|
||||
# Prepend a zero scalar to the object. Later in this function we'll
|
||||
# write an offset here that points to the object's vtable:
|
||||
self.PrependSOffsetTRelative(0)
|
||||
|
||||
objectOffset = self.Offset()
|
||||
|
||||
vtKey = []
|
||||
trim = True
|
||||
for elem in reversed(self.current_vtable):
|
||||
if elem == 0:
|
||||
if trim:
|
||||
continue
|
||||
else:
|
||||
elem = objectOffset - elem
|
||||
trim = False
|
||||
|
||||
vtKey.append(elem)
|
||||
|
||||
vtKey = tuple(vtKey)
|
||||
vt2Offset = self.vtables.get(vtKey)
|
||||
if vt2Offset is None:
|
||||
# Did not find a vtable, so write this one to the buffer.
|
||||
|
||||
# Write out the current vtable in reverse , because
|
||||
# serialization occurs in last-first order:
|
||||
i = len(self.current_vtable) - 1
|
||||
trailing = 0
|
||||
trim = True
|
||||
while i >= 0:
|
||||
off = 0
|
||||
elem = self.current_vtable[i]
|
||||
i -= 1
|
||||
|
||||
if elem == 0:
|
||||
if trim:
|
||||
trailing += 1
|
||||
continue
|
||||
else:
|
||||
# Forward reference to field;
|
||||
# use 32bit number to ensure no overflow:
|
||||
off = objectOffset - elem
|
||||
trim = False
|
||||
|
||||
self.PrependVOffsetT(off)
|
||||
|
||||
# The two metadata fields are written last.
|
||||
|
||||
# First, store the object bytesize:
|
||||
objectSize = UOffsetTFlags.py_type(objectOffset - self.objectEnd)
|
||||
self.PrependVOffsetT(VOffsetTFlags.py_type(objectSize))
|
||||
|
||||
# Second, store the vtable bytesize:
|
||||
vBytes = len(self.current_vtable) - trailing + VtableMetadataFields
|
||||
vBytes *= N.VOffsetTFlags.bytewidth
|
||||
self.PrependVOffsetT(VOffsetTFlags.py_type(vBytes))
|
||||
|
||||
# Next, write the offset to the new vtable in the
|
||||
# already-allocated SOffsetT at the beginning of this object:
|
||||
objectStart = SOffsetTFlags.py_type(len(self.Bytes) - objectOffset)
|
||||
encode.Write(
|
||||
packer.soffset,
|
||||
self.Bytes,
|
||||
objectStart,
|
||||
SOffsetTFlags.py_type(self.Offset() - objectOffset),
|
||||
)
|
||||
|
||||
# Finally, store this vtable in memory for future
|
||||
# deduplication:
|
||||
self.vtables[vtKey] = self.Offset()
|
||||
else:
|
||||
# Found a duplicate vtable.
|
||||
objectStart = SOffsetTFlags.py_type(len(self.Bytes) - objectOffset)
|
||||
self.head = UOffsetTFlags.py_type(objectStart)
|
||||
|
||||
# Write the offset to the found vtable in the
|
||||
# already-allocated SOffsetT at the beginning of this object:
|
||||
encode.Write(
|
||||
packer.soffset,
|
||||
self.Bytes,
|
||||
self.Head(),
|
||||
SOffsetTFlags.py_type(vt2Offset - objectOffset),
|
||||
)
|
||||
|
||||
self.current_vtable = None
|
||||
return objectOffset
|
||||
|
||||
def EndObject(self):
|
||||
"""EndObject writes data necessary to finish object construction."""
|
||||
self.assertNested()
|
||||
self.nested = False
|
||||
return self.WriteVtable()
|
||||
|
||||
def growByteBuffer(self):
|
||||
"""Doubles the size of the byteslice, and copies the old data towards
|
||||
|
||||
the end of the new buffer (since we build the buffer backwards).
|
||||
"""
|
||||
if len(self.Bytes) == Builder.MAX_BUFFER_SIZE:
|
||||
msg = "flatbuffers: cannot grow buffer beyond 2 gigabytes"
|
||||
raise BuilderSizeError(msg)
|
||||
|
||||
newSize = min(len(self.Bytes) * 2, Builder.MAX_BUFFER_SIZE)
|
||||
if newSize == 0:
|
||||
newSize = 1
|
||||
bytes2 = bytearray(newSize)
|
||||
bytes2[newSize - len(self.Bytes) :] = self.Bytes
|
||||
self.Bytes = bytes2
|
||||
|
||||
## @endcond
|
||||
|
||||
def Head(self):
|
||||
"""Get the start of useful data in the underlying byte buffer.
|
||||
|
||||
Note: unlike other functions, this value is interpreted as from the
|
||||
left.
|
||||
"""
|
||||
## @cond FLATBUFFERS_INTERNAL
|
||||
return self.head
|
||||
## @endcond
|
||||
|
||||
## @cond FLATBUFFERS_INTERNAL
|
||||
def Offset(self):
|
||||
"""Offset relative to the end of the buffer."""
|
||||
return UOffsetTFlags.py_type(len(self.Bytes) - self.Head())
|
||||
|
||||
def Pad(self, n):
|
||||
"""Pad places zeros at the current offset."""
|
||||
for i in range_func(n):
|
||||
self.Place(0, N.Uint8Flags)
|
||||
|
||||
def Prep(self, size, additionalBytes):
|
||||
"""Prep prepares to write an element of `size` after `additional_bytes`
|
||||
|
||||
have been written, e.g. if you write a string, you need to align
|
||||
such the int length field is aligned to SizeInt32, and the string
|
||||
data follows it directly.
|
||||
If all you need to do is align, `additionalBytes` will be 0.
|
||||
"""
|
||||
|
||||
# Track the biggest thing we've ever aligned to.
|
||||
if size > self.minalign:
|
||||
self.minalign = size
|
||||
|
||||
# Find the amount of alignment needed such that `size` is properly
|
||||
# aligned after `additionalBytes`:
|
||||
alignSize = (~(len(self.Bytes) - self.Head() + additionalBytes)) + 1
|
||||
alignSize &= size - 1
|
||||
|
||||
# Reallocate the buffer if needed:
|
||||
while self.Head() < alignSize + size + additionalBytes:
|
||||
oldBufSize = len(self.Bytes)
|
||||
self.growByteBuffer()
|
||||
updated_head = self.head + len(self.Bytes) - oldBufSize
|
||||
self.head = UOffsetTFlags.py_type(updated_head)
|
||||
self.Pad(alignSize)
|
||||
|
||||
def PrependSOffsetTRelative(self, off):
|
||||
"""PrependSOffsetTRelative prepends an SOffsetT, relative to where it
|
||||
|
||||
will be written.
|
||||
"""
|
||||
|
||||
# Ensure alignment is already done:
|
||||
self.Prep(N.SOffsetTFlags.bytewidth, 0)
|
||||
if not (off <= self.Offset()):
|
||||
msg = "flatbuffers: Offset arithmetic error."
|
||||
raise OffsetArithmeticError(msg)
|
||||
off2 = self.Offset() - off + N.SOffsetTFlags.bytewidth
|
||||
self.PlaceSOffsetT(off2)
|
||||
|
||||
## @endcond
|
||||
|
||||
def PrependUOffsetTRelative(self, off):
|
||||
"""Prepends an unsigned offset into vector data, relative to where it
|
||||
|
||||
will be written.
|
||||
"""
|
||||
|
||||
# Ensure alignment is already done:
|
||||
self.Prep(N.UOffsetTFlags.bytewidth, 0)
|
||||
if not (off <= self.Offset()):
|
||||
msg = "flatbuffers: Offset arithmetic error."
|
||||
raise OffsetArithmeticError(msg)
|
||||
off2 = self.Offset() - off + N.UOffsetTFlags.bytewidth
|
||||
self.PlaceUOffsetT(off2)
|
||||
|
||||
## @cond FLATBUFFERS_INTERNAL
|
||||
def StartVector(self, elemSize, numElems, alignment):
|
||||
"""StartVector initializes bookkeeping for writing a new vector.
|
||||
|
||||
A vector has the following format:
|
||||
- <UOffsetT: number of elements in this vector>
|
||||
- <T: data>+, where T is the type of elements of this vector.
|
||||
"""
|
||||
|
||||
self.assertNotNested()
|
||||
self.nested = True
|
||||
self.vectorNumElems = numElems
|
||||
self.Prep(N.Uint32Flags.bytewidth, elemSize * numElems)
|
||||
self.Prep(alignment, elemSize * numElems) # In case alignment > int.
|
||||
return self.Offset()
|
||||
|
||||
## @endcond
|
||||
|
||||
def EndVector(self, numElems=None):
|
||||
"""EndVector writes data necessary to finish vector construction."""
|
||||
|
||||
self.assertNested()
|
||||
## @cond FLATBUFFERS_INTERNAL
|
||||
self.nested = False
|
||||
## @endcond
|
||||
|
||||
if numElems:
|
||||
warnings.warn("numElems is deprecated.", DeprecationWarning, stacklevel=2)
|
||||
if numElems != self.vectorNumElems:
|
||||
raise EndVectorLengthMismatched()
|
||||
|
||||
# we already made space for this, so write without PrependUint32
|
||||
self.PlaceUOffsetT(self.vectorNumElems)
|
||||
self.vectorNumElems = None
|
||||
return self.Offset()
|
||||
|
||||
def CreateSharedString(self, s, encoding="utf-8", errors="strict"):
|
||||
"""CreateSharedString checks if the string is already written to the buffer
|
||||
|
||||
before calling CreateString.
|
||||
"""
|
||||
|
||||
if s in self.sharedStrings:
|
||||
return self.sharedStrings[s]
|
||||
|
||||
off = self.CreateString(s, encoding, errors)
|
||||
self.sharedStrings[s] = off
|
||||
|
||||
return off
|
||||
|
||||
def CreateString(self, s, encoding="utf-8", errors="strict"):
|
||||
"""CreateString writes a null-terminated byte string as a vector."""
|
||||
|
||||
self.assertNotNested()
|
||||
## @cond FLATBUFFERS_INTERNAL
|
||||
self.nested = True
|
||||
## @endcond
|
||||
|
||||
if isinstance(s, compat.string_types):
|
||||
x = s.encode(encoding, errors)
|
||||
elif isinstance(s, compat.binary_types):
|
||||
x = s
|
||||
else:
|
||||
raise TypeError("non-string passed to CreateString")
|
||||
|
||||
self.Prep(N.UOffsetTFlags.bytewidth, (len(x) + 1) * N.Uint8Flags.bytewidth)
|
||||
self.Place(0, N.Uint8Flags)
|
||||
|
||||
l = UOffsetTFlags.py_type(len(s))
|
||||
## @cond FLATBUFFERS_INTERNAL
|
||||
self.head = UOffsetTFlags.py_type(self.Head() - l)
|
||||
## @endcond
|
||||
self.Bytes[self.Head() : self.Head() + l] = x
|
||||
|
||||
self.vectorNumElems = len(x)
|
||||
return self.EndVector()
|
||||
|
||||
def CreateByteVector(self, x):
|
||||
"""CreateString writes a byte vector."""
|
||||
|
||||
self.assertNotNested()
|
||||
## @cond FLATBUFFERS_INTERNAL
|
||||
self.nested = True
|
||||
## @endcond
|
||||
|
||||
if not isinstance(x, compat.binary_types):
|
||||
raise TypeError("non-byte vector passed to CreateByteVector")
|
||||
|
||||
self.Prep(N.UOffsetTFlags.bytewidth, len(x) * N.Uint8Flags.bytewidth)
|
||||
|
||||
l = UOffsetTFlags.py_type(len(x))
|
||||
## @cond FLATBUFFERS_INTERNAL
|
||||
self.head = UOffsetTFlags.py_type(self.Head() - l)
|
||||
## @endcond
|
||||
self.Bytes[self.Head() : self.Head() + l] = x
|
||||
|
||||
self.vectorNumElems = len(x)
|
||||
return self.EndVector()
|
||||
|
||||
def CreateNumpyVector(self, x):
|
||||
"""CreateNumpyVector writes a numpy array into the buffer."""
|
||||
|
||||
if np is None:
|
||||
# Numpy is required for this feature
|
||||
raise NumpyRequiredForThisFeature("Numpy was not found.")
|
||||
|
||||
if not isinstance(x, np.ndarray):
|
||||
raise TypeError("non-numpy-ndarray passed to CreateNumpyVector")
|
||||
|
||||
if x.dtype.kind not in ["b", "i", "u", "f"]:
|
||||
raise TypeError("numpy-ndarray holds elements of unsupported datatype")
|
||||
|
||||
if x.ndim > 1:
|
||||
raise TypeError("multidimensional-ndarray passed to CreateNumpyVector")
|
||||
|
||||
self.StartVector(x.itemsize, x.size, x.dtype.alignment)
|
||||
|
||||
# Ensure little endian byte ordering
|
||||
if x.dtype.str[0] == "<":
|
||||
x_lend = x
|
||||
else:
|
||||
x_lend = x.byteswap(inplace=False)
|
||||
|
||||
# Calculate total length
|
||||
l = UOffsetTFlags.py_type(x_lend.itemsize * x_lend.size)
|
||||
## @cond FLATBUFFERS_INTERNAL
|
||||
self.head = UOffsetTFlags.py_type(self.Head() - l)
|
||||
## @endcond
|
||||
|
||||
# tobytes ensures c_contiguous ordering
|
||||
self.Bytes[self.Head() : self.Head() + l] = x_lend.tobytes(order="C")
|
||||
|
||||
self.vectorNumElems = x.size
|
||||
return self.EndVector()
|
||||
|
||||
## @cond FLATBUFFERS_INTERNAL
|
||||
def assertNested(self):
|
||||
"""Check that we are in the process of building an object."""
|
||||
|
||||
if not self.nested:
|
||||
raise IsNotNestedError()
|
||||
|
||||
def assertNotNested(self):
|
||||
"""Check that no other objects are being built while making this object.
|
||||
|
||||
If not, raise an exception.
|
||||
"""
|
||||
|
||||
if self.nested:
|
||||
raise IsNestedError()
|
||||
|
||||
def assertStructIsInline(self, obj):
|
||||
"""Structs are always stored inline, so need to be created right
|
||||
|
||||
where they are used. You'll get this error if you created it
|
||||
elsewhere.
|
||||
"""
|
||||
|
||||
N.enforce_number(obj, N.UOffsetTFlags)
|
||||
if obj != self.Offset():
|
||||
msg = (
|
||||
"flatbuffers: Tried to write a Struct at an Offset that "
|
||||
"is different from the current Offset of the Builder."
|
||||
)
|
||||
raise StructIsNotInlineError(msg)
|
||||
|
||||
def Slot(self, slotnum):
|
||||
"""Slot sets the vtable key `voffset` to the current location in the
|
||||
|
||||
buffer.
|
||||
"""
|
||||
self.assertNested()
|
||||
self.current_vtable[slotnum] = self.Offset()
|
||||
|
||||
## @endcond
|
||||
|
||||
def __Finish(self, rootTable, sizePrefix, file_identifier=None):
|
||||
"""Finish finalizes a buffer, pointing to the given `rootTable`."""
|
||||
N.enforce_number(rootTable, N.UOffsetTFlags)
|
||||
|
||||
prepSize = N.UOffsetTFlags.bytewidth
|
||||
if file_identifier is not None:
|
||||
prepSize += N.Int32Flags.bytewidth
|
||||
if sizePrefix:
|
||||
prepSize += N.Int32Flags.bytewidth
|
||||
self.Prep(self.minalign, prepSize)
|
||||
|
||||
if file_identifier is not None:
|
||||
self.Prep(N.UOffsetTFlags.bytewidth, encode.FILE_IDENTIFIER_LENGTH)
|
||||
|
||||
# Convert bytes object file_identifier to an array of 4 8-bit integers,
|
||||
# and use big-endian to enforce size compliance.
|
||||
# https://docs.python.org/2/library/struct.html#format-characters
|
||||
file_identifier = N.struct.unpack(">BBBB", file_identifier)
|
||||
for i in range(encode.FILE_IDENTIFIER_LENGTH - 1, -1, -1):
|
||||
# Place the bytes of the file_identifer in reverse order:
|
||||
self.Place(file_identifier[i], N.Uint8Flags)
|
||||
|
||||
self.PrependUOffsetTRelative(rootTable)
|
||||
if sizePrefix:
|
||||
size = len(self.Bytes) - self.Head()
|
||||
N.enforce_number(size, N.Int32Flags)
|
||||
self.PrependInt32(size)
|
||||
self.finished = True
|
||||
return self.Head()
|
||||
|
||||
def Finish(self, rootTable, file_identifier=None):
|
||||
"""Finish finalizes a buffer, pointing to the given `rootTable`."""
|
||||
return self.__Finish(rootTable, False, file_identifier=file_identifier)
|
||||
|
||||
def FinishSizePrefixed(self, rootTable, file_identifier=None):
|
||||
"""Finish finalizes a buffer, pointing to the given `rootTable`,
|
||||
|
||||
with the size prefixed.
|
||||
"""
|
||||
return self.__Finish(rootTable, True, file_identifier=file_identifier)
|
||||
|
||||
## @cond FLATBUFFERS_INTERNAL
|
||||
def Prepend(self, flags, off):
|
||||
self.Prep(flags.bytewidth, 0)
|
||||
self.Place(off, flags)
|
||||
|
||||
def PrependSlot(self, flags, o, x, d):
|
||||
if x is not None:
|
||||
N.enforce_number(x, flags)
|
||||
if d is not None:
|
||||
N.enforce_number(d, flags)
|
||||
if x != d or (self.forceDefaults and d is not None):
|
||||
self.Prepend(flags, x)
|
||||
self.Slot(o)
|
||||
|
||||
def PrependBoolSlot(self, *args):
|
||||
self.PrependSlot(N.BoolFlags, *args)
|
||||
|
||||
def PrependByteSlot(self, *args):
|
||||
self.PrependSlot(N.Uint8Flags, *args)
|
||||
|
||||
def PrependUint8Slot(self, *args):
|
||||
self.PrependSlot(N.Uint8Flags, *args)
|
||||
|
||||
def PrependUint16Slot(self, *args):
|
||||
self.PrependSlot(N.Uint16Flags, *args)
|
||||
|
||||
def PrependUint32Slot(self, *args):
|
||||
self.PrependSlot(N.Uint32Flags, *args)
|
||||
|
||||
def PrependUint64Slot(self, *args):
|
||||
self.PrependSlot(N.Uint64Flags, *args)
|
||||
|
||||
def PrependInt8Slot(self, *args):
|
||||
self.PrependSlot(N.Int8Flags, *args)
|
||||
|
||||
def PrependInt16Slot(self, *args):
|
||||
self.PrependSlot(N.Int16Flags, *args)
|
||||
|
||||
def PrependInt32Slot(self, *args):
|
||||
self.PrependSlot(N.Int32Flags, *args)
|
||||
|
||||
def PrependInt64Slot(self, *args):
|
||||
self.PrependSlot(N.Int64Flags, *args)
|
||||
|
||||
def PrependFloat32Slot(self, *args):
|
||||
self.PrependSlot(N.Float32Flags, *args)
|
||||
|
||||
def PrependFloat64Slot(self, *args):
|
||||
self.PrependSlot(N.Float64Flags, *args)
|
||||
|
||||
def PrependUOffsetTRelativeSlot(self, o, x, d):
|
||||
"""PrependUOffsetTRelativeSlot prepends an UOffsetT onto the object at
|
||||
|
||||
vtable slot `o`. If value `x` equals default `d`, then the slot will
|
||||
be set to zero and no other data will be written.
|
||||
"""
|
||||
|
||||
if x != d or self.forceDefaults:
|
||||
self.PrependUOffsetTRelative(x)
|
||||
self.Slot(o)
|
||||
|
||||
def PrependStructSlot(self, v, x, d):
|
||||
"""PrependStructSlot prepends a struct onto the object at vtable slot `o`.
|
||||
|
||||
Structs are stored inline, so nothing additional is being added. In
|
||||
generated code, `d` is always 0.
|
||||
"""
|
||||
|
||||
N.enforce_number(d, N.UOffsetTFlags)
|
||||
if x != d:
|
||||
self.assertStructIsInline(x)
|
||||
self.Slot(v)
|
||||
|
||||
## @endcond
|
||||
|
||||
def PrependBool(self, x):
|
||||
"""Prepend a `bool` to the Builder buffer.
|
||||
|
||||
Note: aligns and checks for space.
|
||||
"""
|
||||
self.Prepend(N.BoolFlags, x)
|
||||
|
||||
def PrependByte(self, x):
|
||||
"""Prepend a `byte` to the Builder buffer.
|
||||
|
||||
Note: aligns and checks for space.
|
||||
"""
|
||||
self.Prepend(N.Uint8Flags, x)
|
||||
|
||||
def PrependUint8(self, x):
|
||||
"""Prepend an `uint8` to the Builder buffer.
|
||||
|
||||
Note: aligns and checks for space.
|
||||
"""
|
||||
self.Prepend(N.Uint8Flags, x)
|
||||
|
||||
def PrependUint16(self, x):
|
||||
"""Prepend an `uint16` to the Builder buffer.
|
||||
|
||||
Note: aligns and checks for space.
|
||||
"""
|
||||
self.Prepend(N.Uint16Flags, x)
|
||||
|
||||
def PrependUint32(self, x):
|
||||
"""Prepend an `uint32` to the Builder buffer.
|
||||
|
||||
Note: aligns and checks for space.
|
||||
"""
|
||||
self.Prepend(N.Uint32Flags, x)
|
||||
|
||||
def PrependUint64(self, x):
|
||||
"""Prepend an `uint64` to the Builder buffer.
|
||||
|
||||
Note: aligns and checks for space.
|
||||
"""
|
||||
self.Prepend(N.Uint64Flags, x)
|
||||
|
||||
def PrependInt8(self, x):
|
||||
"""Prepend an `int8` to the Builder buffer.
|
||||
|
||||
Note: aligns and checks for space.
|
||||
"""
|
||||
self.Prepend(N.Int8Flags, x)
|
||||
|
||||
def PrependInt16(self, x):
|
||||
"""Prepend an `int16` to the Builder buffer.
|
||||
|
||||
Note: aligns and checks for space.
|
||||
"""
|
||||
self.Prepend(N.Int16Flags, x)
|
||||
|
||||
def PrependInt32(self, x):
|
||||
"""Prepend an `int32` to the Builder buffer.
|
||||
|
||||
Note: aligns and checks for space.
|
||||
"""
|
||||
self.Prepend(N.Int32Flags, x)
|
||||
|
||||
def PrependInt64(self, x):
|
||||
"""Prepend an `int64` to the Builder buffer.
|
||||
|
||||
Note: aligns and checks for space.
|
||||
"""
|
||||
self.Prepend(N.Int64Flags, x)
|
||||
|
||||
def PrependFloat32(self, x):
|
||||
"""Prepend a `float32` to the Builder buffer.
|
||||
|
||||
Note: aligns and checks for space.
|
||||
"""
|
||||
self.Prepend(N.Float32Flags, x)
|
||||
|
||||
def PrependFloat64(self, x):
|
||||
"""Prepend a `float64` to the Builder buffer.
|
||||
|
||||
Note: aligns and checks for space.
|
||||
"""
|
||||
self.Prepend(N.Float64Flags, x)
|
||||
|
||||
def ForceDefaults(self, forceDefaults):
|
||||
"""In order to save space, fields that are set to their default value
|
||||
|
||||
don't get serialized into the buffer. Forcing defaults provides a
|
||||
way to manually disable this optimization. When set to `True`, will
|
||||
always serialize default values.
|
||||
"""
|
||||
self.forceDefaults = forceDefaults
|
||||
|
||||
##############################################################
|
||||
|
||||
## @cond FLATBUFFERS_INTERNAL
|
||||
def PrependVOffsetT(self, x):
|
||||
self.Prepend(N.VOffsetTFlags, x)
|
||||
|
||||
def Place(self, x, flags):
|
||||
"""Place prepends a value specified by `flags` to the Builder,
|
||||
|
||||
without checking for available space.
|
||||
"""
|
||||
|
||||
N.enforce_number(x, flags)
|
||||
self.head = self.head - flags.bytewidth
|
||||
encode.Write(flags.packer_type, self.Bytes, self.Head(), x)
|
||||
|
||||
def PlaceVOffsetT(self, x):
|
||||
"""PlaceVOffsetT prepends a VOffsetT to the Builder, without checking
|
||||
|
||||
for space.
|
||||
"""
|
||||
N.enforce_number(x, N.VOffsetTFlags)
|
||||
self.head = self.head - N.VOffsetTFlags.bytewidth
|
||||
encode.Write(packer.voffset, self.Bytes, self.Head(), x)
|
||||
|
||||
def PlaceSOffsetT(self, x):
|
||||
"""PlaceSOffsetT prepends a SOffsetT to the Builder, without checking
|
||||
|
||||
for space.
|
||||
"""
|
||||
N.enforce_number(x, N.SOffsetTFlags)
|
||||
self.head = self.head - N.SOffsetTFlags.bytewidth
|
||||
encode.Write(packer.soffset, self.Bytes, self.Head(), x)
|
||||
|
||||
def PlaceUOffsetT(self, x):
|
||||
"""PlaceUOffsetT prepends a UOffsetT to the Builder, without checking
|
||||
|
||||
for space.
|
||||
"""
|
||||
N.enforce_number(x, N.UOffsetTFlags)
|
||||
self.head = self.head - N.UOffsetTFlags.bytewidth
|
||||
encode.Write(packer.uoffset, self.Bytes, self.Head(), x)
|
||||
|
||||
## @endcond
|
||||
|
||||
|
||||
## @cond FLATBUFFERS_INTERNAL
|
||||
def vtableEqual(a, objectStart, b):
|
||||
"""vtableEqual compares an unwritten vtable to a written vtable."""
|
||||
|
||||
N.enforce_number(objectStart, N.UOffsetTFlags)
|
||||
|
||||
if len(a) * N.VOffsetTFlags.bytewidth != len(b):
|
||||
return False
|
||||
|
||||
for i, elem in enumerate(a):
|
||||
x = encode.Get(packer.voffset, b, i * N.VOffsetTFlags.bytewidth)
|
||||
|
||||
# Skip vtable entries that indicate a default value.
|
||||
if x == 0 and elem == 0:
|
||||
pass
|
||||
else:
|
||||
y = objectStart - elem
|
||||
if x != y:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
## @endcond
|
||||
## @}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
# Copyright 2016 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""A tiny version of `six` to help with backwards compability.
|
||||
|
||||
Also includes compatibility helpers for numpy.
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
PY2 = sys.version_info[0] == 2
|
||||
PY26 = sys.version_info[0:2] == (2, 6)
|
||||
PY27 = sys.version_info[0:2] == (2, 7)
|
||||
PY275 = sys.version_info[0:3] >= (2, 7, 5)
|
||||
PY3 = sys.version_info[0] == 3
|
||||
PY34 = sys.version_info[0:2] >= (3, 4)
|
||||
|
||||
if PY3:
|
||||
import importlib.machinery
|
||||
|
||||
string_types = (str,)
|
||||
binary_types = (bytes, bytearray)
|
||||
range_func = range
|
||||
memoryview_type = memoryview
|
||||
struct_bool_decl = "?"
|
||||
else:
|
||||
import imp
|
||||
|
||||
string_types = (unicode,)
|
||||
if PY26 or PY27:
|
||||
binary_types = (str, bytearray)
|
||||
else:
|
||||
binary_types = (str,)
|
||||
range_func = xrange
|
||||
if PY26 or (PY27 and not PY275):
|
||||
memoryview_type = buffer
|
||||
struct_bool_decl = "<b"
|
||||
else:
|
||||
memoryview_type = memoryview
|
||||
struct_bool_decl = "?"
|
||||
|
||||
# Helper functions to facilitate making numpy optional instead of required
|
||||
|
||||
|
||||
def import_numpy():
|
||||
"""Returns the numpy module if it exists on the system,
|
||||
|
||||
otherwise returns None.
|
||||
"""
|
||||
if PY3:
|
||||
numpy_exists = importlib.machinery.PathFinder.find_spec("numpy") is not None
|
||||
else:
|
||||
try:
|
||||
imp.find_module("numpy")
|
||||
numpy_exists = True
|
||||
except ImportError:
|
||||
numpy_exists = False
|
||||
|
||||
if numpy_exists:
|
||||
# We do this outside of try/except block in case numpy exists
|
||||
# but is not installed correctly. We do not want to catch an
|
||||
# incorrect installation which would manifest as an
|
||||
# ImportError.
|
||||
import numpy as np
|
||||
else:
|
||||
np = None
|
||||
|
||||
return np
|
||||
|
||||
|
||||
class NumpyRequiredForThisFeature(RuntimeError):
|
||||
"""Error raised when user tries to use a feature that
|
||||
|
||||
requires numpy without having numpy installed.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
# NOTE: Future Jython support may require code here (look at `six`).
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
# Copyright 2014 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from . import number_types as N
|
||||
from . import packer
|
||||
from .compat import memoryview_type
|
||||
from .compat import NumpyRequiredForThisFeature, import_numpy
|
||||
|
||||
np = import_numpy()
|
||||
|
||||
FILE_IDENTIFIER_LENGTH = 4
|
||||
|
||||
|
||||
def Get(packer_type, buf, head):
|
||||
"""Get decodes a value at buf[head] using `packer_type`."""
|
||||
return packer_type.unpack_from(memoryview_type(buf), head)[0]
|
||||
|
||||
|
||||
def GetVectorAsNumpy(numpy_type, buf, count, offset):
|
||||
"""GetVecAsNumpy decodes values starting at buf[head] as
|
||||
|
||||
`numpy_type`, where `numpy_type` is a numpy dtype.
|
||||
"""
|
||||
if np is not None:
|
||||
# TODO: could set .flags.writeable = False to make users jump through
|
||||
# hoops before modifying...
|
||||
return np.frombuffer(buf, dtype=numpy_type, count=count, offset=offset)
|
||||
else:
|
||||
raise NumpyRequiredForThisFeature('Numpy was not found.')
|
||||
|
||||
|
||||
def Write(packer_type, buf, head, n):
|
||||
"""Write encodes `n` at buf[head] using `packer_type`."""
|
||||
packer_type.pack_into(buf, head, n)
|
||||
+1592
File diff suppressed because it is too large
Load Diff
+182
@@ -0,0 +1,182 @@
|
||||
# Copyright 2014 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import collections
|
||||
import struct
|
||||
|
||||
from . import packer
|
||||
from .compat import NumpyRequiredForThisFeature, import_numpy
|
||||
|
||||
np = import_numpy()
|
||||
|
||||
# For reference, see:
|
||||
# https://docs.python.org/2/library/ctypes.html#ctypes-fundamental-data-types-2
|
||||
|
||||
# These classes could be collections.namedtuple instances, but those are new
|
||||
# in 2.6 and we want to work towards 2.5 compatability.
|
||||
|
||||
|
||||
class BoolFlags(object):
|
||||
bytewidth = 1
|
||||
min_val = False
|
||||
max_val = True
|
||||
py_type = bool
|
||||
name = "bool"
|
||||
packer_type = packer.boolean
|
||||
|
||||
|
||||
class Uint8Flags(object):
|
||||
bytewidth = 1
|
||||
min_val = 0
|
||||
max_val = (2**8) - 1
|
||||
py_type = int
|
||||
name = "uint8"
|
||||
packer_type = packer.uint8
|
||||
|
||||
|
||||
class Uint16Flags(object):
|
||||
bytewidth = 2
|
||||
min_val = 0
|
||||
max_val = (2**16) - 1
|
||||
py_type = int
|
||||
name = "uint16"
|
||||
packer_type = packer.uint16
|
||||
|
||||
|
||||
class Uint32Flags(object):
|
||||
bytewidth = 4
|
||||
min_val = 0
|
||||
max_val = (2**32) - 1
|
||||
py_type = int
|
||||
name = "uint32"
|
||||
packer_type = packer.uint32
|
||||
|
||||
|
||||
class Uint64Flags(object):
|
||||
bytewidth = 8
|
||||
min_val = 0
|
||||
max_val = (2**64) - 1
|
||||
py_type = int
|
||||
name = "uint64"
|
||||
packer_type = packer.uint64
|
||||
|
||||
|
||||
class Int8Flags(object):
|
||||
bytewidth = 1
|
||||
min_val = -(2**7)
|
||||
max_val = (2**7) - 1
|
||||
py_type = int
|
||||
name = "int8"
|
||||
packer_type = packer.int8
|
||||
|
||||
|
||||
class Int16Flags(object):
|
||||
bytewidth = 2
|
||||
min_val = -(2**15)
|
||||
max_val = (2**15) - 1
|
||||
py_type = int
|
||||
name = "int16"
|
||||
packer_type = packer.int16
|
||||
|
||||
|
||||
class Int32Flags(object):
|
||||
bytewidth = 4
|
||||
min_val = -(2**31)
|
||||
max_val = (2**31) - 1
|
||||
py_type = int
|
||||
name = "int32"
|
||||
packer_type = packer.int32
|
||||
|
||||
|
||||
class Int64Flags(object):
|
||||
bytewidth = 8
|
||||
min_val = -(2**63)
|
||||
max_val = (2**63) - 1
|
||||
py_type = int
|
||||
name = "int64"
|
||||
packer_type = packer.int64
|
||||
|
||||
|
||||
class Float32Flags(object):
|
||||
bytewidth = 4
|
||||
min_val = None
|
||||
max_val = None
|
||||
py_type = float
|
||||
name = "float32"
|
||||
packer_type = packer.float32
|
||||
|
||||
|
||||
class Float64Flags(object):
|
||||
bytewidth = 8
|
||||
min_val = None
|
||||
max_val = None
|
||||
py_type = float
|
||||
name = "float64"
|
||||
packer_type = packer.float64
|
||||
|
||||
|
||||
class SOffsetTFlags(Int32Flags):
|
||||
pass
|
||||
|
||||
|
||||
class UOffsetTFlags(Uint32Flags):
|
||||
pass
|
||||
|
||||
|
||||
class VOffsetTFlags(Uint16Flags):
|
||||
pass
|
||||
|
||||
|
||||
def valid_number(n, flags):
|
||||
if flags.min_val is None and flags.max_val is None:
|
||||
return True
|
||||
return flags.min_val <= n <= flags.max_val
|
||||
|
||||
|
||||
def enforce_number(n, flags):
|
||||
if flags.min_val is None and flags.max_val is None:
|
||||
return
|
||||
if not flags.min_val <= n <= flags.max_val:
|
||||
raise TypeError("bad number %s for type %s" % (str(n), flags.name))
|
||||
|
||||
|
||||
def float32_to_uint32(n):
|
||||
packed = struct.pack("<1f", n)
|
||||
(converted,) = struct.unpack("<1L", packed)
|
||||
return converted
|
||||
|
||||
|
||||
def uint32_to_float32(n):
|
||||
packed = struct.pack("<1L", n)
|
||||
(unpacked,) = struct.unpack("<1f", packed)
|
||||
return unpacked
|
||||
|
||||
|
||||
def float64_to_uint64(n):
|
||||
packed = struct.pack("<1d", n)
|
||||
(converted,) = struct.unpack("<1Q", packed)
|
||||
return converted
|
||||
|
||||
|
||||
def uint64_to_float64(n):
|
||||
packed = struct.pack("<1Q", n)
|
||||
(unpacked,) = struct.unpack("<1d", packed)
|
||||
return unpacked
|
||||
|
||||
|
||||
def to_numpy_type(number_type):
|
||||
if np is not None:
|
||||
return np.dtype(number_type.name).newbyteorder("<")
|
||||
else:
|
||||
raise NumpyRequiredForThisFeature("Numpy was not found.")
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
# Copyright 2016 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Provide pre-compiled struct packers for encoding and decoding.
|
||||
|
||||
See: https://docs.python.org/2/library/struct.html#format-characters
|
||||
"""
|
||||
|
||||
import struct
|
||||
from . import compat
|
||||
|
||||
|
||||
boolean = struct.Struct(compat.struct_bool_decl)
|
||||
|
||||
uint8 = struct.Struct("<B")
|
||||
uint16 = struct.Struct("<H")
|
||||
uint32 = struct.Struct("<I")
|
||||
uint64 = struct.Struct("<Q")
|
||||
|
||||
int8 = struct.Struct("<b")
|
||||
int16 = struct.Struct("<h")
|
||||
int32 = struct.Struct("<i")
|
||||
int64 = struct.Struct("<q")
|
||||
|
||||
float32 = struct.Struct("<f")
|
||||
float64 = struct.Struct("<d")
|
||||
|
||||
uoffset = uint32
|
||||
soffset = int32
|
||||
voffset = uint16
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
# Copyright 2014 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from . import encode
|
||||
from . import number_types as N
|
||||
|
||||
|
||||
class Table(object):
|
||||
"""Table wraps a byte slice and provides read access to its data.
|
||||
|
||||
The variable `Pos` indicates the root of the FlatBuffers object therein.
|
||||
"""
|
||||
|
||||
__slots__ = ("Bytes", "Pos")
|
||||
|
||||
def __init__(self, buf, pos):
|
||||
N.enforce_number(pos, N.UOffsetTFlags)
|
||||
|
||||
self.Bytes = buf
|
||||
self.Pos = pos
|
||||
|
||||
def Offset(self, vtableOffset):
|
||||
"""Offset provides access into the Table's vtable.
|
||||
|
||||
Deprecated fields are ignored by checking the vtable's length.
|
||||
"""
|
||||
|
||||
vtable = self.Pos - self.Get(N.SOffsetTFlags, self.Pos)
|
||||
vtableEnd = self.Get(N.VOffsetTFlags, vtable)
|
||||
if vtableOffset < vtableEnd:
|
||||
return self.Get(N.VOffsetTFlags, vtable + vtableOffset)
|
||||
return 0
|
||||
|
||||
def Indirect(self, off):
|
||||
"""Indirect retrieves the relative offset stored at `offset`."""
|
||||
N.enforce_number(off, N.UOffsetTFlags)
|
||||
return off + encode.Get(N.UOffsetTFlags.packer_type, self.Bytes, off)
|
||||
|
||||
def String(self, off):
|
||||
"""String gets a string from data stored inside the flatbuffer."""
|
||||
N.enforce_number(off, N.UOffsetTFlags)
|
||||
off += encode.Get(N.UOffsetTFlags.packer_type, self.Bytes, off)
|
||||
start = off + N.UOffsetTFlags.bytewidth
|
||||
length = encode.Get(N.UOffsetTFlags.packer_type, self.Bytes, off)
|
||||
return bytes(self.Bytes[start : start + length])
|
||||
|
||||
def VectorLen(self, off):
|
||||
"""VectorLen retrieves the length of the vector whose offset is stored
|
||||
|
||||
at "off" in this object.
|
||||
"""
|
||||
N.enforce_number(off, N.UOffsetTFlags)
|
||||
|
||||
off += self.Pos
|
||||
off += encode.Get(N.UOffsetTFlags.packer_type, self.Bytes, off)
|
||||
ret = encode.Get(N.UOffsetTFlags.packer_type, self.Bytes, off)
|
||||
return ret
|
||||
|
||||
def Vector(self, off):
|
||||
"""Vector retrieves the start of data of the vector whose offset is
|
||||
|
||||
stored at "off" in this object.
|
||||
"""
|
||||
N.enforce_number(off, N.UOffsetTFlags)
|
||||
|
||||
off += self.Pos
|
||||
x = off + self.Get(N.UOffsetTFlags, off)
|
||||
# data starts after metadata containing the vector length
|
||||
x += N.UOffsetTFlags.bytewidth
|
||||
return x
|
||||
|
||||
def Union(self, t2, off):
|
||||
"""Union initializes any Table-derived type to point to the union at
|
||||
|
||||
the given offset.
|
||||
"""
|
||||
assert type(t2) is Table
|
||||
N.enforce_number(off, N.UOffsetTFlags)
|
||||
|
||||
off += self.Pos
|
||||
t2.Pos = off + self.Get(N.UOffsetTFlags, off)
|
||||
t2.Bytes = self.Bytes
|
||||
|
||||
def Get(self, flags, off):
|
||||
"""Get retrieves a value of the type specified by `flags` at the
|
||||
|
||||
given offset.
|
||||
"""
|
||||
N.enforce_number(off, N.UOffsetTFlags)
|
||||
return flags.py_type(encode.Get(flags.packer_type, self.Bytes, off))
|
||||
|
||||
def GetSlot(self, slot, d, validator_flags):
|
||||
N.enforce_number(slot, N.VOffsetTFlags)
|
||||
if validator_flags is not None:
|
||||
N.enforce_number(d, validator_flags)
|
||||
off = self.Offset(slot)
|
||||
if off == 0:
|
||||
return d
|
||||
return self.Get(validator_flags, self.Pos + off)
|
||||
|
||||
def GetVectorAsNumpy(self, flags, off):
|
||||
"""GetVectorAsNumpy returns the vector that starts at `Vector(off)`
|
||||
|
||||
as a numpy array with the type specified by `flags`. The array is
|
||||
a `view` into Bytes, so modifying the returned array will
|
||||
modify Bytes in place.
|
||||
"""
|
||||
offset = self.Vector(off)
|
||||
length = self.VectorLen(off) # TODO: length accounts for bytewidth, right?
|
||||
numpy_dtype = N.to_numpy_type(flags)
|
||||
return encode.GetVectorAsNumpy(numpy_dtype, self.Bytes, length, offset)
|
||||
|
||||
def GetArrayAsNumpy(self, flags, off, length):
|
||||
"""GetArrayAsNumpy returns the array with fixed width that starts at `Vector(offset)`
|
||||
|
||||
with length `length` as a numpy array with the type specified by `flags`.
|
||||
The
|
||||
array is a `view` into Bytes so modifying the returned will modify Bytes in
|
||||
place.
|
||||
"""
|
||||
numpy_dtype = N.to_numpy_type(flags)
|
||||
return encode.GetVectorAsNumpy(numpy_dtype, self.Bytes, length, off)
|
||||
|
||||
def GetVOffsetTSlot(self, slot, d):
|
||||
"""GetVOffsetTSlot retrieves the VOffsetT that the given vtable location
|
||||
|
||||
points to. If the vtable value is zero, the default value `d`
|
||||
will be returned.
|
||||
"""
|
||||
|
||||
N.enforce_number(slot, N.VOffsetTFlags)
|
||||
N.enforce_number(d, N.VOffsetTFlags)
|
||||
|
||||
off = self.Offset(slot)
|
||||
if off == 0:
|
||||
return d
|
||||
return off
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
# Copyright 2017 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from . import encode
|
||||
from . import number_types
|
||||
from . import packer
|
||||
|
||||
|
||||
def GetSizePrefix(buf, offset):
|
||||
"""Extract the size prefix from a buffer."""
|
||||
return encode.Get(packer.int32, buf, offset)
|
||||
|
||||
|
||||
def GetBufferIdentifier(buf, offset, size_prefixed=False):
|
||||
"""Extract the file_identifier from a buffer"""
|
||||
if size_prefixed:
|
||||
# increase offset by size of UOffsetTFlags
|
||||
offset += number_types.UOffsetTFlags.bytewidth
|
||||
# increase offset by size of root table pointer
|
||||
offset += number_types.UOffsetTFlags.bytewidth
|
||||
# end of FILE_IDENTIFIER
|
||||
end = offset + encode.FILE_IDENTIFIER_LENGTH
|
||||
return buf[offset:end]
|
||||
|
||||
|
||||
def BufferHasIdentifier(buf, offset, file_identifier, size_prefixed=False):
|
||||
got = GetBufferIdentifier(buf, offset, size_prefixed=size_prefixed)
|
||||
return got == file_identifier
|
||||
|
||||
|
||||
def RemoveSizePrefix(buf, offset):
|
||||
"""Create a slice of a size-prefixed buffer that has
|
||||
|
||||
its position advanced just past the size prefix.
|
||||
"""
|
||||
return buf, offset + number_types.Int32Flags.bytewidth
|
||||
+347
@@ -0,0 +1,347 @@
|
||||
Metadata-Version: 2.2
|
||||
Name: h3
|
||||
Version: 4.3.1
|
||||
Summary: Uber's hierarchical hexagonal geospatial indexing system
|
||||
Author-Email: Uber Technologies <ajfriend@gmail.com>
|
||||
Maintainer-Email: AJ Friend <ajfriend@gmail.com>
|
||||
License:
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: Intended Audience :: Science/Research
|
||||
Classifier: License :: OSI Approved :: Apache Software License
|
||||
Classifier: Programming Language :: C
|
||||
Classifier: Programming Language :: Cython
|
||||
Classifier: Programming Language :: Python :: 3.8
|
||||
Classifier: Programming Language :: Python :: 3.9
|
||||
Classifier: Programming Language :: Python :: 3.10
|
||||
Classifier: Programming Language :: Python :: 3.11
|
||||
Classifier: Programming Language :: Python :: 3.12
|
||||
Classifier: Programming Language :: Python :: 3.13
|
||||
Classifier: Operating System :: MacOS :: MacOS X
|
||||
Classifier: Operating System :: POSIX :: Linux
|
||||
Classifier: Operating System :: Microsoft :: Windows
|
||||
Classifier: Topic :: Scientific/Engineering :: GIS
|
||||
Project-URL: Homepage, https://github.com/uber/h3-py
|
||||
Project-URL: Documentation, https://uber.github.io/h3-py/
|
||||
Project-URL: Bug Tracker, https://github.com/uber/h3-py/issues
|
||||
Project-URL: Discussions, https://github.com/uber/h3-py/discussions
|
||||
Project-URL: Changelog, https://uber.github.io/h3-py/_changelog.html
|
||||
Requires-Python: >=3.8
|
||||
Provides-Extra: numpy
|
||||
Requires-Dist: numpy; extra == "numpy"
|
||||
Provides-Extra: test
|
||||
Requires-Dist: pytest; extra == "test"
|
||||
Requires-Dist: pytest-cov; extra == "test"
|
||||
Requires-Dist: ruff; extra == "test"
|
||||
Requires-Dist: numpy; extra == "test"
|
||||
Provides-Extra: all
|
||||
Requires-Dist: h3[test]; extra == "all"
|
||||
Requires-Dist: jupyter-book; extra == "all"
|
||||
Requires-Dist: sphinx>=7.3.3; extra == "all"
|
||||
Requires-Dist: jupyterlab; extra == "all"
|
||||
Requires-Dist: jupyterlab-geojson; extra == "all"
|
||||
Requires-Dist: geopandas; extra == "all"
|
||||
Requires-Dist: geodatasets; extra == "all"
|
||||
Requires-Dist: matplotlib; extra == "all"
|
||||
Requires-Dist: contextily; extra == "all"
|
||||
Requires-Dist: cartopy; extra == "all"
|
||||
Requires-Dist: geoviews; extra == "all"
|
||||
Description-Content-Type: text/markdown
|
||||
|
||||
<img align="right" src="https://uber.github.io/img/h3Logo-color.svg" alt="H3 Logo" width="130">
|
||||
|
||||
# **h3-py**: Uber's H3 Hexagonal Hierarchical Geospatial Indexing System in Python
|
||||
|
||||
[](https://badge.fury.io/py/h3)
|
||||
[](https://pypistats.org/packages/h3)
|
||||
[](https://anaconda.org/conda-forge/h3-py)
|
||||
[](https://github.com/uber/h3/releases/tag/v4.3.0)
|
||||
[](https://github.com/uber/h3-py/blob/master/LICENSE)
|
||||
|
||||
[](https://github.com/uber/h3-py/actions)
|
||||
[](https://github.com/uber/h3-py/blob/master/.github/workflows/lint_and_coverage.yml#L31) <!-- 100% coverage is enforced in CI -->
|
||||
|
||||
|
||||
Python bindings for the [H3 core library](https://h3geo.org/).
|
||||
|
||||
- Documentation: [uber.github.io/h3-py](https://uber.github.io/h3-py)
|
||||
- GitHub repo: [github.com/uber/h3-py](https://github.com/uber/h3-py)
|
||||
|
||||
## Installation
|
||||
|
||||
From [PyPI](https://pypi.org/project/h3/):
|
||||
|
||||
```console
|
||||
pip install h3
|
||||
```
|
||||
|
||||
From [conda](https://github.com/conda-forge/h3-py-feedstock):
|
||||
|
||||
```console
|
||||
conda config --add channels conda-forge
|
||||
conda install h3-py
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```python
|
||||
>>> import h3
|
||||
>>> lat, lng = 37.769377, -122.388903
|
||||
>>> resolution = 9
|
||||
>>> h3.latlng_to_cell(lat, lng, resolution)
|
||||
'89283082e73ffff'
|
||||
```
|
||||
|
||||
|
||||
## APIs
|
||||
|
||||
[api_comparison]: https://uber.github.io/h3-py/api_comparison
|
||||
[api_quick]: https://uber.github.io/h3-py/api_quick
|
||||
|
||||
We provide [multiple APIs][api_comparison] in `h3-py`.
|
||||
|
||||
- All APIs have the same set of functions;
|
||||
see the [API reference][api_quick].
|
||||
- The APIs differ only in their input/output formats;
|
||||
see the [API comparison page][api_comparison].
|
||||
|
||||
|
||||
## Example gallery
|
||||
|
||||
Browse [a collection of example notebooks](https://github.com/uber/h3-py-notebooks),
|
||||
and if you have examples or visualizations of your own, please feel free
|
||||
to contribute!
|
||||
|
||||
[walkthrough]: https://nbviewer.jupyter.org/github/uber/h3-py-notebooks/blob/master/notebooks/usage.ipynb
|
||||
|
||||
We also have an introductory [walkthrough of the API][walkthrough].
|
||||
|
||||
|
||||
## Versioning
|
||||
|
||||
<!-- todo: this should just be the h3.versions() docstring, yeah? -->
|
||||
|
||||
`h3-py` wraps the [H3 core library](https://github.com/uber/h3),
|
||||
which is written in C.
|
||||
The C and Python projects each employ
|
||||
[semantic versioning](https://semver.org/),
|
||||
where versions take the form `X.Y.Z`.
|
||||
|
||||
The `h3-py` version string is guaranteed to match the C library string
|
||||
in both *major* and *minor* numbers (`X.Y`), but may differ on the
|
||||
*patch* (`Z`) number.
|
||||
This convention provides users with information on breaking changes and
|
||||
feature additions, while providing downstream bindings (like this one!)
|
||||
with the versioning freedom to fix bugs.
|
||||
|
||||
Use `h3.versions()` to see the version numbers for both
|
||||
`h3-py` and the C library. For example,
|
||||
|
||||
```python
|
||||
>>> import h3
|
||||
>>> h3.versions()
|
||||
{'c': '4.1.0', 'python': '4.1.1'}
|
||||
```
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
h3/CMakeLists.txt,sha256=8zQ0011t8bmsJw_GiKOFbkTZnquBh6ESCMZyLrm9u_U,22
|
||||
h3/__init__.py,sha256=-i_HfsVLg1wW2wX8p74WIxHXi7NPO1GSVtjILstnS8U,575
|
||||
h3/_h3shape.py,sha256=hhsBJyuy5MqDhG_BixzbCTOfQgaO6Gf2olFEYd6iLKE,8559
|
||||
h3/_version.py,sha256=Tjq_BBPmWroGgfnrf7u9TpAWss9iA5PnWSv8kkZkJY8,88
|
||||
h3/_cy/CMakeLists.txt,sha256=-h6Dk_V8VYydmDht9zCOv7wbSOl_G4MtlajIrj2D8hE,1528
|
||||
h3/_cy/__init__.py,sha256=-f0Zqm46bnFuV0-Vs2FJMhODzbL1Oow-zuRJQS5dBFs,2488
|
||||
h3/_cy/cells.cpython-312-aarch64-linux-gnu.so,sha256=IT938GoA2i_KXkLbzfy84nZB85Jl9g4KSm7rdHWBHPY,469320
|
||||
h3/_cy/cells.pxd,sha256=9GydN6Nc4vJFU0nVyCP8BvDA4P702OX2LDQdkAnHv9I,1326
|
||||
h3/_cy/cells.pyx,sha256=TcEjufzELbfLGxQ10IA1aFX-nQt8sDx6JT_HhKQtsNc,9517
|
||||
h3/_cy/edges.cpython-312-aarch64-linux-gnu.so,sha256=8nCk6r3A9PISVMLdzHTiatYt3dqNDeFkQ-sfemWmvYM,402824
|
||||
h3/_cy/edges.pxd,sha256=_zUOkV8aeWhk_xjicSWBDHNOp3vMEeg8o2Da06iYn38,561
|
||||
h3/_cy/edges.pyx,sha256=1ECoK-OP3_BplwLZqwqNwItMLNIja6kVMzMeo7maHz8,2487
|
||||
h3/_cy/error_system.cpython-312-aarch64-linux-gnu.so,sha256=R4fc8to7fKrP7QBXX5KB7SXQzasH_vo81f7U6bGs1mk,202360
|
||||
h3/_cy/error_system.pxd,sha256=Dd2LjHcmlkCcs5Tr_HSp7xcn8YsQq2Evk4HxtIZF9m4,109
|
||||
h3/_cy/error_system.pyx,sha256=gyg7NPuY2nfsj2QnJC11OTZUCXLvNybpcgNC25Jor7E,6908
|
||||
h3/_cy/h3api.h,sha256=lQHNByNGZG6AkVjpIB2OZEv7fnAbBfCGqe4oqx0Hgd0,26418
|
||||
h3/_cy/h3lib.pxd,sha256=d37c0MiHuWQL28ogaxiLjKq1P4lh_gdIPRZrjizHi2g,6955
|
||||
h3/_cy/latlng.cpython-312-aarch64-linux-gnu.so,sha256=Nr-18UTddm3XyqtmVqrxgbWPbihilri0Od-gE2FRr1Q,471768
|
||||
h3/_cy/latlng.pxd,sha256=WjOjY4jH_2lK6hnaVXCusqLg2DvvZ4rvAJyXeCQd2uk,266
|
||||
h3/_cy/latlng.pyx,sha256=FW8L4LEr6l7qhsRL28mFakVLHnfqSCKQDQ6Ued-nLks,8370
|
||||
h3/_cy/memory.cpython-312-aarch64-linux-gnu.so,sha256=FXPAzIgzILQh4LxXlOchgkLY6_kpFWmzb3zsIFFL9lg,336208
|
||||
h3/_cy/memory.pxd,sha256=jXGN68hdcPUyA_yFCesZxCksHwmHMO4Ah-I9ZwYBvXs,236
|
||||
h3/_cy/memory.pyx,sha256=KZo65H3rXn290iH05ZNkyt78mKEGIaVjzmgYdOon_PU,7103
|
||||
h3/_cy/to_multipoly.cpython-312-aarch64-linux-gnu.so,sha256=4r6p7uq0B_Ln85xK_P9HvC59LtTR-ZAXGYXMG8CUwBk,402440
|
||||
h3/_cy/to_multipoly.pyx,sha256=bpaP3rGl5mtWTp1aH0ksL-gMi_tobSxjnZvxX6B2R4o,1369
|
||||
h3/_cy/util.cpython-312-aarch64-linux-gnu.so,sha256=zIQQ7i19XEZiT4I6hMg3RdnXxb0ZDjRCU1ohQ9pwoxY,267856
|
||||
h3/_cy/util.pxd,sha256=9JeCVVOOxfd3QoK4q_W-yIhmEASq_X2Y-A_Crn2bvZg,346
|
||||
h3/_cy/util.pyx,sha256=9woUsIwPG18UmjDbw8QFNnIXT62HMOUKGUmGIKt_ONo,2348
|
||||
h3/_cy/vertex.cpython-312-aarch64-linux-gnu.so,sha256=5-tDMKX5uWCv-2W3gVPhAwFbcB8f5q092KLuUa5oChA,337024
|
||||
h3/_cy/vertex.pxd,sha256=lnRECjEFpohFr7iB6d2UrTN-s37UzXnSpaP_UV5866I,229
|
||||
h3/_cy/vertex.pyx,sha256=_26ur2q3CZzb0BGQ85Lvbjq9dRWscvjAsKlgmCAqVHc,910
|
||||
h3/api/__init__.py,sha256=X6P438-1N_2jWlFKNZ8q_jUop7ICRhwwa4I0RuxtQIQ,114
|
||||
h3/api/basic_int/__init__.py,sha256=pg0QGCIGIyT0WTnD2vDqP-LyW0m5E1qd9F19l6wf3Rs,25924
|
||||
h3/api/basic_int/_convert.py,sha256=GmVFFTT-mMHJ_Newx-6aF8TAtKBTrXglMx5RNV9w0Nk,187
|
||||
h3/api/basic_str/__init__.py,sha256=pg0QGCIGIyT0WTnD2vDqP-LyW0m5E1qd9F19l6wf3Rs,25924
|
||||
h3/api/basic_str/_convert.py,sha256=9B7uHdbUJhDb0GUEdSg-dUQpNCmvPviK6_DX99YS5UE,256
|
||||
h3/api/memview_int/__init__.py,sha256=pg0QGCIGIyT0WTnD2vDqP-LyW0m5E1qd9F19l6wf3Rs,25924
|
||||
h3/api/memview_int/_convert.py,sha256=ef5Omw0GJsUlR8r66O1p8f9IEEhCeTdDjlvN2A0urjA,105
|
||||
h3/api/numpy_int/__init__.py,sha256=pg0QGCIGIyT0WTnD2vDqP-LyW0m5E1qd9F19l6wf3Rs,25924
|
||||
h3/api/numpy_int/_convert.py,sha256=dhZLocPjucl6Uu872k1tAcuWXBRT29oUG8qFMoleulE,288
|
||||
include/h3/h3api.h,sha256=lQHNByNGZG6AkVjpIB2OZEv7fnAbBfCGqe4oqx0Hgd0,26418
|
||||
lib64/libh3.a,sha256=daDl9sRycc5tHGPbiHyd-IYfmyaXFQKnB-xES26wv4Q,170004
|
||||
lib64/cmake/h3/h3Config.cmake,sha256=QwISc49jy-ZH9Ba1YCQnick54sapi_pZDEJjDJyMrb4,959
|
||||
lib64/cmake/h3/h3ConfigVersion.cmake,sha256=Nf3JY8h9E9o1YHZ9TuUc_XN5CyS3yxa4pp5PTIEViKM,2762
|
||||
lib64/cmake/h3/h3Targets-release.cmake,sha256=pnJffyu5LDg0GeSMTTwBoVLamlDKo8XrjrCEyN7aP0w,797
|
||||
lib64/cmake/h3/h3Targets.cmake,sha256=K18pICoM546T1tLsCSvdLlnLf1-GyFYPqMq8G0mZobM,4217
|
||||
h3-4.3.1.dist-info/METADATA,sha256=XJDmH460i2LSmjPAibQR_6XHyedrvDe_0tXZM3v-7n0,18459
|
||||
h3-4.3.1.dist-info/WHEEL,sha256=uOikQdbS4EYP0OE7pa4p-weSIqjfixseckdKxHaHlvE,198
|
||||
h3-4.3.1.dist-info/RECORD,,
|
||||
h3-4.3.1.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
||||
@@ -0,0 +1,7 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: scikit-build-core 0.11.5
|
||||
Root-Is-Purelib: false
|
||||
Tag: cp312-cp312-manylinux_2_17_aarch64
|
||||
Tag: cp312-cp312-manylinux2014_aarch64
|
||||
Tag: cp312-cp312-manylinux_2_28_aarch64
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
+1
@@ -0,0 +1 @@
|
||||
add_subdirectory(_cy)
|
||||
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
# flake8: noqa
|
||||
|
||||
from .api.basic_str import *
|
||||
from ._version import __version__
|
||||
|
||||
from ._cy import (
|
||||
UnknownH3ErrorCode,
|
||||
H3BaseException,
|
||||
|
||||
H3GridNavigationError,
|
||||
H3MemoryError,
|
||||
H3ValueError,
|
||||
|
||||
H3FailedError,
|
||||
H3DomainError,
|
||||
H3LatLngDomainError,
|
||||
H3ResDomainError,
|
||||
H3CellInvalidError,
|
||||
H3DirEdgeInvalidError,
|
||||
H3UndirEdgeInvalidError,
|
||||
H3VertexInvalidError,
|
||||
H3PentagonError,
|
||||
H3DuplicateInputError,
|
||||
H3NotNeighborsError,
|
||||
H3ResMismatchError,
|
||||
H3MemoryAllocError,
|
||||
H3MemoryBoundsError,
|
||||
H3OptionInvalidError,
|
||||
)
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
macro(add_cython_file filename)
|
||||
add_custom_command(
|
||||
OUTPUT "${filename}.c"
|
||||
COMMENT
|
||||
"Making ${CMAKE_CURRENT_BINARY_DIR}/${filename}.c from ${CMAKE_CURRENT_SOURCE_DIR}/${filename}.pyx"
|
||||
COMMAND Python::Interpreter -m cython
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${filename}.pyx" --output-file "${filename}.c" -I ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
DEPENDS "${filename}.pyx"
|
||||
VERBATIM)
|
||||
|
||||
python_add_library(${filename} MODULE "${filename}.c" WITH_SOABI)
|
||||
|
||||
set_property(TARGET ${filename} PROPERTY C_STANDARD 99)
|
||||
target_link_libraries(${filename} PRIVATE h3)
|
||||
install(TARGETS ${filename} LIBRARY DESTINATION ${SKBUILD_PROJECT_NAME}/_cy)
|
||||
endmacro()
|
||||
|
||||
# GLOB pattern is recommended against
|
||||
# https://cmake.org/cmake/help/v3.14/command/file.html?highlight=file#filesystem
|
||||
add_cython_file(cells)
|
||||
add_cython_file(edges)
|
||||
add_cython_file(error_system)
|
||||
add_cython_file(latlng)
|
||||
add_cython_file(memory)
|
||||
add_cython_file(vertex)
|
||||
|
||||
add_cython_file(to_multipoly)
|
||||
add_cython_file(util)
|
||||
|
||||
# Include pyx and pxd files in distribution for use by Cython API
|
||||
install(
|
||||
FILES
|
||||
cells.pxd
|
||||
cells.pyx
|
||||
edges.pxd
|
||||
edges.pyx
|
||||
error_system.pyx
|
||||
h3lib.pxd
|
||||
latlng.pxd
|
||||
latlng.pyx
|
||||
memory.pxd
|
||||
memory.pyx
|
||||
util.pxd
|
||||
util.pyx
|
||||
vertex.pxd
|
||||
vertex.pyx
|
||||
DESTINATION
|
||||
${SKBUILD_PROJECT_NAME}/_cy
|
||||
)
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
# flake8: noqa
|
||||
|
||||
"""
|
||||
This module should serve as the interface between the C/Cython code and
|
||||
the Python code. That is, it is an internal API.
|
||||
This module should import all the Cython functions we
|
||||
intend to expose to be used in pure Python code, and each of the H3-py
|
||||
APIs should *only* reference functions and symbols listed here.
|
||||
|
||||
These functions should handle input validation, guard against the
|
||||
possibility of segfaults, raise appropriate errors, and handle memory
|
||||
management. The API wrapping code around this should focus on the cosmetic
|
||||
function interface and input conversion (string to int, for instance).
|
||||
"""
|
||||
|
||||
from .cells import (
|
||||
is_valid_cell,
|
||||
is_pentagon,
|
||||
get_base_cell_number,
|
||||
get_resolution,
|
||||
cell_to_parent,
|
||||
grid_distance,
|
||||
grid_disk,
|
||||
grid_ring,
|
||||
cell_to_children_size,
|
||||
cell_to_children,
|
||||
cell_to_child_pos,
|
||||
child_pos_to_cell,
|
||||
compact_cells,
|
||||
uncompact_cells,
|
||||
get_num_cells,
|
||||
average_hexagon_area,
|
||||
cell_area,
|
||||
grid_path_cells,
|
||||
is_res_class_iii,
|
||||
get_pentagons,
|
||||
get_res0_cells,
|
||||
cell_to_center_child,
|
||||
get_icosahedron_faces,
|
||||
cell_to_local_ij,
|
||||
local_ij_to_cell,
|
||||
)
|
||||
|
||||
from .edges import (
|
||||
are_neighbor_cells,
|
||||
cells_to_directed_edge,
|
||||
is_valid_directed_edge,
|
||||
get_directed_edge_origin,
|
||||
get_directed_edge_destination,
|
||||
directed_edge_to_cells,
|
||||
origin_to_directed_edges,
|
||||
average_hexagon_edge_length,
|
||||
edge_length,
|
||||
)
|
||||
|
||||
from .latlng import (
|
||||
latlng_to_cell,
|
||||
cell_to_latlng,
|
||||
polygon_to_cells,
|
||||
polygons_to_cells,
|
||||
polygon_to_cells_experimental,
|
||||
polygons_to_cells_experimental,
|
||||
cell_to_boundary,
|
||||
directed_edge_to_boundary,
|
||||
great_circle_distance,
|
||||
)
|
||||
|
||||
from .vertex import (
|
||||
cell_to_vertex,
|
||||
cell_to_vertexes,
|
||||
vertex_to_latlng,
|
||||
is_valid_vertex,
|
||||
)
|
||||
|
||||
from .to_multipoly import (
|
||||
cells_to_multi_polygon
|
||||
)
|
||||
|
||||
from .util import (
|
||||
c_version,
|
||||
str_to_int,
|
||||
int_to_str,
|
||||
)
|
||||
|
||||
from .memory import (
|
||||
iter_to_mv,
|
||||
)
|
||||
|
||||
from .error_system import (
|
||||
UnknownH3ErrorCode,
|
||||
H3BaseException,
|
||||
|
||||
H3GridNavigationError,
|
||||
H3MemoryError,
|
||||
H3ValueError,
|
||||
|
||||
H3FailedError,
|
||||
H3DomainError,
|
||||
H3LatLngDomainError,
|
||||
H3ResDomainError,
|
||||
H3CellInvalidError,
|
||||
H3DirEdgeInvalidError,
|
||||
H3UndirEdgeInvalidError,
|
||||
H3VertexInvalidError,
|
||||
H3PentagonError,
|
||||
H3DuplicateInputError,
|
||||
H3NotNeighborsError,
|
||||
H3ResMismatchError,
|
||||
H3MemoryAllocError,
|
||||
H3MemoryBoundsError,
|
||||
H3OptionInvalidError,
|
||||
)
|
||||
Binary file not shown.
+27
@@ -0,0 +1,27 @@
|
||||
from .h3lib cimport bool, int64_t, H3int
|
||||
|
||||
cpdef bool is_valid_cell(H3int h)
|
||||
cpdef bool is_pentagon(H3int h)
|
||||
cpdef int get_base_cell_number(H3int h) except -1
|
||||
cpdef int get_resolution(H3int h) except -1
|
||||
cpdef int grid_distance(H3int h1, H3int h2) except -1
|
||||
cpdef H3int[:] grid_disk(H3int h, int k)
|
||||
cpdef H3int[:] grid_ring(H3int h, int k)
|
||||
cpdef H3int cell_to_parent(H3int h, res=*) except 0
|
||||
cpdef int64_t cell_to_children_size(H3int h, res=*) except -1
|
||||
cpdef H3int[:] cell_to_children(H3int h, res=*)
|
||||
cpdef H3int cell_to_center_child(H3int h, res=*) except 0
|
||||
cpdef int64_t cell_to_child_pos(H3int child, int parent_res) except -1
|
||||
cpdef H3int child_pos_to_cell(H3int parent, int child_res, int64_t child_pos) except 0
|
||||
cpdef H3int[:] compact_cells(const H3int[:] hu)
|
||||
cpdef H3int[:] uncompact_cells(const H3int[:] hc, int res)
|
||||
cpdef int64_t get_num_cells(int resolution) except -1
|
||||
cpdef double average_hexagon_area(int resolution, unit=*) except -1
|
||||
cpdef double cell_area(H3int h, unit=*) except -1
|
||||
cpdef H3int[:] grid_path_cells(H3int start, H3int end)
|
||||
cpdef bool is_res_class_iii(H3int h)
|
||||
cpdef H3int[:] get_pentagons(int res)
|
||||
cpdef H3int[:] get_res0_cells()
|
||||
cpdef get_icosahedron_faces(H3int h)
|
||||
cpdef (int, int) cell_to_local_ij(H3int origin, H3int h) except *
|
||||
cpdef H3int local_ij_to_cell(H3int origin, int i, int j) except 0
|
||||
+419
@@ -0,0 +1,419 @@
|
||||
cimport h3lib
|
||||
from .h3lib cimport bool, int64_t, H3int, H3ErrorCodes
|
||||
|
||||
from .util cimport (
|
||||
check_cell,
|
||||
check_res, # we don't use?
|
||||
check_distance,
|
||||
)
|
||||
|
||||
from .error_system cimport (
|
||||
check_for_error,
|
||||
check_for_error_msg,
|
||||
)
|
||||
|
||||
from .memory cimport (
|
||||
H3MemoryManager,
|
||||
int_mv,
|
||||
)
|
||||
|
||||
# todo: add notes about Cython exception handling
|
||||
|
||||
|
||||
# bool is a python type, so we don't need the except clause
|
||||
cpdef bool is_valid_cell(H3int h):
|
||||
"""Validates an H3 cell (hexagon or pentagon)
|
||||
|
||||
Returns
|
||||
-------
|
||||
boolean
|
||||
"""
|
||||
return h3lib.isValidCell(h) == 1
|
||||
|
||||
|
||||
cpdef bool is_pentagon(H3int h):
|
||||
return h3lib.isPentagon(h) == 1
|
||||
|
||||
|
||||
cpdef int get_base_cell_number(H3int h) except -1:
|
||||
check_cell(h)
|
||||
|
||||
return h3lib.getBaseCellNumber(h)
|
||||
|
||||
|
||||
cpdef int get_resolution(H3int h) except -1:
|
||||
"""Returns the resolution of an H3 Index
|
||||
0--15
|
||||
"""
|
||||
check_cell(h)
|
||||
|
||||
return h3lib.getResolution(h)
|
||||
|
||||
|
||||
cpdef int grid_distance(H3int h1, H3int h2) except -1:
|
||||
""" Compute the grid distance between two cells
|
||||
"""
|
||||
cdef:
|
||||
int64_t distance
|
||||
|
||||
check_cell(h1)
|
||||
check_cell(h2)
|
||||
|
||||
check_for_error(
|
||||
h3lib.gridDistance(h1, h2, &distance)
|
||||
)
|
||||
|
||||
return distance
|
||||
|
||||
cpdef H3int[:] grid_disk(H3int h, int k):
|
||||
""" Return cells at grid distance `<= k` from `h`.
|
||||
"""
|
||||
cdef:
|
||||
int64_t n
|
||||
|
||||
check_cell(h)
|
||||
check_distance(k)
|
||||
|
||||
check_for_error(
|
||||
h3lib.maxGridDiskSize(k, &n)
|
||||
)
|
||||
|
||||
hmm = H3MemoryManager(n)
|
||||
check_for_error(
|
||||
h3lib.gridDisk(h, k, hmm.ptr)
|
||||
)
|
||||
mv = hmm.to_mv()
|
||||
|
||||
return mv
|
||||
|
||||
|
||||
cpdef H3int[:] grid_ring(H3int h, int k):
|
||||
""" Return cells at grid distance `== k` from `h`.
|
||||
Collection is "hollow" for k >= 1.
|
||||
"""
|
||||
check_cell(h)
|
||||
check_distance(k)
|
||||
|
||||
n = 6*k if k > 0 else 1
|
||||
hmm = H3MemoryManager(n)
|
||||
check_for_error(
|
||||
h3lib.gridRing(h, k, hmm.ptr)
|
||||
)
|
||||
mv = hmm.to_mv()
|
||||
|
||||
return mv
|
||||
|
||||
|
||||
cpdef H3int cell_to_parent(H3int h, res=None) except 0:
|
||||
cdef:
|
||||
H3int parent
|
||||
|
||||
check_cell(h)
|
||||
if res is None:
|
||||
res = get_resolution(h) - 1
|
||||
|
||||
err = h3lib.cellToParent(h, res, &parent)
|
||||
if err:
|
||||
msg = 'Invalid parent resolution {} for cell {}.'
|
||||
msg = msg.format(res, hex(h))
|
||||
check_for_error_msg(err, msg)
|
||||
|
||||
return parent
|
||||
|
||||
|
||||
cpdef int64_t cell_to_children_size(H3int h, res=None) except -1:
|
||||
cdef:
|
||||
int64_t n
|
||||
|
||||
check_cell(h)
|
||||
if res is None:
|
||||
res = get_resolution(h) + 1
|
||||
|
||||
err = h3lib.cellToChildrenSize(h, res, &n)
|
||||
if err:
|
||||
msg = 'Invalid child resolution {} for cell {}.'
|
||||
msg = msg.format(res, hex(h))
|
||||
check_for_error_msg(err, msg)
|
||||
|
||||
return n
|
||||
|
||||
|
||||
cpdef H3int[:] cell_to_children(H3int h, res=None):
|
||||
check_cell(h)
|
||||
if res is None:
|
||||
res = get_resolution(h) + 1
|
||||
|
||||
n = cell_to_children_size(h, res)
|
||||
|
||||
hmm = H3MemoryManager(n)
|
||||
check_for_error(
|
||||
h3lib.cellToChildren(h, res, hmm.ptr)
|
||||
)
|
||||
mv = hmm.to_mv()
|
||||
|
||||
return mv
|
||||
|
||||
|
||||
|
||||
cpdef H3int cell_to_center_child(H3int h, res=None) except 0:
|
||||
cdef:
|
||||
H3int child
|
||||
|
||||
check_cell(h)
|
||||
if res is None:
|
||||
res = get_resolution(h) + 1
|
||||
|
||||
err = h3lib.cellToCenterChild(h, res, &child)
|
||||
if err:
|
||||
msg = 'Invalid child resolution {} for cell {}.'
|
||||
msg = msg.format(res, hex(h))
|
||||
check_for_error_msg(err, msg)
|
||||
|
||||
return child
|
||||
|
||||
|
||||
cpdef int64_t cell_to_child_pos(H3int child, int parent_res) except -1:
|
||||
cdef:
|
||||
int64_t child_pos
|
||||
|
||||
check_cell(child)
|
||||
err = h3lib.cellToChildPos(child, parent_res, &child_pos)
|
||||
if err:
|
||||
msg = "Couldn't find child pos of cell {} at res {}."
|
||||
msg = msg.format(hex(child), parent_res)
|
||||
check_for_error_msg(err, msg)
|
||||
|
||||
return child_pos
|
||||
|
||||
|
||||
cpdef H3int child_pos_to_cell(H3int parent, int child_res, int64_t child_pos) except 0:
|
||||
cdef:
|
||||
H3int child
|
||||
|
||||
check_cell(parent)
|
||||
err = h3lib.childPosToCell(child_pos, parent, child_res, &child)
|
||||
if err:
|
||||
msg = "Couldn't find child with pos {} at res {} from parent {}."
|
||||
msg = msg.format(child_pos, child_res, hex(parent))
|
||||
check_for_error_msg(err, msg)
|
||||
|
||||
return child
|
||||
|
||||
|
||||
cpdef H3int[:] compact_cells(const H3int[:] hu):
|
||||
# todo: fix this with my own Cython object "wrapper" class?
|
||||
# everything has a .ptr interface?
|
||||
# todo: the Clib can handle 0-len arrays because it **avoids**
|
||||
# dereferencing the pointer, but Cython's syntax of
|
||||
# `&hu[0]` **requires** a dereference. For Cython, checking for array
|
||||
# length of zero and returning early seems like the easiest solution.
|
||||
# note: open to better ideas!
|
||||
|
||||
if len(hu) == 0:
|
||||
return H3MemoryManager(0).to_mv()
|
||||
|
||||
for h in hu: ## todo: should we have an array version? would that be faster?
|
||||
check_cell(h)
|
||||
|
||||
cdef size_t n = len(hu)
|
||||
hmm = H3MemoryManager(n)
|
||||
check_for_error(
|
||||
h3lib.compactCells(&hu[0], hmm.ptr, n)
|
||||
)
|
||||
mv = hmm.to_mv()
|
||||
|
||||
return mv
|
||||
|
||||
|
||||
# todo: https://stackoverflow.com/questions/50684977/cython-exception-type-for-a-function-returning-a-typed-memoryview
|
||||
# apparently, memoryviews are python objects, so we don't need to do the except clause
|
||||
cpdef H3int[:] uncompact_cells(const H3int[:] hc, int res):
|
||||
# todo: the Clib can handle 0-len arrays because it **avoids**
|
||||
# dereferencing the pointer, but Cython's syntax of
|
||||
# `&hc[0]` **requires** a dereference. For Cython, checking for array
|
||||
# length of zero and returning early seems like the easiest solution.
|
||||
# note: open to better ideas!
|
||||
cdef:
|
||||
int64_t n
|
||||
|
||||
|
||||
if len(hc) == 0:
|
||||
return H3MemoryManager(0).to_mv()
|
||||
|
||||
for h in hc:
|
||||
check_cell(h)
|
||||
|
||||
check_for_error(
|
||||
h3lib.uncompactCellsSize(&hc[0], len(hc), res, &n)
|
||||
)
|
||||
|
||||
hmm = H3MemoryManager(n)
|
||||
check_for_error(
|
||||
h3lib.uncompactCells(
|
||||
&hc[0], # todo: symmetry here with the wrapper object might be nice. hc.ptr / hc.n
|
||||
len(hc),
|
||||
hmm.ptr,
|
||||
hmm.n,
|
||||
res
|
||||
)
|
||||
)
|
||||
|
||||
mv = hmm.to_mv()
|
||||
|
||||
return mv
|
||||
|
||||
|
||||
cpdef int64_t get_num_cells(int resolution) except -1:
|
||||
cdef:
|
||||
int64_t num_cells
|
||||
|
||||
check_for_error(
|
||||
h3lib.getNumCells(resolution, &num_cells)
|
||||
)
|
||||
|
||||
return num_cells
|
||||
|
||||
|
||||
cpdef double average_hexagon_area(int resolution, unit='km^2') except -1:
|
||||
cdef:
|
||||
double area
|
||||
|
||||
check_for_error(
|
||||
h3lib.getHexagonAreaAvgKm2(resolution, &area)
|
||||
)
|
||||
|
||||
# todo: multiple units
|
||||
convert = {
|
||||
'km^2': 1.0,
|
||||
'm^2': 1000*1000.0
|
||||
}
|
||||
|
||||
try:
|
||||
area *= convert[unit]
|
||||
except:
|
||||
raise ValueError('Unknown unit: {}'.format(unit))
|
||||
|
||||
return area
|
||||
|
||||
|
||||
cpdef double cell_area(H3int h, unit='km^2') except -1:
|
||||
cdef:
|
||||
double area
|
||||
|
||||
if unit == 'rads^2':
|
||||
err = h3lib.cellAreaRads2(h, &area)
|
||||
elif unit == 'km^2':
|
||||
err = h3lib.cellAreaKm2(h, &area)
|
||||
elif unit == 'm^2':
|
||||
err = h3lib.cellAreaM2(h, &area)
|
||||
else:
|
||||
raise ValueError('Unknown unit: {}'.format(unit))
|
||||
|
||||
check_for_error(err)
|
||||
|
||||
return area
|
||||
|
||||
|
||||
cdef _could_not_find_line(err, start, end):
|
||||
msg = "Couldn't find line between cells {} and {}"
|
||||
msg = msg.format(hex(start), hex(end))
|
||||
|
||||
check_for_error_msg(err, msg)
|
||||
|
||||
cpdef H3int[:] grid_path_cells(H3int start, H3int end):
|
||||
cdef:
|
||||
int64_t n
|
||||
|
||||
# todo: can we segfault here with invalid inputs?
|
||||
# Can we trust the c library to validate the start/end cells?
|
||||
# probably applies to all size/work pairs of functions...
|
||||
err = h3lib.gridPathCellsSize(start, end, &n)
|
||||
|
||||
_could_not_find_line(err, start, end)
|
||||
|
||||
hmm = H3MemoryManager(n)
|
||||
err = h3lib.gridPathCells(start, end, hmm.ptr)
|
||||
|
||||
_could_not_find_line(err, start, end)
|
||||
|
||||
# todo: probably here too?
|
||||
mv = hmm.to_mv()
|
||||
|
||||
return mv
|
||||
|
||||
cpdef bool is_res_class_iii(H3int h):
|
||||
return h3lib.isResClassIII(h) == 1
|
||||
|
||||
|
||||
cpdef H3int[:] get_pentagons(int res):
|
||||
n = h3lib.pentagonCount()
|
||||
|
||||
hmm = H3MemoryManager(n)
|
||||
check_for_error(
|
||||
h3lib.getPentagons(res, hmm.ptr)
|
||||
)
|
||||
mv = hmm.to_mv()
|
||||
|
||||
return mv
|
||||
|
||||
|
||||
cpdef H3int[:] get_res0_cells():
|
||||
n = h3lib.res0CellCount()
|
||||
|
||||
hmm = H3MemoryManager(n)
|
||||
check_for_error(
|
||||
h3lib.getRes0Cells(hmm.ptr)
|
||||
)
|
||||
mv = hmm.to_mv()
|
||||
|
||||
return mv
|
||||
|
||||
# oh, this is returning a set??
|
||||
# todo: convert to int[:]?
|
||||
cpdef get_icosahedron_faces(H3int h):
|
||||
cdef:
|
||||
int n
|
||||
int[:] faces ## todo: weird, this needs to be specified to avoid errors. cython bug?
|
||||
|
||||
check_for_error(
|
||||
h3lib.maxFaceCount(h, &n)
|
||||
)
|
||||
|
||||
faces = int_mv(n)
|
||||
check_for_error(
|
||||
h3lib.getIcosahedronFaces(h, &faces[0])
|
||||
)
|
||||
|
||||
# todo: wait? do faces start from 0 or 1?
|
||||
# we could do this check/processing in the int_mv object
|
||||
out = [f for f in faces if f >= 0]
|
||||
|
||||
return out
|
||||
|
||||
|
||||
cpdef (int, int) cell_to_local_ij(H3int origin, H3int h) except *:
|
||||
cdef:
|
||||
h3lib.CoordIJ c
|
||||
|
||||
err = h3lib.cellToLocalIj(origin, h, 0, &c)
|
||||
if err:
|
||||
msg = "Couldn't find local (i,j) between cells {} and {}."
|
||||
msg = msg.format(hex(origin), hex(h))
|
||||
check_for_error_msg(err, msg)
|
||||
|
||||
return c.i, c.j
|
||||
|
||||
cpdef H3int local_ij_to_cell(H3int origin, int i, int j) except 0:
|
||||
cdef:
|
||||
h3lib.CoordIJ c
|
||||
H3int out
|
||||
|
||||
c.i, c.j = i, j
|
||||
|
||||
err = h3lib.localIjToCell(origin, &c, 0, &out)
|
||||
if err:
|
||||
msg = "Couldn't find cell at local ({},{}) from cell {}."
|
||||
msg = msg.format(i, j, hex(origin))
|
||||
check_for_error_msg(err, msg)
|
||||
|
||||
return out
|
||||
Binary file not shown.
+11
@@ -0,0 +1,11 @@
|
||||
from .h3lib cimport bool, H3int
|
||||
|
||||
cpdef bool are_neighbor_cells(H3int h1, H3int h2)
|
||||
cpdef H3int cells_to_directed_edge(H3int origin, H3int destination) except *
|
||||
cpdef bool is_valid_directed_edge(H3int e)
|
||||
cpdef H3int get_directed_edge_origin(H3int e) except 1
|
||||
cpdef H3int get_directed_edge_destination(H3int e) except 1
|
||||
cpdef (H3int, H3int) directed_edge_to_cells(H3int e) except *
|
||||
cpdef H3int[:] origin_to_directed_edges(H3int origin)
|
||||
cpdef double average_hexagon_edge_length(int resolution, unit=*) except -1
|
||||
cpdef double edge_length(H3int e, unit=*) except -1
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
cimport h3lib
|
||||
from .h3lib cimport bool, H3int
|
||||
|
||||
from .error_system cimport check_for_error
|
||||
|
||||
from .memory cimport H3MemoryManager
|
||||
|
||||
# todo: make bint
|
||||
cpdef bool are_neighbor_cells(H3int h1, H3int h2):
|
||||
cdef:
|
||||
int out
|
||||
|
||||
err = h3lib.areNeighborCells(h1, h2, &out)
|
||||
|
||||
# note: we are intentionally not raising an error here, and just
|
||||
# returning false.
|
||||
# todo: is this choice consistent across the Python and C libs?
|
||||
if err:
|
||||
return False
|
||||
|
||||
return out == 1
|
||||
|
||||
|
||||
cpdef H3int cells_to_directed_edge(H3int origin, H3int destination) except *:
|
||||
cdef:
|
||||
int neighbor_out
|
||||
H3int out
|
||||
|
||||
check_for_error(
|
||||
h3lib.cellsToDirectedEdge(origin, destination, &out)
|
||||
)
|
||||
|
||||
return out
|
||||
|
||||
|
||||
cpdef bool is_valid_directed_edge(H3int e):
|
||||
return h3lib.isValidDirectedEdge(e) == 1
|
||||
|
||||
cpdef H3int get_directed_edge_origin(H3int e) except 1:
|
||||
cdef:
|
||||
H3int out
|
||||
|
||||
check_for_error(
|
||||
h3lib.getDirectedEdgeOrigin(e, &out)
|
||||
)
|
||||
|
||||
return out
|
||||
|
||||
cpdef H3int get_directed_edge_destination(H3int e) except 1:
|
||||
cdef:
|
||||
H3int out
|
||||
|
||||
check_for_error(
|
||||
h3lib.getDirectedEdgeDestination(e, &out)
|
||||
)
|
||||
|
||||
return out
|
||||
|
||||
cpdef (H3int, H3int) directed_edge_to_cells(H3int e) except *:
|
||||
# todo: use directed_edge_to_cells in h3lib
|
||||
return get_directed_edge_origin(e), get_directed_edge_destination(e)
|
||||
|
||||
cpdef H3int[:] origin_to_directed_edges(H3int origin):
|
||||
""" Returns the 6 (or 5 for pentagons) directed edges
|
||||
for the given origin cell
|
||||
"""
|
||||
|
||||
hmm = H3MemoryManager(6)
|
||||
check_for_error(
|
||||
h3lib.originToDirectedEdges(origin, hmm.ptr)
|
||||
)
|
||||
mv = hmm.to_mv()
|
||||
|
||||
return mv
|
||||
|
||||
|
||||
cpdef double average_hexagon_edge_length(int resolution, unit='km') except -1:
|
||||
cdef:
|
||||
double length
|
||||
|
||||
check_for_error(
|
||||
h3lib.getHexagonEdgeLengthAvgKm(resolution, &length)
|
||||
)
|
||||
|
||||
# todo: multiple units
|
||||
convert = {
|
||||
'km': 1.0,
|
||||
'm': 1000.0
|
||||
}
|
||||
|
||||
try:
|
||||
length *= convert[unit]
|
||||
except:
|
||||
raise ValueError('Unknown unit: {}'.format(unit))
|
||||
|
||||
return length
|
||||
|
||||
|
||||
cpdef double edge_length(H3int e, unit='km') except -1:
|
||||
cdef:
|
||||
double length
|
||||
|
||||
if unit == 'rads':
|
||||
err = h3lib.edgeLengthRads(e, &length)
|
||||
elif unit == 'km':
|
||||
err = h3lib.edgeLengthKm(e, &length)
|
||||
elif unit == 'm':
|
||||
err = h3lib.edgeLengthM(e, &length)
|
||||
else:
|
||||
raise ValueError('Unknown unit: {}'.format(unit))
|
||||
|
||||
check_for_error(err)
|
||||
|
||||
return length
|
||||
Binary file not shown.
@@ -0,0 +1,3 @@
|
||||
from .h3lib cimport H3Error
|
||||
cdef check_for_error(H3Error err)
|
||||
cdef check_for_error_msg(H3Error err, str msg)
|
||||
+231
@@ -0,0 +1,231 @@
|
||||
"""
|
||||
Exceptions from the h3-py library have three possible sources:
|
||||
|
||||
- the Python code
|
||||
- the Cython code
|
||||
- the underlying H3 C library code
|
||||
|
||||
The Python and Cython `h3-py` code will only raise standard Python
|
||||
built-in exceptions; **no custom** exception classes will be used.
|
||||
|
||||
Conversely, many functions in the H3 C library return a `uint32_t`
|
||||
error code (aliased as type `H3Error`).
|
||||
When these errors happen (and `h3-py` can't recover from them internally),
|
||||
they are passed up to the Python/Cython code, where their
|
||||
`uint32_t` error values are converted to **custom** Python exception types.
|
||||
These custom exception classes all inherit from `H3BaseException`.
|
||||
|
||||
There is a 1-1 correspondence between the concrete subclasses of
|
||||
`H3BaseException` and the H3 C library `H3ErrorCodes` values.
|
||||
The correspondence is intentional, so that the user can refer to the
|
||||
H3 C library documentation on these errors.
|
||||
|
||||
The (`uint32_t` <-> Exception) correspondence should be clear from
|
||||
the names of each error/exception, but the explicit mapping is given by
|
||||
a dictionary in the code below.
|
||||
|
||||
Note that some "abstract" subclasses of `H3BaseException` are also included to
|
||||
group the exceptions by type. (We say "abstract" because Python has no easy
|
||||
way to make true abstract exception classes.)
|
||||
|
||||
These "abstract" exceptions will never be raised directly by `h3-py`, but they
|
||||
allow the user to catch general groups of errors.
|
||||
Note that `h3-py` will only ever directly raise
|
||||
the "concrete" exception classes.
|
||||
|
||||
Summarizing, all exceptions originating from the C library inherit from
|
||||
`H3BaseException`, which has both "abstract" and "concrete" subclasses.
|
||||
|
||||
**Abstract classes**:
|
||||
|
||||
- H3BaseException
|
||||
- H3ValueError
|
||||
- H3MemoryError
|
||||
- H3GridNavigationError
|
||||
|
||||
**Concrete classes**:
|
||||
|
||||
- H3FailedError
|
||||
- H3DomainError
|
||||
- H3LatLngDomainError
|
||||
- H3ResDomainError
|
||||
- H3CellInvalidError
|
||||
- H3DirEdgeInvalidError
|
||||
- H3UndirEdgeInvalidError
|
||||
- H3VertexInvalidError
|
||||
- H3PentagonError
|
||||
- H3DuplicateInputError
|
||||
- H3NotNeighborsError
|
||||
- H3ResMismatchError
|
||||
- H3MemoryAllocError
|
||||
- H3MemoryBoundsError
|
||||
- H3OptionInvalidError
|
||||
|
||||
|
||||
# TODO: add tests verifying that concrete exception classes have the right error codes associated with them
|
||||
"""
|
||||
|
||||
from contextlib import contextmanager
|
||||
|
||||
from .h3lib cimport (
|
||||
H3Error,
|
||||
|
||||
# H3ErrorCodes enum values
|
||||
E_SUCCESS,
|
||||
E_FAILED,
|
||||
E_DOMAIN,
|
||||
E_LATLNG_DOMAIN,
|
||||
E_RES_DOMAIN,
|
||||
E_CELL_INVALID,
|
||||
E_DIR_EDGE_INVALID,
|
||||
E_UNDIR_EDGE_INVALID,
|
||||
E_VERTEX_INVALID,
|
||||
E_PENTAGON,
|
||||
E_DUPLICATE_INPUT,
|
||||
E_NOT_NEIGHBORS,
|
||||
E_RES_MISMATCH,
|
||||
E_MEMORY_ALLOC,
|
||||
E_MEMORY_BOUNDS,
|
||||
E_OPTION_INVALID,
|
||||
)
|
||||
|
||||
@contextmanager
|
||||
def _the_error(obj):
|
||||
"""
|
||||
Syntactic maple syrup for grouping exception definitions.
|
||||
The associated `with` statement ends up as a not-half-bad
|
||||
approximation to a valid sentence fragment.
|
||||
|
||||
This provides sort of a "pretend scope", in that it allows for
|
||||
block indentation which helps to visually indicate the "scope"
|
||||
of the `... as e` statement. Just note that Python doesn't treat the
|
||||
`with` block as a "true" separate scope.
|
||||
|
||||
Note that this doesn't actually do anything context-manager-y, outside
|
||||
of the variable assignment and block indentation.
|
||||
"""
|
||||
yield obj
|
||||
|
||||
|
||||
#
|
||||
# Base exception for C library error codes
|
||||
#
|
||||
class H3BaseException(Exception):
|
||||
""" Base H3 exception class.
|
||||
|
||||
Concrete subclasses of this class correspond to specific
|
||||
error codes from the C library.
|
||||
|
||||
Base/abstract subclasses will have `h3_error_code = None`, while
|
||||
concrete subclasses will have `h3_error_code` equal to their associated
|
||||
C library error code.
|
||||
"""
|
||||
h3_error_code = None
|
||||
|
||||
|
||||
#
|
||||
# A few "abstract" exceptions; organizational.
|
||||
#
|
||||
with _the_error(H3BaseException) as e:
|
||||
class H3ValueError(e, ValueError): ...
|
||||
class H3MemoryError(e, MemoryError): ...
|
||||
class H3GridNavigationError(e, RuntimeError): ...
|
||||
|
||||
|
||||
#
|
||||
# Concrete exceptions
|
||||
#
|
||||
class UnknownH3ErrorCode(H3BaseException):
|
||||
"""
|
||||
Indicates that the h3-py Python bindings have received an
|
||||
unrecognized error code from the C library.
|
||||
|
||||
This should never happen. Please report if you get this error.
|
||||
|
||||
Note that this exception is *outside* of the
|
||||
H3BaseException class hierarchy.
|
||||
"""
|
||||
pass
|
||||
|
||||
with _the_error(H3BaseException) as e:
|
||||
class H3FailedError(e): ...
|
||||
|
||||
with _the_error(H3GridNavigationError) as e:
|
||||
class H3PentagonError(e): ...
|
||||
|
||||
with _the_error(H3MemoryError) as e:
|
||||
class H3MemoryAllocError(e): ...
|
||||
class H3MemoryBoundsError(e): ...
|
||||
|
||||
with _the_error(H3ValueError) as e:
|
||||
class H3DomainError(e): ...
|
||||
class H3LatLngDomainError(e): ...
|
||||
class H3ResDomainError(e): ...
|
||||
class H3CellInvalidError(e): ...
|
||||
class H3DirEdgeInvalidError(e): ...
|
||||
class H3UndirEdgeInvalidError(e): ...
|
||||
class H3VertexInvalidError(e): ...
|
||||
class H3DuplicateInputError(e): ...
|
||||
class H3NotNeighborsError(e): ...
|
||||
class H3ResMismatchError(e): ...
|
||||
class H3OptionInvalidError(e): ...
|
||||
|
||||
|
||||
"""
|
||||
This defines a mapping between uint32_t error codes and concrete Python
|
||||
exception classes.
|
||||
Note that we intentionally omit E_SUCCESS, as it isn't an actual error.
|
||||
"""
|
||||
error_mapping = {
|
||||
E_FAILED: H3FailedError,
|
||||
E_DOMAIN: H3DomainError,
|
||||
E_LATLNG_DOMAIN: H3LatLngDomainError,
|
||||
E_RES_DOMAIN: H3ResDomainError,
|
||||
E_CELL_INVALID: H3CellInvalidError,
|
||||
E_DIR_EDGE_INVALID: H3DirEdgeInvalidError,
|
||||
E_UNDIR_EDGE_INVALID: H3UndirEdgeInvalidError,
|
||||
E_VERTEX_INVALID: H3VertexInvalidError,
|
||||
E_PENTAGON: H3PentagonError,
|
||||
E_DUPLICATE_INPUT: H3DuplicateInputError,
|
||||
E_NOT_NEIGHBORS: H3NotNeighborsError,
|
||||
E_RES_MISMATCH: H3ResMismatchError,
|
||||
E_MEMORY_ALLOC: H3MemoryAllocError,
|
||||
E_MEMORY_BOUNDS: H3MemoryBoundsError,
|
||||
E_OPTION_INVALID: H3OptionInvalidError,
|
||||
}
|
||||
|
||||
# Go back and modify the class definitions so that each concrete exception
|
||||
# stores its associated error code.
|
||||
for code, ex in error_mapping.items():
|
||||
ex.h3_error_code = code
|
||||
|
||||
|
||||
#
|
||||
# Helper functions
|
||||
#
|
||||
|
||||
# TODO: Move the helpers to util?
|
||||
# TODO: Unclear how/where to expose these functions. cdef/cpdef?
|
||||
|
||||
cdef code_to_exception(H3Error err):
|
||||
if err == E_SUCCESS:
|
||||
return None
|
||||
elif err in error_mapping:
|
||||
return error_mapping[err]
|
||||
else:
|
||||
raise UnknownH3ErrorCode(err)
|
||||
|
||||
cdef check_for_error(H3Error err):
|
||||
ex = code_to_exception(err)
|
||||
if ex:
|
||||
raise ex
|
||||
|
||||
# todo: There's no easy way to do `*args` in `cdef` functions, but I'm also
|
||||
# not sure this even needs to be a Cython `cdef` function at all, or that
|
||||
# any of the other helper functions need to be in Cython.
|
||||
# todo: Revisit after we've played with this a bit.
|
||||
# todo: also: maybe the extra messages aren't that much more helpful...
|
||||
cdef check_for_error_msg(H3Error err, str msg):
|
||||
ex = code_to_exception(err)
|
||||
if ex:
|
||||
raise ex(msg)
|
||||
Vendored
+809
@@ -0,0 +1,809 @@
|
||||
/*
|
||||
* Copyright 2016-2021 Uber Technologies, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/** @file h3api.h
|
||||
* @brief Primary H3 core library entry points.
|
||||
*
|
||||
* This file defines the public API of the H3 library. Incompatible changes to
|
||||
* these functions require the library's major version be increased.
|
||||
*/
|
||||
|
||||
#ifndef H3API_H
|
||||
#define H3API_H
|
||||
|
||||
/*
|
||||
* Preprocessor code to support renaming (prefixing) the public API.
|
||||
* All public functions should be wrapped in H3_EXPORT so they can be
|
||||
* renamed.
|
||||
*/
|
||||
#ifdef H3_PREFIX
|
||||
#define XTJOIN(a, b) a##b
|
||||
#define TJOIN(a, b) XTJOIN(a, b)
|
||||
|
||||
/* export joins the user provided prefix with our exported function name */
|
||||
#define H3_EXPORT(name) TJOIN(H3_PREFIX, name)
|
||||
#else
|
||||
#define H3_EXPORT(name) name
|
||||
#endif
|
||||
|
||||
/* Windows DLL requires attributes indicating what to export */
|
||||
#if _WIN32 && BUILD_SHARED_LIBS
|
||||
#if BUILDING_H3
|
||||
#define DECLSPEC __declspec(dllexport)
|
||||
#else
|
||||
#define DECLSPEC __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define DECLSPEC
|
||||
#endif
|
||||
|
||||
/* For uint64_t */
|
||||
#include <stdint.h>
|
||||
/* For size_t */
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
* H3 is compiled as C, not C++ code. `extern "C"` is needed for C++ code
|
||||
* to be able to use the library.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Identifier for an object (cell, edge, etc) in the H3 system.
|
||||
*
|
||||
* The H3Index fits within a 64-bit unsigned integer.
|
||||
*/
|
||||
typedef uint64_t H3Index;
|
||||
|
||||
/**
|
||||
* Invalid index used to indicate an error from latLngToCell and related
|
||||
* functions or missing data in arrays of H3 indices. Analogous to NaN in
|
||||
* floating point.
|
||||
*/
|
||||
#define H3_NULL 0
|
||||
|
||||
/** @brief Result code (success or specific error) from an H3 operation */
|
||||
typedef uint32_t H3Error;
|
||||
|
||||
typedef enum {
|
||||
E_SUCCESS = 0, // Success (no error)
|
||||
E_FAILED =
|
||||
1, // The operation failed but a more specific error is not available
|
||||
E_DOMAIN = 2, // Argument was outside of acceptable range (when a more
|
||||
// specific error code is not available)
|
||||
E_LATLNG_DOMAIN =
|
||||
3, // Latitude or longitude arguments were outside of acceptable range
|
||||
E_RES_DOMAIN = 4, // Resolution argument was outside of acceptable range
|
||||
E_CELL_INVALID = 5, // `H3Index` cell argument was not valid
|
||||
E_DIR_EDGE_INVALID = 6, // `H3Index` directed edge argument was not valid
|
||||
E_UNDIR_EDGE_INVALID =
|
||||
7, // `H3Index` undirected edge argument was not valid
|
||||
E_VERTEX_INVALID = 8, // `H3Index` vertex argument was not valid
|
||||
E_PENTAGON = 9, // Pentagon distortion was encountered which the algorithm
|
||||
// could not handle it
|
||||
E_DUPLICATE_INPUT = 10, // Duplicate input was encountered in the arguments
|
||||
// and the algorithm could not handle it
|
||||
E_NOT_NEIGHBORS = 11, // `H3Index` cell arguments were not neighbors
|
||||
E_RES_MISMATCH =
|
||||
12, // `H3Index` cell arguments had incompatible resolutions
|
||||
E_MEMORY_ALLOC = 13, // Necessary memory allocation failed
|
||||
E_MEMORY_BOUNDS = 14, // Bounds of provided memory were not large enough
|
||||
E_OPTION_INVALID = 15 // Mode or flags argument was not valid.
|
||||
} H3ErrorCodes;
|
||||
|
||||
/** @defgroup describeH3Error describeH3Error
|
||||
* Functions for describeH3Error
|
||||
* @{
|
||||
*/
|
||||
/** @brief converts the provided H3Error value into a description string */
|
||||
DECLSPEC const char *H3_EXPORT(describeH3Error)(H3Error err);
|
||||
/** @} */
|
||||
|
||||
/* library version numbers generated from VERSION file */
|
||||
// clang-format off
|
||||
#define H3_VERSION_MAJOR 4
|
||||
#define H3_VERSION_MINOR 3
|
||||
#define H3_VERSION_PATCH 0
|
||||
// clang-format on
|
||||
|
||||
/** Maximum number of cell boundary vertices; worst case is pentagon:
|
||||
* 5 original verts + 5 edge crossings
|
||||
*/
|
||||
#define MAX_CELL_BNDRY_VERTS 10
|
||||
|
||||
/** @struct LatLng
|
||||
@brief latitude/longitude in radians
|
||||
*/
|
||||
typedef struct {
|
||||
double lat; ///< latitude in radians
|
||||
double lng; ///< longitude in radians
|
||||
} LatLng;
|
||||
|
||||
/** @struct CellBoundary
|
||||
@brief cell boundary in latitude/longitude
|
||||
*/
|
||||
typedef struct {
|
||||
int numVerts; ///< number of vertices
|
||||
LatLng verts[MAX_CELL_BNDRY_VERTS]; ///< vertices in ccw order
|
||||
} CellBoundary;
|
||||
|
||||
/** @struct GeoLoop
|
||||
* @brief similar to CellBoundary, but requires more alloc work
|
||||
*/
|
||||
typedef struct {
|
||||
int numVerts;
|
||||
LatLng *verts;
|
||||
} GeoLoop;
|
||||
|
||||
/** @struct GeoPolygon
|
||||
* @brief Simplified core of GeoJSON Polygon coordinates definition
|
||||
*/
|
||||
typedef struct {
|
||||
GeoLoop geoloop; ///< exterior boundary of the polygon
|
||||
int numHoles; ///< number of elements in the array pointed to by holes
|
||||
GeoLoop *holes; ///< interior boundaries (holes) in the polygon
|
||||
} GeoPolygon;
|
||||
|
||||
/** @struct GeoMultiPolygon
|
||||
* @brief Simplified core of GeoJSON MultiPolygon coordinates definition
|
||||
*/
|
||||
typedef struct {
|
||||
int numPolygons;
|
||||
GeoPolygon *polygons;
|
||||
} GeoMultiPolygon;
|
||||
|
||||
/**
|
||||
* Values representing polyfill containment modes, to be used in
|
||||
* the `flags` bit field for `polygonToCellsExperimental`.
|
||||
*/
|
||||
typedef enum {
|
||||
CONTAINMENT_CENTER = 0, ///< Cell center is contained in the shape
|
||||
CONTAINMENT_FULL = 1, ///< Cell is fully contained in the shape
|
||||
CONTAINMENT_OVERLAPPING = 2, ///< Cell overlaps the shape at any point
|
||||
CONTAINMENT_OVERLAPPING_BBOX = 3, ///< Cell bounding box overlaps shape
|
||||
CONTAINMENT_INVALID = 4 ///< This mode is invalid and should not be used
|
||||
} ContainmentMode;
|
||||
|
||||
/** @struct LinkedLatLng
|
||||
* @brief A coordinate node in a linked geo structure, part of a linked list
|
||||
*/
|
||||
typedef struct LinkedLatLng LinkedLatLng;
|
||||
struct LinkedLatLng {
|
||||
LatLng vertex;
|
||||
LinkedLatLng *next;
|
||||
};
|
||||
|
||||
/** @struct LinkedGeoLoop
|
||||
* @brief A loop node in a linked geo structure, part of a linked list
|
||||
*/
|
||||
typedef struct LinkedGeoLoop LinkedGeoLoop;
|
||||
struct LinkedGeoLoop {
|
||||
LinkedLatLng *first;
|
||||
LinkedLatLng *last;
|
||||
LinkedGeoLoop *next;
|
||||
};
|
||||
|
||||
/** @struct LinkedGeoPolygon
|
||||
* @brief A polygon node in a linked geo structure, part of a linked list.
|
||||
*/
|
||||
typedef struct LinkedGeoPolygon LinkedGeoPolygon;
|
||||
struct LinkedGeoPolygon {
|
||||
LinkedGeoLoop *first;
|
||||
LinkedGeoLoop *last;
|
||||
LinkedGeoPolygon *next;
|
||||
};
|
||||
|
||||
/** @struct CoordIJ
|
||||
* @brief IJ hexagon coordinates
|
||||
*
|
||||
* Each axis is spaced 120 degrees apart.
|
||||
*/
|
||||
typedef struct {
|
||||
int i; ///< i component
|
||||
int j; ///< j component
|
||||
} CoordIJ;
|
||||
|
||||
/** @defgroup latLngToCell latLngToCell
|
||||
* Functions for latLngToCell
|
||||
* @{
|
||||
*/
|
||||
/** @brief find the H3 index of the resolution res cell containing the lat/lng
|
||||
*/
|
||||
DECLSPEC H3Error H3_EXPORT(latLngToCell)(const LatLng *g, int res,
|
||||
H3Index *out);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup cellToLatLng cellToLatLng
|
||||
* Functions for cellToLatLng
|
||||
* @{
|
||||
*/
|
||||
/** @brief find the lat/lng center point g of the cell h3 */
|
||||
DECLSPEC H3Error H3_EXPORT(cellToLatLng)(H3Index h3, LatLng *g);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup cellToBoundary cellToBoundary
|
||||
* Functions for cellToBoundary
|
||||
* @{
|
||||
*/
|
||||
/** @brief give the cell boundary in lat/lng coordinates for the cell h3 */
|
||||
DECLSPEC H3Error H3_EXPORT(cellToBoundary)(H3Index h3, CellBoundary *gp);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup gridDisk gridDisk
|
||||
* Functions for gridDisk
|
||||
* @{
|
||||
*/
|
||||
/** @brief maximum number of hexagons in k-ring */
|
||||
DECLSPEC H3Error H3_EXPORT(maxGridDiskSize)(int k, int64_t *out);
|
||||
|
||||
/** @brief hexagons neighbors in all directions, assuming no pentagons */
|
||||
DECLSPEC H3Error H3_EXPORT(gridDiskUnsafe)(H3Index origin, int k, H3Index *out);
|
||||
/** @} */
|
||||
|
||||
/** @brief hexagons neighbors in all directions, assuming no pentagons,
|
||||
* reporting distance from origin */
|
||||
DECLSPEC H3Error H3_EXPORT(gridDiskDistancesUnsafe)(H3Index origin, int k,
|
||||
H3Index *out,
|
||||
int *distances);
|
||||
|
||||
/** @brief hexagons neighbors in all directions reporting distance from origin
|
||||
*/
|
||||
DECLSPEC H3Error H3_EXPORT(gridDiskDistancesSafe)(H3Index origin, int k,
|
||||
H3Index *out, int *distances);
|
||||
|
||||
/** @brief collection of hex rings sorted by ring for all given hexagons */
|
||||
DECLSPEC H3Error H3_EXPORT(gridDisksUnsafe)(H3Index *h3Set, int length, int k,
|
||||
H3Index *out);
|
||||
|
||||
/** @brief hexagon neighbors in all directions */
|
||||
DECLSPEC H3Error H3_EXPORT(gridDisk)(H3Index origin, int k, H3Index *out);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup gridDiskDistances gridDiskDistances
|
||||
* Functions for gridDiskDistances
|
||||
* @{
|
||||
*/
|
||||
/** @brief hexagon neighbors in all directions, reporting distance from origin
|
||||
*/
|
||||
DECLSPEC H3Error H3_EXPORT(gridDiskDistances)(H3Index origin, int k,
|
||||
H3Index *out, int *distances);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup gridRing gridRing
|
||||
* Functions for gridRing
|
||||
* @{
|
||||
*/
|
||||
/** @brief maximum number of hexagons in hollow k-ring */
|
||||
DECLSPEC H3Error H3_EXPORT(maxGridRingSize)(int k, int64_t *out);
|
||||
|
||||
/** @brief hollow hexagon ring k distance from origin */
|
||||
DECLSPEC H3Error H3_EXPORT(gridRingUnsafe)(H3Index origin, int k, H3Index *out);
|
||||
|
||||
/** @brief hollow hexagon ring k distance from origin */
|
||||
DECLSPEC H3Error H3_EXPORT(gridRing)(H3Index origin, int k, H3Index *out);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup polygonToCells polygonToCells
|
||||
* Functions for polygonToCells
|
||||
* @{
|
||||
*/
|
||||
/** @brief maximum number of cells that could be in the polygon */
|
||||
DECLSPEC H3Error H3_EXPORT(maxPolygonToCellsSize)(const GeoPolygon *geoPolygon,
|
||||
int res, uint32_t flags,
|
||||
int64_t *out);
|
||||
|
||||
/** @brief cells within the given polygon */
|
||||
DECLSPEC H3Error H3_EXPORT(polygonToCells)(const GeoPolygon *geoPolygon,
|
||||
int res, uint32_t flags,
|
||||
H3Index *out);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup polygonToCellsExperimental polygonToCellsExperimental
|
||||
* Functions for polygonToCellsExperimental.
|
||||
* This is an experimental-only API and is subject to change in minor versions.
|
||||
* @{
|
||||
*/
|
||||
/** @brief maximum number of cells that could be in the polygon */
|
||||
DECLSPEC H3Error H3_EXPORT(maxPolygonToCellsSizeExperimental)(
|
||||
const GeoPolygon *polygon, int res, uint32_t flags, int64_t *out);
|
||||
|
||||
/** @brief cells within the given polygon */
|
||||
DECLSPEC H3Error H3_EXPORT(polygonToCellsExperimental)(
|
||||
const GeoPolygon *polygon, int res, uint32_t flags, int64_t size,
|
||||
H3Index *out);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup cellsToMultiPolygon cellsToMultiPolygon
|
||||
* Functions for cellsToMultiPolygon (currently a binding-only concept)
|
||||
* @{
|
||||
*/
|
||||
/** @brief Create a LinkedGeoPolygon from a set of contiguous hexagons */
|
||||
DECLSPEC H3Error H3_EXPORT(cellsToLinkedMultiPolygon)(const H3Index *h3Set,
|
||||
const int numHexes,
|
||||
LinkedGeoPolygon *out);
|
||||
|
||||
/** @brief Free all memory created for a LinkedGeoPolygon */
|
||||
DECLSPEC void H3_EXPORT(destroyLinkedMultiPolygon)(LinkedGeoPolygon *polygon);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup degsToRads degsToRads
|
||||
* Functions for degsToRads
|
||||
* @{
|
||||
*/
|
||||
/** @brief converts degrees to radians */
|
||||
DECLSPEC double H3_EXPORT(degsToRads)(double degrees);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup radsToDegs radsToDegs
|
||||
* Functions for radsToDegs
|
||||
* @{
|
||||
*/
|
||||
/** @brief converts radians to degrees */
|
||||
DECLSPEC double H3_EXPORT(radsToDegs)(double radians);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup greatCircleDistance greatCircleDistance
|
||||
* Functions for distance
|
||||
* @{
|
||||
*/
|
||||
/** @brief "great circle distance" between pairs of LatLng points in radians*/
|
||||
DECLSPEC double H3_EXPORT(greatCircleDistanceRads)(const LatLng *a,
|
||||
const LatLng *b);
|
||||
|
||||
/** @brief "great circle distance" between pairs of LatLng points in
|
||||
* kilometers*/
|
||||
DECLSPEC double H3_EXPORT(greatCircleDistanceKm)(const LatLng *a,
|
||||
const LatLng *b);
|
||||
|
||||
/** @brief "great circle distance" between pairs of LatLng points in meters*/
|
||||
DECLSPEC double H3_EXPORT(greatCircleDistanceM)(const LatLng *a,
|
||||
const LatLng *b);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup getHexagonAreaAvg getHexagonAreaAvg
|
||||
* Functions for getHexagonAreaAvg
|
||||
* @{
|
||||
*/
|
||||
/** @brief average hexagon area in square kilometers (excludes pentagons) */
|
||||
DECLSPEC H3Error H3_EXPORT(getHexagonAreaAvgKm2)(int res, double *out);
|
||||
|
||||
/** @brief average hexagon area in square meters (excludes pentagons) */
|
||||
DECLSPEC H3Error H3_EXPORT(getHexagonAreaAvgM2)(int res, double *out);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup cellArea cellArea
|
||||
* Functions for cellArea
|
||||
* @{
|
||||
*/
|
||||
/** @brief exact area for a specific cell (hexagon or pentagon) in radians^2 */
|
||||
DECLSPEC H3Error H3_EXPORT(cellAreaRads2)(H3Index h, double *out);
|
||||
|
||||
/** @brief exact area for a specific cell (hexagon or pentagon) in kilometers^2
|
||||
*/
|
||||
DECLSPEC H3Error H3_EXPORT(cellAreaKm2)(H3Index h, double *out);
|
||||
|
||||
/** @brief exact area for a specific cell (hexagon or pentagon) in meters^2 */
|
||||
DECLSPEC H3Error H3_EXPORT(cellAreaM2)(H3Index h, double *out);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup getHexagonEdgeLengthAvg getHexagonEdgeLengthAvg
|
||||
* Functions for getHexagonEdgeLengthAvg
|
||||
* @{
|
||||
*/
|
||||
/** @brief average hexagon edge length in kilometers (excludes pentagons) */
|
||||
DECLSPEC H3Error H3_EXPORT(getHexagonEdgeLengthAvgKm)(int res, double *out);
|
||||
|
||||
/** @brief average hexagon edge length in meters (excludes pentagons) */
|
||||
DECLSPEC H3Error H3_EXPORT(getHexagonEdgeLengthAvgM)(int res, double *out);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup edgeLength edgeLength
|
||||
* Functions for edgeLength
|
||||
* @{
|
||||
*/
|
||||
/** @brief exact length for a specific directed edge in radians*/
|
||||
DECLSPEC H3Error H3_EXPORT(edgeLengthRads)(H3Index edge, double *length);
|
||||
|
||||
/** @brief exact length for a specific directed edge in kilometers*/
|
||||
DECLSPEC H3Error H3_EXPORT(edgeLengthKm)(H3Index edge, double *length);
|
||||
|
||||
/** @brief exact length for a specific directed edge in meters*/
|
||||
DECLSPEC H3Error H3_EXPORT(edgeLengthM)(H3Index edge, double *length);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup getNumCells getNumCells
|
||||
* Functions for getNumCells
|
||||
* @{
|
||||
*/
|
||||
/** @brief number of cells (hexagons and pentagons) for a given resolution
|
||||
*
|
||||
* It works out to be `2 + 120*7^r` for resolution `r`.
|
||||
*
|
||||
* # Mathematical notes
|
||||
*
|
||||
* Let h(n) be the number of children n levels below
|
||||
* a single *hexagon*.
|
||||
*
|
||||
* Then h(n) = 7^n.
|
||||
*
|
||||
* Let p(n) be the number of children n levels below
|
||||
* a single *pentagon*.
|
||||
*
|
||||
* Then p(0) = 1, and p(1) = 6, since each pentagon
|
||||
* has 5 hexagonal immediate children and 1 pentagonal
|
||||
* immediate child.
|
||||
*
|
||||
* In general, we have the recurrence relation
|
||||
*
|
||||
* p(n) = 5*h(n-1) + p(n-1)
|
||||
* = 5*7^(n-1) + p(n-1).
|
||||
*
|
||||
* Working through the recurrence, we get that
|
||||
*
|
||||
* p(n) = 1 + 5*\sum_{k=1}^n 7^{k-1}
|
||||
* = 1 + 5*(7^n - 1)/6,
|
||||
*
|
||||
* using the closed form for a geometric series.
|
||||
*
|
||||
* Using the closed forms for h(n) and p(n), we can
|
||||
* get a closed form for the total number of cells
|
||||
* at resolution r:
|
||||
*
|
||||
* c(r) = 12*p(r) + 110*h(r)
|
||||
* = 2 + 120*7^r.
|
||||
*
|
||||
*
|
||||
* @param res H3 cell resolution
|
||||
*
|
||||
* @return number of cells at resolution `res`
|
||||
*/
|
||||
DECLSPEC H3Error H3_EXPORT(getNumCells)(int res, int64_t *out);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup getRes0Cells getRes0Cells
|
||||
* Functions for getRes0Cells
|
||||
* @{
|
||||
*/
|
||||
/** @brief returns the number of resolution 0 cells (hexagons and pentagons) */
|
||||
DECLSPEC int H3_EXPORT(res0CellCount)(void);
|
||||
|
||||
/** @brief provides all base cells in H3Index format*/
|
||||
DECLSPEC H3Error H3_EXPORT(getRes0Cells)(H3Index *out);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup getPentagons getPentagons
|
||||
* Functions for getPentagons
|
||||
* @{
|
||||
*/
|
||||
/** @brief returns the number of pentagons per resolution */
|
||||
DECLSPEC int H3_EXPORT(pentagonCount)(void);
|
||||
|
||||
/** @brief generates all pentagons at the specified resolution */
|
||||
DECLSPEC H3Error H3_EXPORT(getPentagons)(int res, H3Index *out);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup getResolution getResolution
|
||||
* Functions for getResolution
|
||||
* @{
|
||||
*/
|
||||
/** @brief returns the resolution of the provided H3 index
|
||||
* Works on both cells and directed edges. */
|
||||
DECLSPEC int H3_EXPORT(getResolution)(H3Index h);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup getBaseCellNumber getBaseCellNumber
|
||||
* Functions for getBaseCellNumber
|
||||
* @{
|
||||
*/
|
||||
/** @brief returns the base cell "number" (0 to 121) of the provided H3 cell
|
||||
*
|
||||
* Note: Technically works on H3 edges, but will return base cell of the
|
||||
* origin cell. */
|
||||
DECLSPEC int H3_EXPORT(getBaseCellNumber)(H3Index h);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup stringToH3 stringToH3
|
||||
* Functions for stringToH3
|
||||
* @{
|
||||
*/
|
||||
/** @brief converts the canonical string format to H3Index format */
|
||||
DECLSPEC H3Error H3_EXPORT(stringToH3)(const char *str, H3Index *out);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup h3ToString h3ToString
|
||||
* Functions for h3ToString
|
||||
* @{
|
||||
*/
|
||||
/** @brief converts an H3Index to a canonical string */
|
||||
DECLSPEC H3Error H3_EXPORT(h3ToString)(H3Index h, char *str, size_t sz);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup isValidCell isValidCell
|
||||
* Functions for isValidCell
|
||||
* @{
|
||||
*/
|
||||
/** @brief confirms if an H3Index is a valid cell (hexagon or pentagon)
|
||||
* In particular, returns 0 (False) for H3 directed edges or invalid data
|
||||
*/
|
||||
DECLSPEC int H3_EXPORT(isValidCell)(H3Index h);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup cellToParent cellToParent
|
||||
* Functions for cellToParent
|
||||
* @{
|
||||
*/
|
||||
/** @brief returns the parent (or grandparent, etc) cell of the given cell
|
||||
*/
|
||||
DECLSPEC H3Error H3_EXPORT(cellToParent)(H3Index h, int parentRes,
|
||||
H3Index *parent);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup cellToChildren cellToChildren
|
||||
* Functions for cellToChildren
|
||||
* @{
|
||||
*/
|
||||
/** @brief determines the exact number of children (or grandchildren, etc)
|
||||
* that would be returned for the given cell */
|
||||
DECLSPEC H3Error H3_EXPORT(cellToChildrenSize)(H3Index h, int childRes,
|
||||
int64_t *out);
|
||||
|
||||
/** @brief provides the children (or grandchildren, etc) of the given cell */
|
||||
DECLSPEC H3Error H3_EXPORT(cellToChildren)(H3Index h, int childRes,
|
||||
H3Index *children);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup cellToCenterChild cellToCenterChild
|
||||
* Functions for cellToCenterChild
|
||||
* @{
|
||||
*/
|
||||
/** @brief returns the center child of the given cell at the specified
|
||||
* resolution */
|
||||
DECLSPEC H3Error H3_EXPORT(cellToCenterChild)(H3Index h, int childRes,
|
||||
H3Index *child);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup cellToChildPos cellToChildPos
|
||||
* Functions for cellToChildPos
|
||||
* @{
|
||||
*/
|
||||
/** @brief Returns the position of the cell within an ordered list of all
|
||||
* children of the cell's parent at the specified resolution */
|
||||
DECLSPEC H3Error H3_EXPORT(cellToChildPos)(H3Index child, int parentRes,
|
||||
int64_t *out);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup childPosToCell childPosToCell
|
||||
* Functions for childPosToCell
|
||||
* @{
|
||||
*/
|
||||
/** @brief Returns the child cell at a given position within an ordered list of
|
||||
* all children at the specified resolution */
|
||||
DECLSPEC H3Error H3_EXPORT(childPosToCell)(int64_t childPos, H3Index parent,
|
||||
int childRes, H3Index *child);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup compactCells compactCells
|
||||
* Functions for compactCells
|
||||
* @{
|
||||
*/
|
||||
/** @brief compacts the given set of hexagons as best as possible */
|
||||
DECLSPEC H3Error H3_EXPORT(compactCells)(const H3Index *h3Set,
|
||||
H3Index *compactedSet,
|
||||
const int64_t numHexes);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup uncompactCells uncompactCells
|
||||
* Functions for uncompactCells
|
||||
* @{
|
||||
*/
|
||||
/** @brief determines the exact number of hexagons that will be uncompacted
|
||||
* from the compacted set */
|
||||
DECLSPEC H3Error H3_EXPORT(uncompactCellsSize)(const H3Index *compactedSet,
|
||||
const int64_t numCompacted,
|
||||
const int res, int64_t *out);
|
||||
|
||||
/** @brief uncompacts the compacted hexagon set */
|
||||
DECLSPEC H3Error H3_EXPORT(uncompactCells)(const H3Index *compactedSet,
|
||||
const int64_t numCompacted,
|
||||
H3Index *outSet,
|
||||
const int64_t numOut, const int res);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup isResClassIII isResClassIII
|
||||
* Functions for isResClassIII
|
||||
* @{
|
||||
*/
|
||||
/** @brief determines if a hexagon is Class III (or Class II) */
|
||||
DECLSPEC int H3_EXPORT(isResClassIII)(H3Index h);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup isPentagon isPentagon
|
||||
* Functions for isPentagon
|
||||
* @{
|
||||
*/
|
||||
/** @brief determines if an H3 cell is a pentagon */
|
||||
DECLSPEC int H3_EXPORT(isPentagon)(H3Index h);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup getIcosahedronFaces getIcosahedronFaces
|
||||
* Functions for getIcosahedronFaces
|
||||
* @{
|
||||
*/
|
||||
/** @brief Max number of icosahedron faces intersected by an index */
|
||||
DECLSPEC H3Error H3_EXPORT(maxFaceCount)(H3Index h3, int *out);
|
||||
|
||||
/** @brief Find all icosahedron faces intersected by a given H3 index */
|
||||
DECLSPEC H3Error H3_EXPORT(getIcosahedronFaces)(H3Index h3, int *out);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup areNeighborCells areNeighborCells
|
||||
* Functions for areNeighborCells
|
||||
* @{
|
||||
*/
|
||||
/** @brief returns whether or not the provided hexagons border */
|
||||
DECLSPEC H3Error H3_EXPORT(areNeighborCells)(H3Index origin,
|
||||
H3Index destination, int *out);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup cellsToDirectedEdge cellsToDirectedEdge
|
||||
* Functions for cellsToDirectedEdge
|
||||
* @{
|
||||
*/
|
||||
/** @brief returns the directed edge H3Index for the specified origin and
|
||||
* destination */
|
||||
DECLSPEC H3Error H3_EXPORT(cellsToDirectedEdge)(H3Index origin,
|
||||
H3Index destination,
|
||||
H3Index *out);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup isValidDirectedEdge isValidDirectedEdge
|
||||
* Functions for isValidDirectedEdge
|
||||
* @{
|
||||
*/
|
||||
/** @brief returns whether the H3Index is a valid directed edge */
|
||||
DECLSPEC int H3_EXPORT(isValidDirectedEdge)(H3Index edge);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup getDirectedEdgeOrigin \
|
||||
* getDirectedEdgeOrigin
|
||||
* Functions for getDirectedEdgeOrigin
|
||||
* @{
|
||||
*/
|
||||
/** @brief Returns the origin hexagon H3Index from the directed edge
|
||||
* H3Index */
|
||||
DECLSPEC H3Error H3_EXPORT(getDirectedEdgeOrigin)(H3Index edge, H3Index *out);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup getDirectedEdgeDestination \
|
||||
* getDirectedEdgeDestination
|
||||
* Functions for getDirectedEdgeDestination
|
||||
* @{
|
||||
*/
|
||||
/** @brief Returns the destination hexagon H3Index from the directed edge
|
||||
* H3Index */
|
||||
DECLSPEC H3Error H3_EXPORT(getDirectedEdgeDestination)(H3Index edge,
|
||||
H3Index *out);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup directedEdgeToCells \
|
||||
* directedEdgeToCells
|
||||
* Functions for directedEdgeToCells
|
||||
* @{
|
||||
*/
|
||||
/** @brief Returns the origin and destination hexagons from the directed
|
||||
* edge H3Index */
|
||||
DECLSPEC H3Error H3_EXPORT(directedEdgeToCells)(H3Index edge,
|
||||
H3Index *originDestination);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup originToDirectedEdges \
|
||||
* originToDirectedEdges
|
||||
* Functions for originToDirectedEdges
|
||||
* @{
|
||||
*/
|
||||
/** @brief Returns the 6 (or 5 for pentagons) edges associated with the H3Index
|
||||
*/
|
||||
DECLSPEC H3Error H3_EXPORT(originToDirectedEdges)(H3Index origin,
|
||||
H3Index *edges);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup directedEdgeToBoundary directedEdgeToBoundary
|
||||
* Functions for directedEdgeToBoundary
|
||||
* @{
|
||||
*/
|
||||
/** @brief Returns the CellBoundary containing the coordinates of the edge */
|
||||
DECLSPEC H3Error H3_EXPORT(directedEdgeToBoundary)(H3Index edge,
|
||||
CellBoundary *gb);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup cellToVertex cellToVertex
|
||||
* Functions for cellToVertex
|
||||
* @{
|
||||
*/
|
||||
/** @brief Returns a single vertex for a given cell, as an H3 index */
|
||||
DECLSPEC H3Error H3_EXPORT(cellToVertex)(H3Index origin, int vertexNum,
|
||||
H3Index *out);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup cellToVertexes cellToVertexes
|
||||
* Functions for cellToVertexes
|
||||
* @{
|
||||
*/
|
||||
/** @brief Returns all vertexes for a given cell, as H3 indexes */
|
||||
DECLSPEC H3Error H3_EXPORT(cellToVertexes)(H3Index origin, H3Index *vertexes);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup vertexToLatLng vertexToLatLng
|
||||
* Functions for vertexToLatLng
|
||||
* @{
|
||||
*/
|
||||
/** @brief Returns a single vertex for a given cell, as an H3 index */
|
||||
DECLSPEC H3Error H3_EXPORT(vertexToLatLng)(H3Index vertex, LatLng *point);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup isValidVertex isValidVertex
|
||||
* Functions for isValidVertex
|
||||
* @{
|
||||
*/
|
||||
/** @brief Whether the input is a valid H3 vertex */
|
||||
DECLSPEC int H3_EXPORT(isValidVertex)(H3Index vertex);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup gridDistance gridDistance
|
||||
* Functions for gridDistance
|
||||
* @{
|
||||
*/
|
||||
/** @brief Returns grid distance between two indexes */
|
||||
DECLSPEC H3Error H3_EXPORT(gridDistance)(H3Index origin, H3Index h3,
|
||||
int64_t *distance);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup gridPathCells gridPathCells
|
||||
* Functions for gridPathCells
|
||||
* @{
|
||||
*/
|
||||
/** @brief Number of indexes in a line connecting two indexes */
|
||||
DECLSPEC H3Error H3_EXPORT(gridPathCellsSize)(H3Index start, H3Index end,
|
||||
int64_t *size);
|
||||
|
||||
/** @brief Line of h3 indexes connecting two indexes */
|
||||
DECLSPEC H3Error H3_EXPORT(gridPathCells)(H3Index start, H3Index end,
|
||||
H3Index *out);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup cellToLocalIj cellToLocalIj
|
||||
* Functions for cellToLocalIj
|
||||
* @{
|
||||
*/
|
||||
/** @brief Returns two dimensional coordinates for the given index */
|
||||
DECLSPEC H3Error H3_EXPORT(cellToLocalIj)(H3Index origin, H3Index h3,
|
||||
uint32_t mode, CoordIJ *out);
|
||||
/** @} */
|
||||
|
||||
/** @defgroup localIjToCell localIjToCell
|
||||
* Functions for localIjToCell
|
||||
* @{
|
||||
*/
|
||||
/** @brief Returns index for the given two dimensional coordinates */
|
||||
DECLSPEC H3Error H3_EXPORT(localIjToCell)(H3Index origin, const CoordIJ *ij,
|
||||
uint32_t mode, H3Index *out);
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+193
@@ -0,0 +1,193 @@
|
||||
# cython: c_string_type=unicode, c_string_encoding=utf8
|
||||
from cpython cimport bool
|
||||
from libc.stdint cimport uint32_t, uint64_t, int64_t
|
||||
|
||||
ctypedef object H3str
|
||||
|
||||
cdef extern from 'h3api.h':
|
||||
cdef int H3_VERSION_MAJOR
|
||||
cdef int H3_VERSION_MINOR
|
||||
cdef int H3_VERSION_PATCH
|
||||
|
||||
ctypedef uint64_t H3int 'H3Index'
|
||||
|
||||
ctypedef uint32_t H3Error
|
||||
ctypedef enum H3ErrorCodes:
|
||||
E_SUCCESS = 0
|
||||
E_FAILED = 1
|
||||
E_DOMAIN = 2
|
||||
E_LATLNG_DOMAIN = 3
|
||||
E_RES_DOMAIN = 4
|
||||
E_CELL_INVALID = 5
|
||||
E_DIR_EDGE_INVALID = 6
|
||||
E_UNDIR_EDGE_INVALID = 7
|
||||
E_VERTEX_INVALID = 8
|
||||
E_PENTAGON = 9
|
||||
E_DUPLICATE_INPUT = 10
|
||||
E_NOT_NEIGHBORS = 11
|
||||
E_RES_MISMATCH = 12
|
||||
E_MEMORY_ALLOC = 13
|
||||
E_MEMORY_BOUNDS = 14
|
||||
E_OPTION_INVALID = 15
|
||||
|
||||
ctypedef struct LatLng:
|
||||
double lat # in radians
|
||||
double lng # in radians
|
||||
|
||||
ctypedef struct CellBoundary:
|
||||
int num_verts 'numVerts'
|
||||
LatLng verts[10] # MAX_CELL_BNDRY_VERTS
|
||||
|
||||
ctypedef struct CoordIJ:
|
||||
int i
|
||||
int j
|
||||
|
||||
ctypedef struct LinkedLatLng:
|
||||
LatLng data 'vertex'
|
||||
LinkedLatLng *next
|
||||
|
||||
# renaming these for clarity
|
||||
ctypedef struct LinkedGeoLoop:
|
||||
LinkedLatLng *data 'first'
|
||||
LinkedLatLng *_data_last 'last' # not needed in Cython bindings
|
||||
LinkedGeoLoop *next
|
||||
|
||||
ctypedef struct LinkedGeoPolygon:
|
||||
LinkedGeoLoop *data 'first'
|
||||
LinkedGeoLoop *_data_last 'last' # not needed in Cython bindings
|
||||
LinkedGeoPolygon *next
|
||||
|
||||
ctypedef struct GeoLoop:
|
||||
int numVerts
|
||||
LatLng *verts
|
||||
|
||||
ctypedef struct GeoPolygon:
|
||||
GeoLoop geoloop
|
||||
int numHoles
|
||||
GeoLoop *holes
|
||||
|
||||
int isValidCell(H3int h) nogil
|
||||
int isPentagon(H3int h) nogil
|
||||
int isResClassIII(H3int h) nogil
|
||||
int isValidDirectedEdge(H3int edge) nogil
|
||||
int isValidVertex(H3int v) nogil
|
||||
|
||||
double degsToRads(double degrees) nogil
|
||||
double radsToDegs(double radians) nogil
|
||||
|
||||
int getResolution(H3int h) nogil
|
||||
int getBaseCellNumber(H3int h) nogil
|
||||
|
||||
H3Error latLngToCell(const LatLng *g, int res, H3int *out) nogil
|
||||
H3Error cellToLatLng(H3int h, LatLng *) nogil
|
||||
H3Error gridDistance(H3int h1, H3int h2, int64_t *distance) nogil
|
||||
|
||||
H3Error cellToVertex(H3int cell, int vertexNum, H3int *out) nogil
|
||||
H3Error cellToVertexes(H3int cell, H3int *vertexes) nogil
|
||||
H3Error vertexToLatLng(H3int vertex, LatLng *coord) nogil
|
||||
|
||||
H3Error maxGridDiskSize(int k, int64_t *out) nogil # num/out/N?
|
||||
H3Error gridDisk(H3int h, int k, H3int *out) nogil
|
||||
|
||||
H3Error cellToParent( H3int h, int parentRes, H3int *parent) nogil
|
||||
H3Error cellToCenterChild(H3int h, int childRes, H3int *child) nogil
|
||||
H3Error cellToChildPos(H3int child, int parentRes, int64_t *out) nogil
|
||||
H3Error childPosToCell(int64_t childPos, H3int parent, int childRes, H3int *child) nogil
|
||||
|
||||
H3Error cellToChildrenSize(H3int h, int childRes, int64_t *num) nogil # num/out/N?
|
||||
H3Error cellToChildren( H3int h, int childRes, H3int *children) nogil
|
||||
|
||||
H3Error compactCells(
|
||||
const H3int *cells_u,
|
||||
H3int *cells_c,
|
||||
const int num_u
|
||||
) nogil
|
||||
H3Error uncompactCellsSize(
|
||||
const H3int *cells_c,
|
||||
const int64_t num_c,
|
||||
const int res,
|
||||
int64_t *num_u
|
||||
) nogil
|
||||
H3Error uncompactCells(
|
||||
const H3int *cells_c,
|
||||
const int num_c,
|
||||
H3int *cells_u,
|
||||
const int num_u,
|
||||
const int res
|
||||
) nogil
|
||||
|
||||
H3Error getNumCells(int res, int64_t *out) nogil
|
||||
int pentagonCount() nogil
|
||||
int res0CellCount() nogil
|
||||
H3Error getPentagons(int res, H3int *out) nogil
|
||||
H3Error getRes0Cells(H3int *out) nogil
|
||||
|
||||
H3Error gridPathCellsSize(H3int start, H3int end, int64_t *size) nogil
|
||||
H3Error gridPathCells(H3int start, H3int end, H3int *out) nogil
|
||||
|
||||
H3Error getHexagonAreaAvgKm2(int res, double *out) nogil
|
||||
H3Error getHexagonAreaAvgM2(int res, double *out) nogil
|
||||
|
||||
H3Error cellAreaRads2(H3int h, double *out) nogil
|
||||
H3Error cellAreaKm2(H3int h, double *out) nogil
|
||||
H3Error cellAreaM2(H3int h, double *out) nogil
|
||||
|
||||
H3Error maxFaceCount(H3int h, int *out) nogil
|
||||
H3Error getIcosahedronFaces(H3int h3, int *out) nogil
|
||||
|
||||
H3Error cellToLocalIj(H3int origin, H3int h3, uint32_t mode, CoordIJ *out) nogil
|
||||
H3Error localIjToCell(H3int origin, const CoordIJ *ij, uint32_t mode, H3int *out) nogil
|
||||
|
||||
H3Error gridDiskDistances(H3int origin, int k, H3int *out, int *distances) nogil
|
||||
H3Error gridRing(H3int origin, int k, H3int *out) nogil
|
||||
H3Error gridRingUnsafe(H3int origin, int k, H3int *out) nogil
|
||||
|
||||
H3Error areNeighborCells(H3int origin, H3int destination, int *out) nogil
|
||||
H3Error cellsToDirectedEdge(H3int origin, H3int destination, H3int *out) nogil
|
||||
H3Error getDirectedEdgeOrigin(H3int edge, H3int *out) nogil
|
||||
H3Error getDirectedEdgeDestination(H3int edge, H3int *out) nogil
|
||||
H3Error originToDirectedEdges(H3int origin, H3int *edges) nogil
|
||||
# todo: directedEdgeToCells
|
||||
|
||||
H3Error getHexagonEdgeLengthAvgKm(int res, double *out) nogil
|
||||
H3Error getHexagonEdgeLengthAvgM(int res, double *out) nogil
|
||||
|
||||
H3Error edgeLengthRads(H3int edge, double *out) nogil
|
||||
H3Error edgeLengthKm(H3int edge, double *out) nogil
|
||||
H3Error edgeLengthM(H3int edge, double *out) nogil
|
||||
|
||||
H3Error cellToBoundary(H3int h3, CellBoundary *gp) nogil
|
||||
H3Error directedEdgeToBoundary(H3int edge, CellBoundary *gb) nogil
|
||||
|
||||
double greatCircleDistanceRads(const LatLng *a, const LatLng *b) nogil
|
||||
double greatCircleDistanceKm(const LatLng *a, const LatLng *b) nogil
|
||||
double greatCircleDistanceM(const LatLng *a, const LatLng *b) nogil
|
||||
|
||||
H3Error cellsToLinkedMultiPolygon(const H3int *h3Set, const int numCells, LinkedGeoPolygon *out)
|
||||
void destroyLinkedMultiPolygon(LinkedGeoPolygon *polygon)
|
||||
|
||||
H3Error maxPolygonToCellsSize(const GeoPolygon *geoPolygon, int res, uint32_t flags, uint64_t *count)
|
||||
H3Error polygonToCells(const GeoPolygon *geoPolygon, int res, uint32_t flags, H3int *out)
|
||||
|
||||
H3Error maxPolygonToCellsSizeExperimental(const GeoPolygon *geoPolygon, int res, uint32_t flags, uint64_t *count)
|
||||
H3Error polygonToCellsExperimental(const GeoPolygon *geoPolygon, int res, uint32_t flags, uint64_t sz, H3int *out)
|
||||
|
||||
# ctypedef struct GeoMultiPolygon:
|
||||
# int numPolygons
|
||||
# GeoPolygon *polygons
|
||||
|
||||
# int hexRange(H3int origin, int k, H3int *out)
|
||||
|
||||
# int hexRangeDistances(H3int origin, int k, H3int *out, int *distances)
|
||||
|
||||
# int hexRanges(H3int *h3Set, int length, int k, H3int *out)
|
||||
|
||||
# void h3SetToLinkedGeo(const H3int *h3Set, const int numCells, LinkedGeoPolygon *out)
|
||||
|
||||
# void destroyLinkedPolygon(LinkedGeoPolygon *polygon)
|
||||
|
||||
# H3int stringToH3(const char *str)
|
||||
|
||||
# void h3ToString(H3int h, char *str, size_t sz)
|
||||
|
||||
# void getH3intesFromUnidirectionalEdge(H3int edge, H3int *originDestination)
|
||||
Binary file not shown.
+7
@@ -0,0 +1,7 @@
|
||||
from .h3lib cimport H3int
|
||||
|
||||
cpdef H3int latlng_to_cell(double lat, double lng, int res) except 1
|
||||
cpdef (double, double) cell_to_latlng(H3int h) except *
|
||||
cpdef double great_circle_distance(
|
||||
double lat1, double lng1,
|
||||
double lat2, double lng2, unit=*) except -1
|
||||
+325
@@ -0,0 +1,325 @@
|
||||
from libc.stdint cimport uint64_t
|
||||
|
||||
cimport h3lib
|
||||
from h3lib cimport bool, H3int
|
||||
|
||||
from .util cimport (
|
||||
check_cell,
|
||||
check_edge,
|
||||
check_res,
|
||||
deg2coord,
|
||||
coord2deg
|
||||
)
|
||||
|
||||
from .error_system cimport check_for_error
|
||||
|
||||
from .memory cimport H3MemoryManager
|
||||
|
||||
# TODO: We might be OK with taking the GIL for the functions in this module
|
||||
from libc.stdlib cimport (
|
||||
# malloc as h3_malloc, # not used
|
||||
calloc as h3_calloc,
|
||||
realloc as h3_realloc,
|
||||
free as h3_free,
|
||||
)
|
||||
|
||||
|
||||
cpdef H3int latlng_to_cell(double lat, double lng, int res) except 1:
|
||||
cdef:
|
||||
h3lib.LatLng c
|
||||
H3int out
|
||||
|
||||
c = deg2coord(lat, lng)
|
||||
|
||||
check_for_error(
|
||||
h3lib.latLngToCell(&c, res, &out)
|
||||
)
|
||||
|
||||
return out
|
||||
|
||||
|
||||
cpdef (double, double) cell_to_latlng(H3int h) except *:
|
||||
"""Map an H3 cell into its centroid geo-coordinate (lat/lng)"""
|
||||
cdef:
|
||||
h3lib.LatLng c
|
||||
|
||||
check_cell(h)
|
||||
# todo: think about: if you give this an invalid cell, should it still return a lat/lng?
|
||||
# idea: safe and unsafe APIs?
|
||||
|
||||
check_for_error(
|
||||
h3lib.cellToLatLng(h, &c)
|
||||
)
|
||||
|
||||
return coord2deg(c)
|
||||
|
||||
|
||||
cdef h3lib.GeoLoop make_geoloop(latlngs) except *:
|
||||
"""
|
||||
The returned `GeoLoop` must be freed with a call to `free_geoloop`.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
latlngs : list or tuple
|
||||
GeoLoop: A sequence of >= 3 (lat, lng) pairs where the last
|
||||
element may or may not be same as the first (to form a closed loop).
|
||||
The order of the pairs may be either clockwise or counterclockwise.
|
||||
"""
|
||||
cdef:
|
||||
h3lib.GeoLoop gl
|
||||
|
||||
gl.numVerts = len(latlngs)
|
||||
|
||||
# todo: need for memory management
|
||||
# can automatically free?
|
||||
gl.verts = <h3lib.LatLng*> h3_calloc(gl.numVerts, sizeof(h3lib.LatLng))
|
||||
|
||||
for i, (lat, lng) in enumerate(latlngs):
|
||||
gl.verts[i] = deg2coord(lat, lng)
|
||||
|
||||
return gl
|
||||
|
||||
|
||||
cdef free_geoloop(h3lib.GeoLoop* gl):
|
||||
h3_free(gl.verts)
|
||||
gl.verts = NULL
|
||||
|
||||
|
||||
cdef class GeoPolygon:
|
||||
cdef:
|
||||
h3lib.GeoPolygon gp
|
||||
|
||||
def __cinit__(self, outer, holes=None):
|
||||
"""
|
||||
|
||||
Parameters
|
||||
----------
|
||||
outer : list or tuple
|
||||
GeoLoop
|
||||
A GeoLoop is a sequence of >= 3 (lat, lng) pairs where the last
|
||||
element may or may not be same as the first (to form a closed loop).
|
||||
The order of the pairs may be either clockwise or counterclockwise.
|
||||
holes : list or tuple
|
||||
A sequence of GeoLoops
|
||||
"""
|
||||
if holes is None:
|
||||
holes = []
|
||||
|
||||
self.gp.geoloop = make_geoloop(outer)
|
||||
self.gp.numHoles = len(holes)
|
||||
self.gp.holes = NULL
|
||||
|
||||
if len(holes) > 0:
|
||||
self.gp.holes = <h3lib.GeoLoop*> h3_calloc(len(holes), sizeof(h3lib.GeoLoop))
|
||||
for i, hole in enumerate(holes):
|
||||
self.gp.holes[i] = make_geoloop(hole)
|
||||
|
||||
|
||||
def __dealloc__(self):
|
||||
free_geoloop(&self.gp.geoloop)
|
||||
|
||||
for i in range(self.gp.numHoles):
|
||||
free_geoloop(&self.gp.holes[i])
|
||||
|
||||
h3_free(self.gp.holes)
|
||||
|
||||
|
||||
def polygon_to_cells(outer, int res, holes=None):
|
||||
""" Get the set of cells whose center is contained in a polygon.
|
||||
|
||||
The polygon is defined similarity to the GeoJson standard, with an exterior
|
||||
`outer` ring of lat/lng points, and a list of `holes`, each of which are also
|
||||
rings of lat/lng points.
|
||||
|
||||
Each ring may be in clockwise or counter-clockwise order
|
||||
(right-hand rule or not), and may or may not be a closed loop (where the last
|
||||
element is equal to the first).
|
||||
The GeoJSON spec requires the right-hand rule and a closed loop, but
|
||||
this function relaxes those constraints.
|
||||
|
||||
Unlike the GeoJson standard, the elements of the lat/lng pairs of each
|
||||
ring are in lat/lng order, instead of lng/lat order.
|
||||
|
||||
We'll handle translation to different formats in the Python code,
|
||||
rather than the Cython code.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
outer : list or tuple
|
||||
A ring given by a sequence of lat/lng pairs.
|
||||
res : int
|
||||
The resolution of the output hexagons
|
||||
holes : list or tuple
|
||||
A collection of rings, each given by a sequence of lat/lng pairs.
|
||||
These describe any the "holes" in the polygon.
|
||||
"""
|
||||
cdef:
|
||||
uint64_t n
|
||||
|
||||
check_res(res)
|
||||
|
||||
if not outer:
|
||||
return H3MemoryManager(0).to_mv()
|
||||
|
||||
gp = GeoPolygon(outer, holes=holes)
|
||||
|
||||
check_for_error(
|
||||
h3lib.maxPolygonToCellsSize(&gp.gp, res, 0, &n)
|
||||
)
|
||||
|
||||
hmm = H3MemoryManager(n)
|
||||
check_for_error(
|
||||
h3lib.polygonToCells(&gp.gp, res, 0, hmm.ptr)
|
||||
)
|
||||
mv = hmm.to_mv()
|
||||
|
||||
return mv
|
||||
|
||||
|
||||
def polygons_to_cells(polygons, int res):
|
||||
mvs = [
|
||||
polygon_to_cells(outer=poly.outer, res=res, holes=poly.holes)
|
||||
for poly in polygons
|
||||
]
|
||||
|
||||
n = sum(map(len, mvs))
|
||||
hmm = H3MemoryManager(n)
|
||||
|
||||
# probably super inefficient, but it is working!
|
||||
# tood: move this to C
|
||||
k = 0
|
||||
for mv in mvs:
|
||||
for v in mv:
|
||||
hmm.ptr[k] = v
|
||||
k += 1
|
||||
|
||||
return hmm.to_mv()
|
||||
|
||||
|
||||
def polygon_to_cells_experimental(outer, int res, int flag, holes=None):
|
||||
""" Get the set of cells whose center is contained in a polygon.
|
||||
|
||||
The polygon is defined similarity to the GeoJson standard, with an exterior
|
||||
`outer` ring of lat/lng points, and a list of `holes`, each of which are also
|
||||
rings of lat/lng points.
|
||||
|
||||
Each ring may be in clockwise or counter-clockwise order
|
||||
(right-hand rule or not), and may or may not be a closed loop (where the last
|
||||
element is equal to the first).
|
||||
The GeoJSON spec requires the right-hand rule and a closed loop, but
|
||||
this function relaxes those constraints.
|
||||
|
||||
Unlike the GeoJson standard, the elements of the lat/lng pairs of each
|
||||
ring are in lat/lng order, instead of lng/lat order.
|
||||
|
||||
We'll handle translation to different formats in the Python code,
|
||||
rather than the Cython code.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
outer : list or tuple
|
||||
A ring given by a sequence of lat/lng pairs.
|
||||
res : int
|
||||
The resolution of the output hexagons
|
||||
flag : int
|
||||
Polygon to cells flag, such as containment mode.
|
||||
holes : list or tuple
|
||||
A collection of rings, each given by a sequence of lat/lng pairs.
|
||||
These describe any the "holes" in the polygon.
|
||||
"""
|
||||
cdef:
|
||||
uint64_t n
|
||||
|
||||
check_res(res)
|
||||
|
||||
if not outer:
|
||||
return H3MemoryManager(0).to_mv()
|
||||
|
||||
gp = GeoPolygon(outer, holes=holes)
|
||||
|
||||
check_for_error(
|
||||
h3lib.maxPolygonToCellsSizeExperimental(&gp.gp, res, flag, &n)
|
||||
)
|
||||
|
||||
hmm = H3MemoryManager(n)
|
||||
check_for_error(
|
||||
h3lib.polygonToCellsExperimental(&gp.gp, res, flag, n, hmm.ptr)
|
||||
)
|
||||
mv = hmm.to_mv()
|
||||
|
||||
return mv
|
||||
|
||||
|
||||
def polygons_to_cells_experimental(polygons, int res, int flag):
|
||||
mvs = [
|
||||
polygon_to_cells_experimental(outer=poly.outer, res=res, holes=poly.holes, flag=flag)
|
||||
for poly in polygons
|
||||
]
|
||||
|
||||
n = sum(map(len, mvs))
|
||||
hmm = H3MemoryManager(n)
|
||||
|
||||
# probably super inefficient, but it is working!
|
||||
# tood: move this to C
|
||||
k = 0
|
||||
for mv in mvs:
|
||||
for v in mv:
|
||||
hmm.ptr[k] = v
|
||||
k += 1
|
||||
|
||||
return hmm.to_mv()
|
||||
|
||||
|
||||
def cell_to_boundary(H3int h):
|
||||
"""Compose an array of geo-coordinates that outlines a hexagonal cell"""
|
||||
cdef:
|
||||
h3lib.CellBoundary gb
|
||||
|
||||
check_cell(h)
|
||||
|
||||
h3lib.cellToBoundary(h, &gb)
|
||||
|
||||
verts = tuple(
|
||||
coord2deg(gb.verts[i])
|
||||
for i in range(gb.num_verts)
|
||||
)
|
||||
|
||||
return verts
|
||||
|
||||
|
||||
def directed_edge_to_boundary(H3int edge):
|
||||
""" Returns the CellBoundary containing the coordinates of the edge
|
||||
"""
|
||||
cdef:
|
||||
h3lib.CellBoundary gb
|
||||
|
||||
check_edge(edge)
|
||||
|
||||
h3lib.directedEdgeToBoundary(edge, &gb)
|
||||
|
||||
# todo: move this verts transform into the CellBoundary object
|
||||
verts = tuple(
|
||||
coord2deg(gb.verts[i])
|
||||
for i in range(gb.num_verts)
|
||||
)
|
||||
|
||||
return verts
|
||||
|
||||
|
||||
cpdef double great_circle_distance(
|
||||
double lat1, double lng1,
|
||||
double lat2, double lng2, unit='km') except -1:
|
||||
|
||||
a = deg2coord(lat1, lng1)
|
||||
b = deg2coord(lat2, lng2)
|
||||
|
||||
if unit == 'rads':
|
||||
d = h3lib.greatCircleDistanceRads(&a, &b)
|
||||
elif unit == 'km':
|
||||
d = h3lib.greatCircleDistanceKm(&a, &b)
|
||||
elif unit == 'm':
|
||||
d = h3lib.greatCircleDistanceM(&a, &b)
|
||||
else:
|
||||
raise ValueError('Unknown unit: {}'.format(unit))
|
||||
|
||||
return d
|
||||
Binary file not shown.
+12
@@ -0,0 +1,12 @@
|
||||
from .h3lib cimport H3int
|
||||
|
||||
cdef class H3MemoryManager:
|
||||
cdef:
|
||||
size_t n
|
||||
H3int* ptr
|
||||
|
||||
cdef H3int[:] to_mv(self)
|
||||
cdef H3int[:] to_mv_keep_zeros(self)
|
||||
|
||||
cdef int[:] int_mv(size_t n)
|
||||
cpdef H3int[:] iter_to_mv(cells)
|
||||
+248
@@ -0,0 +1,248 @@
|
||||
from cython.view cimport array
|
||||
from .h3lib cimport H3int
|
||||
|
||||
"""
|
||||
### Memory allocation options
|
||||
|
||||
We have a few options for the memory allocation functions.
|
||||
There's a trade-off between using the Python allocators which let Python
|
||||
track memory usage and offers some optimizations vs the system
|
||||
allocators, which do not need to acquire the GIL.
|
||||
"""
|
||||
|
||||
"""
|
||||
System allocation functions. These do not acquire the GIL.
|
||||
"""
|
||||
from libc.stdlib cimport (
|
||||
# malloc as h3_malloc, # not used
|
||||
calloc as h3_calloc,
|
||||
realloc as h3_realloc,
|
||||
free as h3_free,
|
||||
)
|
||||
|
||||
|
||||
"""
|
||||
PyMem_Raw* functions should just be wrappers around system allocators
|
||||
also given in libc.stdlib. These functions do not acquire the GIL.
|
||||
|
||||
Note that these do not have a calloc function until py 3.5 and Cython 3.0,
|
||||
so we would need to zero-out memory manually.
|
||||
|
||||
https://python.readthedocs.io/en/stable/c-api/memory.html#raw-memory-interface
|
||||
"""
|
||||
# from cpython.mem cimport (
|
||||
# PyMem_RawMalloc as h3_malloc,
|
||||
# # PyMem_RawCalloc as h3_calloc, # only in Python >=3.5 (and Cython >=3.0?)
|
||||
# PyMem_RawRealloc as h3_realloc,
|
||||
# PyMem_RawFree as h3_free,
|
||||
# )
|
||||
|
||||
|
||||
"""
|
||||
These functions use the Python allocator (instead of the system allocator),
|
||||
which offers some optimizations for Python, and allows Python to track
|
||||
memory usage. However, these functions must acquire the GIL.
|
||||
|
||||
Note that these do not have a calloc function until py 3.5 and Cython 3.0,
|
||||
so we would need to zero-out memory manually.
|
||||
|
||||
https://cython.readthedocs.io/en/stable/src/tutorial/memory_allocation.html
|
||||
https://python.readthedocs.io/en/stable/c-api/memory.html#memory-interface
|
||||
"""
|
||||
# from cpython.mem cimport (
|
||||
# PyMem_Malloc as h3_malloc,
|
||||
# # PyMem_Calloc as h3_calloc, # only in Python >=3.5 (and Cython >=3.0?)
|
||||
# PyMem_Realloc as h3_realloc,
|
||||
# PyMem_Free as h3_free,
|
||||
# )
|
||||
|
||||
|
||||
cdef size_t move_nonzeros(H3int* a, size_t n):
|
||||
""" Move nonzero elements to front of array `a` of length `n`.
|
||||
Return the number of nonzero elements.
|
||||
|
||||
Loop invariant: Everything *before* `i` or *after* `j` is "done".
|
||||
Move `i` and `j` inwards until they equal, and exit.
|
||||
You can move `i` forward until there's a zero in front of it.
|
||||
You can move `j` backward until there's a nonzero to the left of it.
|
||||
Anything to the right of `j` is "junk" that can be reallocated.
|
||||
|
||||
| a | b | 0 | c | d | ... |
|
||||
^ ^
|
||||
i j
|
||||
|
||||
|
||||
| a | b | d | c | d | ... |
|
||||
^ ^
|
||||
i j
|
||||
"""
|
||||
cdef:
|
||||
size_t i = 0
|
||||
size_t j = n
|
||||
|
||||
while i < j:
|
||||
if a[j-1] == 0:
|
||||
j -= 1
|
||||
continue
|
||||
|
||||
if a[i] != 0:
|
||||
i += 1
|
||||
continue
|
||||
|
||||
# if we're here, we know:
|
||||
# a[i] == 0
|
||||
# a[j-1] != 0
|
||||
# i < j
|
||||
# so we can swap! (actually, move a[j-1] -> a[i])
|
||||
a[i] = a[j-1]
|
||||
j -= 1
|
||||
|
||||
return i
|
||||
|
||||
|
||||
cdef H3int[:] empty_memory_view():
|
||||
# todo: get rid of this?
|
||||
# there's gotta be a better way to do this...
|
||||
# create an empty cython.view.array?
|
||||
cdef:
|
||||
H3int a[1]
|
||||
|
||||
return (<H3int[:]>a)[:0]
|
||||
|
||||
|
||||
cdef _remove_zeros(H3MemoryManager x):
|
||||
x.n = move_nonzeros(x.ptr, x.n)
|
||||
|
||||
if x.n == 0:
|
||||
h3_free(x.ptr)
|
||||
x.ptr = NULL
|
||||
else:
|
||||
x.ptr = <H3int*> h3_realloc(x.ptr, x.n*sizeof(H3int))
|
||||
if not x.ptr:
|
||||
raise MemoryError()
|
||||
|
||||
|
||||
cdef H3int[:] _copy_to_mv(const H3int* ptr, size_t n):
|
||||
cdef:
|
||||
array arr
|
||||
|
||||
arr = <H3int[:n]> ptr
|
||||
arr.callback_free_data = h3_free
|
||||
|
||||
return arr
|
||||
|
||||
|
||||
cdef H3int[:] _create_mv(H3MemoryManager x):
|
||||
if x.n == 0:
|
||||
h3_free(x.ptr)
|
||||
x.ptr = NULL
|
||||
mv = empty_memory_view()
|
||||
else:
|
||||
mv = _copy_to_mv(x.ptr, x.n)
|
||||
|
||||
# responsibility for the memory moves from this object to the array/memoryview
|
||||
x.ptr = NULL
|
||||
x.n = 0
|
||||
|
||||
return mv
|
||||
|
||||
|
||||
"""
|
||||
TODO: The not None declaration for the argument automatically rejects None values as input, which would otherwise be allowed. The reason why None is allowed by default is that it is conveniently used for return arguments:
|
||||
https://cython.readthedocs.io/en/latest/src/userguide/memoryviews.html#syntax
|
||||
|
||||
TODO: potential optimization: https://cython.readthedocs.io/en/latest/src/userguide/memoryviews.html#performance-disabling-initialization-checks
|
||||
|
||||
## future improvements:
|
||||
|
||||
- abolish any appearance of &thing[0]. (i.e., identical interfaces)
|
||||
- can i make the interface for all these memory views identical?
|
||||
"""
|
||||
|
||||
cdef class H3MemoryManager:
|
||||
"""
|
||||
Cython object in charge of allocating and freeing memory for arrays
|
||||
of H3 indexes.
|
||||
|
||||
Initially allocates memory and provides access through `self.ptr` and
|
||||
`self.n`.
|
||||
|
||||
The `to_mv()` function removes responsibility for the allocated memory
|
||||
from this object to a memory view object. A memory view object automatically
|
||||
deallocates its memory during garbage collection.
|
||||
|
||||
If the H3MemoryManager is garbage collected before running `to_mv()`,
|
||||
it will deallocate its memory itself.
|
||||
|
||||
This pattern is useful for a few reasons:
|
||||
|
||||
- provide convenient access to the raw memory pointer and length for passing
|
||||
to h3lib functions
|
||||
- remove zeroes from the array output (some h3lib functions may return
|
||||
results with zeros/H3NULL values)
|
||||
- cython and python array types have weird interfaces; memoryviews are
|
||||
much cleaner
|
||||
|
||||
If we find a better way to do these then this class may no longer be
|
||||
necessary.
|
||||
|
||||
TODO: consider a context manager pattern
|
||||
"""
|
||||
def __cinit__(self, size_t n):
|
||||
self.n = n
|
||||
self.ptr = <H3int*> h3_calloc(self.n, sizeof(H3int))
|
||||
|
||||
if not self.ptr:
|
||||
raise MemoryError()
|
||||
|
||||
cdef H3int[:] to_mv_keep_zeros(self):
|
||||
# todo: this could be a private method
|
||||
return _create_mv(self)
|
||||
|
||||
cdef H3int[:] to_mv(self):
|
||||
_remove_zeros(self)
|
||||
return _create_mv(self)
|
||||
|
||||
def __dealloc__(self):
|
||||
# If the memory has been handed off to a memoryview, this pointer
|
||||
# should be NULL, and deallocing on NULL is fine.
|
||||
# If the pointer is *not* NULL, then this means the MemoryManager
|
||||
# has is still responsible for the memory (it hasn't given the memory away to another object).
|
||||
h3_free(self.ptr)
|
||||
|
||||
|
||||
"""
|
||||
todo: combine with the H3MemoryManager using fused types?
|
||||
https://cython.readthedocs.io/en/stable/src/userguide/fusedtypes.html
|
||||
"""
|
||||
cdef int[:] int_mv(size_t n):
|
||||
cdef:
|
||||
array arr
|
||||
|
||||
if n == 0:
|
||||
raise MemoryError()
|
||||
else:
|
||||
ptr = <int*> h3_calloc(n, sizeof(int))
|
||||
if ptr is NULL:
|
||||
raise MemoryError()
|
||||
|
||||
arr = <int[:n]> ptr
|
||||
arr.callback_free_data = h3_free
|
||||
|
||||
return arr
|
||||
|
||||
|
||||
cpdef H3int[:] iter_to_mv(cells):
|
||||
""" cells needs to be an iterable that knows its size...
|
||||
or should we have it match the np.fromiter function, which infers if not available?
|
||||
"""
|
||||
cdef:
|
||||
H3int[:] mv
|
||||
|
||||
n = len(cells)
|
||||
mv = H3MemoryManager(n).to_mv_keep_zeros()
|
||||
|
||||
for i,h in enumerate(cells):
|
||||
mv[i] = h
|
||||
|
||||
return mv
|
||||
Binary file not shown.
+60
@@ -0,0 +1,60 @@
|
||||
cimport h3lib
|
||||
from h3lib cimport H3int
|
||||
from .util cimport check_cell, coord2deg
|
||||
|
||||
|
||||
# todo: it's driving me crazy that these three functions are all essentially the same linked list walker...
|
||||
# grumble: no way to do iterators in with cdef functions!
|
||||
cdef walk_polys(const h3lib.LinkedGeoPolygon* L):
|
||||
out = []
|
||||
while L:
|
||||
out += [walk_loops(L.data)]
|
||||
L = L.next
|
||||
|
||||
return out
|
||||
|
||||
|
||||
cdef walk_loops(const h3lib.LinkedGeoLoop* L):
|
||||
out = []
|
||||
while L:
|
||||
out += [walk_coords(L.data)]
|
||||
L = L.next
|
||||
|
||||
return out
|
||||
|
||||
|
||||
cdef walk_coords(const h3lib.LinkedLatLng* L):
|
||||
out = []
|
||||
while L:
|
||||
out += [coord2deg(L.data)]
|
||||
L = L.next
|
||||
|
||||
return out
|
||||
|
||||
# todo: tuples instead of lists?
|
||||
def _to_multi_polygon(const H3int[:] cells):
|
||||
cdef:
|
||||
h3lib.LinkedGeoPolygon polygon
|
||||
|
||||
for h in cells:
|
||||
check_cell(h)
|
||||
|
||||
h3lib.cellsToLinkedMultiPolygon(&cells[0], len(cells), &polygon)
|
||||
|
||||
out = walk_polys(&polygon)
|
||||
|
||||
# we're still responsible for cleaning up the passed in `polygon`,
|
||||
# but not a problem here, since it is stack allocated
|
||||
h3lib.destroyLinkedMultiPolygon(&polygon)
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def cells_to_multi_polygon(const H3int[:] cells):
|
||||
# todo: gotta be a more elegant way to handle these...
|
||||
if len(cells) == 0:
|
||||
return []
|
||||
|
||||
multipoly = _to_multi_polygon(cells)
|
||||
|
||||
return multipoly
|
||||
Binary file not shown.
+13
@@ -0,0 +1,13 @@
|
||||
from .h3lib cimport H3int, H3str, LatLng
|
||||
|
||||
cdef LatLng deg2coord(double lat, double lng) nogil
|
||||
cdef (double, double) coord2deg(LatLng c) nogil
|
||||
|
||||
cpdef H3int str_to_int(H3str h) except? 0
|
||||
cpdef H3str int_to_str(H3int x)
|
||||
|
||||
cdef check_cell(H3int h)
|
||||
cdef check_edge(H3int e)
|
||||
cdef check_res(int res)
|
||||
cdef check_vertex(H3int v)
|
||||
cdef check_distance(int k)
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
from .h3lib cimport H3int, H3str, isValidCell, isValidDirectedEdge, isValidVertex
|
||||
|
||||
cimport h3lib
|
||||
|
||||
from .error_system import (
|
||||
H3ResDomainError,
|
||||
H3DomainError,
|
||||
H3DirEdgeInvalidError,
|
||||
H3CellInvalidError,
|
||||
H3VertexInvalidError
|
||||
)
|
||||
|
||||
cdef h3lib.LatLng deg2coord(double lat, double lng) nogil:
|
||||
cdef:
|
||||
h3lib.LatLng c
|
||||
|
||||
c.lat = h3lib.degsToRads(lat)
|
||||
c.lng = h3lib.degsToRads(lng)
|
||||
|
||||
return c
|
||||
|
||||
|
||||
cdef (double, double) coord2deg(h3lib.LatLng c) nogil:
|
||||
return (
|
||||
h3lib.radsToDegs(c.lat),
|
||||
h3lib.radsToDegs(c.lng)
|
||||
)
|
||||
|
||||
|
||||
cpdef basestring c_version():
|
||||
v = (
|
||||
h3lib.H3_VERSION_MAJOR,
|
||||
h3lib.H3_VERSION_MINOR,
|
||||
h3lib.H3_VERSION_PATCH,
|
||||
)
|
||||
|
||||
return '{}.{}.{}'.format(*v)
|
||||
|
||||
|
||||
cpdef H3int str_to_int(H3str h) except? 0:
|
||||
return int(h, 16)
|
||||
|
||||
|
||||
cpdef H3str int_to_str(H3int x):
|
||||
""" Convert H3 integer to hex string representation
|
||||
|
||||
Need to be careful in Python 2 because `hex(x)` may return a string
|
||||
with a trailing `L` character (denoting a "large" integer).
|
||||
The formatting approach below avoids this.
|
||||
|
||||
Also need to be careful about unicode/str differences.
|
||||
"""
|
||||
return '{:x}'.format(x)
|
||||
|
||||
|
||||
cdef check_cell(H3int h):
|
||||
""" Check if valid H3 "cell" (hexagon or pentagon).
|
||||
|
||||
Does not check if a valid H3 edge, for example.
|
||||
|
||||
Since this function is used by multiple interfaces (int or str),
|
||||
we want the error message to be informative to the user
|
||||
in either case.
|
||||
|
||||
We use the builtin `hex` function instead of `int_to_str` to
|
||||
prepend `0x` to indicate that this **integer** representation
|
||||
is incorrect, but in a format that is easily compared to
|
||||
`str` inputs.
|
||||
"""
|
||||
if isValidCell(h) == 0:
|
||||
raise H3CellInvalidError('Integer is not a valid H3 cell: {}'.format(hex(h)))
|
||||
|
||||
cdef check_edge(H3int e):
|
||||
if isValidDirectedEdge(e) == 0:
|
||||
raise H3DirEdgeInvalidError('Integer is not a valid H3 edge: {}'.format(hex(e)))
|
||||
|
||||
cdef check_vertex(H3int v):
|
||||
if isValidVertex(v) == 0:
|
||||
raise H3VertexInvalidError('Integer is not a valid H3 vertex: {}'.format(hex(v)))
|
||||
|
||||
cdef check_res(int res):
|
||||
if (res < 0) or (res > 15):
|
||||
raise H3ResDomainError(res)
|
||||
|
||||
cdef check_distance(int k):
|
||||
if k < 0:
|
||||
raise H3DomainError(
|
||||
'Grid distances must be nonnegative. Received: {}'.format(k)
|
||||
)
|
||||
Binary file not shown.
+6
@@ -0,0 +1,6 @@
|
||||
from .h3lib cimport bool, H3int
|
||||
|
||||
cpdef H3int cell_to_vertex(H3int h, int vertex_num) except 1
|
||||
cpdef H3int[:] cell_to_vertexes(H3int h)
|
||||
cpdef (double, double) vertex_to_latlng(H3int v) except *
|
||||
cpdef bool is_valid_vertex(H3int v)
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
cimport h3lib
|
||||
from h3lib cimport bool, H3int
|
||||
|
||||
from .util cimport (
|
||||
check_cell,
|
||||
check_vertex,
|
||||
coord2deg
|
||||
)
|
||||
|
||||
from .error_system cimport check_for_error
|
||||
|
||||
from .memory cimport H3MemoryManager
|
||||
|
||||
|
||||
cpdef H3int cell_to_vertex(H3int h, int vertex_num) except 1:
|
||||
cdef:
|
||||
H3int out
|
||||
|
||||
check_cell(h)
|
||||
|
||||
check_for_error(
|
||||
h3lib.cellToVertex(h, vertex_num, &out)
|
||||
)
|
||||
|
||||
return out
|
||||
|
||||
cpdef H3int[:] cell_to_vertexes(H3int h):
|
||||
cdef:
|
||||
H3int out
|
||||
|
||||
check_cell(h)
|
||||
|
||||
hmm = H3MemoryManager(6)
|
||||
check_for_error(
|
||||
h3lib.cellToVertexes(h, hmm.ptr)
|
||||
)
|
||||
mv = hmm.to_mv()
|
||||
|
||||
return mv
|
||||
|
||||
cpdef (double, double) vertex_to_latlng(H3int v) except *:
|
||||
cdef:
|
||||
h3lib.LatLng c
|
||||
|
||||
check_vertex(v)
|
||||
|
||||
check_for_error(
|
||||
h3lib.vertexToLatLng(v, &c)
|
||||
)
|
||||
|
||||
return coord2deg(c)
|
||||
|
||||
cpdef bool is_valid_vertex(H3int v):
|
||||
return h3lib.isValidVertex(v) == 1
|
||||
Vendored
+338
@@ -0,0 +1,338 @@
|
||||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
|
||||
class H3Shape(metaclass=ABCMeta):
|
||||
"""
|
||||
Abstract parent class of ``LatLngPoly`` and ``LatLngMultiPoly``.
|
||||
"""
|
||||
@property
|
||||
@abstractmethod
|
||||
def __geo_interface__(self):
|
||||
""" https://github.com/pytest-dev/pytest-cov/issues/428 """
|
||||
|
||||
|
||||
class LatLngPoly(H3Shape):
|
||||
"""
|
||||
Container for loops of lat/lng points describing a polygon, possibly with holes.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
outer : list[tuple[float, float]]
|
||||
List of lat/lng points describing the outer loop of the polygon
|
||||
|
||||
holes : list[list[tuple[float, float]]]
|
||||
List of loops of lat/lng points describing the holes of the polygon
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
A polygon with a single outer ring consisting of 4 points, having no holes:
|
||||
|
||||
>>> LatLngPoly(
|
||||
... [(37.68, -122.54), (37.68, -122.34), (37.82, -122.34), (37.82, -122.54)],
|
||||
... )
|
||||
<LatLngPoly: [4]>
|
||||
|
||||
The same polygon, but with one hole consisting of 3 points:
|
||||
|
||||
>>> LatLngPoly(
|
||||
... [(37.68, -122.54), (37.68, -122.34), (37.82, -122.34), (37.82, -122.54)],
|
||||
... [(37.76, -122.51), (37.76, -122.44), (37.81, -122.51)],
|
||||
... )
|
||||
<LatLngPoly: [4/(3,)]>
|
||||
|
||||
The same as above, but with one additional hole, made up of 5 points:
|
||||
|
||||
>>> LatLngPoly(
|
||||
... [(37.68, -122.54), (37.68, -122.34), (37.82, -122.34), (37.82, -122.54)],
|
||||
... [(37.76, -122.51), (37.76, -122.44), (37.81, -122.51)],
|
||||
... [(37.71, -122.43), (37.71, -122.37), (37.73, -122.37), (37.75, -122.41),
|
||||
... (37.73, -122.43)],
|
||||
... )
|
||||
<LatLngPoly: [4/(3, 5)]>
|
||||
"""
|
||||
def __init__(self, outer, *holes):
|
||||
loops = [outer] + list(holes)
|
||||
for loop in loops:
|
||||
if len(loop) in (1, 2):
|
||||
raise ValueError('Non-empty LatLngPoly loops need at least 3 points.')
|
||||
|
||||
point_dimensions = set(map(len, loop))
|
||||
# empty set is possible for empty polygons, so we check if a subset
|
||||
if not (point_dimensions <= {2}):
|
||||
raise ValueError('LatLngPoly only accepts 2D points: lat/lng.')
|
||||
|
||||
self.outer = tuple(_open_ring(outer))
|
||||
self.holes = tuple(
|
||||
_open_ring(hole)
|
||||
for hole in holes
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return '<LatLngPoly: {}>'.format(self.loopcode)
|
||||
|
||||
def __len__(self):
|
||||
"""
|
||||
Should this be the number of points in the outer loop,
|
||||
the number of holes (or +1 for the outer loop)?
|
||||
"""
|
||||
raise NotImplementedError('No clear definition of length for LatLngPoly.')
|
||||
|
||||
@property
|
||||
def loopcode(self):
|
||||
""" Short code for describing the length of the outer loop and each hole
|
||||
|
||||
Example: ``[382/(18, 6, 6)]`` indicates an outer loop of 382 points,
|
||||
along with 3 holes with 18, 6, and 6 points, respectively.
|
||||
|
||||
Example: ``[15]`` indicates an outer loop of 15 points and no holes.
|
||||
"""
|
||||
outer = len(self.outer)
|
||||
holes = tuple(map(len, self.holes))
|
||||
|
||||
outer = str(outer)
|
||||
|
||||
if holes:
|
||||
out = outer + '/' + str(holes)
|
||||
else:
|
||||
out = outer
|
||||
|
||||
return '[' + out + ']'
|
||||
|
||||
@property
|
||||
def __geo_interface__(self):
|
||||
ll2 = _polygon_to_LL2(self)
|
||||
gj_dict = _LL2_to_geojson_dict(ll2)
|
||||
|
||||
return gj_dict
|
||||
|
||||
|
||||
class LatLngMultiPoly(H3Shape):
|
||||
"""
|
||||
Container for multiple ``LatLngPoly`` polygons.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
polys : list[LatLngPoly]
|
||||
List of lat/lng points describing the outer loop of the polygon
|
||||
"""
|
||||
def __init__(self, *polys):
|
||||
self.polys = tuple(polys)
|
||||
|
||||
for p in self.polys:
|
||||
if not isinstance(p, LatLngPoly):
|
||||
raise ValueError('LatLngMultiPoly requires each input to be an LatLngPoly object, instead got: ' + str(p)) # noqa
|
||||
|
||||
def __repr__(self):
|
||||
out = [p.loopcode for p in self.polys]
|
||||
out = ', '.join(out)
|
||||
out = '<LatLngMultiPoly: {}>'.format(out)
|
||||
return out
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.polys)
|
||||
|
||||
def __len__(self):
|
||||
""" Give the number of polygons in this multi-polygon.
|
||||
"""
|
||||
|
||||
"""
|
||||
TODO: Pandas series or dataframe representation changes depending
|
||||
on if __len__ is defined.
|
||||
|
||||
I'd prefer the one that states `LatLngMultiPoly`.
|
||||
It seems like Pandas is assuming an iterable is best-described
|
||||
by its elements when choosing the representation.
|
||||
|
||||
when __len__ *IS NOT* defined:
|
||||
|
||||
0 <LatLngMultiPoly: [368], [20], [6]>
|
||||
1 <LatLngMultiPoly: [632/(6, 6, 6, 6, 6)], [290/(6,)...
|
||||
2 <LatLngMultiPoly: [490/(6, 6, 10, 10, 14, 10, 6)],...
|
||||
3 <LatLngMultiPoly: [344/(6,)], [22], [6], [10], [6]...
|
||||
4 <LatLngMultiPoly: [382/(18, 6, 6)], [32], [6], [18...
|
||||
|
||||
when __len__ *IS* defined:
|
||||
|
||||
0 (<LatLngPoly: [368]>, <LatLngPoly: [20]>, <LatLngPoly: [6]>)
|
||||
1 (<LatLngPoly: [632/(6, 6, 6, 6, 6)]>, <LatLngPoly: [29...
|
||||
2 (<LatLngPoly: [490/(6, 6, 10, 10, 14, 10, 6)]>, <H...
|
||||
3 (<LatLngPoly: [344/(6,)]>, <LatLngPoly: [22]>, <LatLngPoly...
|
||||
4 (<LatLngPoly: [382/(18, 6, 6)]>, <LatLngPoly: [32]>, <...
|
||||
"""
|
||||
return len(self.polys)
|
||||
|
||||
def __getitem__(self, index):
|
||||
return self.polys[index]
|
||||
|
||||
@property
|
||||
def __geo_interface__(self):
|
||||
ll3 = _mpoly_to_LL3(self)
|
||||
gj_dict = _LL3_to_geojson_dict(ll3)
|
||||
|
||||
return gj_dict
|
||||
|
||||
|
||||
"""
|
||||
Helpers for cells_to_geojson and geojson_to_cells.
|
||||
|
||||
Dealing with GeoJSON Polygons and MultiPolygons can be confusing because
|
||||
there are so many nested lists. To help keep track, we use the following
|
||||
symbols to denote different levels of nesting.
|
||||
|
||||
LL0: lat/lng or lng/lat pair
|
||||
LL1: list of LL0s
|
||||
LL2: list of LL1s (i.e., a polygon with holes)
|
||||
LL3: list of LL2s (i.e., several polygons with holes)
|
||||
|
||||
|
||||
## TODO
|
||||
|
||||
- Allow user to specify "container" in `cells_to_geojson`.
|
||||
- That is, they may want a MultiPolygon even if the output fits in a Polygon
|
||||
- 'auto', Polygon, MultiPolygon, FeatureCollection, GeometryCollection, ...
|
||||
"""
|
||||
|
||||
|
||||
def _mpoly_to_LL3(mpoly):
|
||||
ll3 = tuple(
|
||||
_polygon_to_LL2(poly)
|
||||
for poly in mpoly
|
||||
)
|
||||
|
||||
return ll3
|
||||
|
||||
|
||||
def _LL3_to_mpoly(ll3):
|
||||
polys = [
|
||||
_LL2_to_polygon(ll2)
|
||||
for ll2 in ll3
|
||||
]
|
||||
|
||||
mpoly = LatLngMultiPoly(*polys)
|
||||
|
||||
return mpoly
|
||||
|
||||
|
||||
def _polygon_to_LL2(poly):
|
||||
ll2 = [poly.outer] + list(poly.holes)
|
||||
ll2 = tuple(
|
||||
_close_ring(_swap_latlng(ll1))
|
||||
for ll1 in ll2
|
||||
)
|
||||
|
||||
return ll2
|
||||
|
||||
|
||||
def _remove_z(ll1):
|
||||
ll1 = [(a, b) for a, b, *z in ll1]
|
||||
return ll1
|
||||
|
||||
|
||||
def _LL2_to_polygon(ll2):
|
||||
ll2 = [
|
||||
_remove_z(ll1)
|
||||
for ll1 in ll2
|
||||
]
|
||||
|
||||
ll2 = [
|
||||
_swap_latlng(ll1)
|
||||
for ll1 in ll2
|
||||
]
|
||||
h3poly = LatLngPoly(*ll2)
|
||||
|
||||
return h3poly
|
||||
|
||||
|
||||
def _LL2_to_geojson_dict(ll2):
|
||||
gj_dict = {
|
||||
'type': 'Polygon',
|
||||
'coordinates': ll2,
|
||||
}
|
||||
|
||||
return gj_dict
|
||||
|
||||
|
||||
def _LL3_to_geojson_dict(ll3):
|
||||
gj_dict = {
|
||||
'type': 'MultiPolygon',
|
||||
'coordinates': ll3,
|
||||
}
|
||||
|
||||
return gj_dict
|
||||
|
||||
|
||||
def _swap_latlng(ll1):
|
||||
ll1 = tuple(
|
||||
(b, a) for a, b in ll1
|
||||
)
|
||||
return ll1
|
||||
|
||||
|
||||
def _close_ring(ll1):
|
||||
"""
|
||||
Idempotent
|
||||
"""
|
||||
if ll1 and (ll1[0] != ll1[-1]):
|
||||
ll1 = tuple(ll1) + (ll1[0],)
|
||||
|
||||
return ll1
|
||||
|
||||
|
||||
def _open_ring(ll1):
|
||||
"""
|
||||
Idempotent
|
||||
"""
|
||||
if ll1 and (ll1[0] == ll1[-1]):
|
||||
ll1 = ll1[:-1]
|
||||
|
||||
return ll1
|
||||
|
||||
|
||||
def geo_to_h3shape(geo):
|
||||
"""
|
||||
Translate from ``__geo_interface__`` to H3Shape.
|
||||
|
||||
``geo`` either implements ``__geo_interface__`` or is a dict matching the format
|
||||
|
||||
Returns
|
||||
-------
|
||||
H3Shape
|
||||
"""
|
||||
|
||||
# geo can be dict, a __geo_interface__, a string, LatLngPoly or LatLngMultiPoly
|
||||
if isinstance(geo, H3Shape):
|
||||
return geo
|
||||
|
||||
if hasattr(geo, '__geo_interface__'):
|
||||
# get dict
|
||||
geo = geo.__geo_interface__
|
||||
|
||||
assert isinstance(geo, dict) # todo: remove
|
||||
|
||||
t = geo['type']
|
||||
coord = geo['coordinates']
|
||||
|
||||
if t == 'Polygon':
|
||||
ll2 = coord
|
||||
shape = _LL2_to_polygon(ll2)
|
||||
elif t == 'MultiPolygon':
|
||||
ll3 = coord
|
||||
shape = _LL3_to_mpoly(ll3)
|
||||
else:
|
||||
raise ValueError('Unrecognized type: ' + str(t))
|
||||
|
||||
return shape
|
||||
|
||||
|
||||
def h3shape_to_geo(h3shape):
|
||||
"""
|
||||
Translate from an ``H3Shape`` to a ``__geo_interface__`` dict.
|
||||
|
||||
``h3shape`` should be either ``LatLngPoly`` or ``LatLngMultiPoly``
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict
|
||||
"""
|
||||
return h3shape.__geo_interface__
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
from importlib import metadata
|
||||
|
||||
__version__ = metadata.version(__package__ or __name__)
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
# flake8: noqa
|
||||
|
||||
from . import basic_int
|
||||
from . import basic_str
|
||||
from . import memview_int
|
||||
from . import numpy_int
|
||||
+1240
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,17 @@
|
||||
from ... import _cy
|
||||
|
||||
|
||||
def _in_scalar(x):
|
||||
return x
|
||||
|
||||
|
||||
_out_scalar = _in_scalar
|
||||
|
||||
|
||||
def _in_collection(cells):
|
||||
it = list(cells)
|
||||
|
||||
return _cy.iter_to_mv(it)
|
||||
|
||||
|
||||
_out_collection = list
|
||||
+1240
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,14 @@
|
||||
from ... import _cy
|
||||
|
||||
_in_scalar = _cy.str_to_int
|
||||
_out_scalar = _cy.int_to_str
|
||||
|
||||
|
||||
def _in_collection(cells):
|
||||
it = [_cy.str_to_int(h) for h in cells]
|
||||
|
||||
return _cy.iter_to_mv(it)
|
||||
|
||||
|
||||
def _out_collection(mv):
|
||||
return list(_cy.int_to_str(h) for h in mv)
|
||||
+1240
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,8 @@
|
||||
def _id(x):
|
||||
return x
|
||||
|
||||
|
||||
_in_scalar = _id
|
||||
_out_scalar = _id
|
||||
_in_collection = _id
|
||||
_out_collection = _id
|
||||
+1240
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
||||
def _in_scalar(x):
|
||||
return x
|
||||
|
||||
|
||||
_out_scalar = _in_scalar
|
||||
|
||||
|
||||
def _in_collection(x):
|
||||
import numpy as np
|
||||
# array is copied only if dtype does not match
|
||||
# `list`s should work, but not `set`s of integers
|
||||
return np.asarray(x, dtype='uint64')
|
||||
|
||||
|
||||
_out_collection = _in_collection
|
||||
@@ -1 +0,0 @@
|
||||
pip
|
||||
@@ -1,180 +0,0 @@
|
||||
Metadata-Version: 2.4
|
||||
Name: reactivex
|
||||
Version: 4.1.0
|
||||
Summary: ReactiveX (Rx) for Python
|
||||
License: MIT
|
||||
License-File: LICENSE
|
||||
Author: Dag Brattli
|
||||
Author-email: dag@brattli.net
|
||||
Requires-Python: >=3.8,<4.0
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Environment :: Other Environment
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: MIT License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.8
|
||||
Classifier: Programming Language :: Python :: 3.9
|
||||
Classifier: Programming Language :: Python :: 3.10
|
||||
Classifier: Programming Language :: Python :: 3.11
|
||||
Classifier: Programming Language :: Python :: 3.12
|
||||
Classifier: Programming Language :: Python :: 3.13
|
||||
Classifier: Programming Language :: Python :: 3.14
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||
Requires-Dist: typing-extensions (>=4.1.1,<5.0.0)
|
||||
Project-URL: Documentation, https://rxpy.readthedocs.io/en/latest/
|
||||
Project-URL: Homepage, http://reactivex.io
|
||||
Project-URL: Repository, https://github.com/ReactiveX/RxPY
|
||||
Description-Content-Type: text/x-rst
|
||||
|
||||
===============================
|
||||
The ReactiveX for Python (RxPY)
|
||||
===============================
|
||||
|
||||
.. image:: https://github.com/ReactiveX/RxPY/workflows/Python%20package/badge.svg
|
||||
:target: https://github.com/ReactiveX/RxPY/actions
|
||||
:alt: Build Status
|
||||
|
||||
.. image:: https://img.shields.io/coveralls/ReactiveX/RxPY.svg
|
||||
:target: https://coveralls.io/github/ReactiveX/RxPY
|
||||
:alt: Coverage Status
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/reactivex.svg
|
||||
:target: https://pypi.org/project/reactivex/
|
||||
:alt: PyPY Package Version
|
||||
|
||||
.. image:: https://img.shields.io/readthedocs/rxpy.svg
|
||||
:target: https://readthedocs.org/projects/rxpy/builds/
|
||||
:alt: Documentation Status
|
||||
|
||||
|
||||
*A library for composing asynchronous and event-based programs using observable
|
||||
collections and query operator functions in Python*
|
||||
|
||||
ReactiveX for Python v4
|
||||
-----------------------
|
||||
|
||||
For v3.X please go to the `v3 branch
|
||||
<https://github.com/ReactiveX/RxPY/tree/release/v3.2.x>`_.
|
||||
|
||||
ReactiveX for Python v4.x runs on `Python <http://www.python.org/>`_ 3.9 or above. To
|
||||
install:
|
||||
|
||||
.. code:: console
|
||||
|
||||
pip3 install reactivex
|
||||
|
||||
|
||||
About ReactiveX
|
||||
---------------
|
||||
|
||||
ReactiveX for Python (RxPY) is a library for composing asynchronous and event-based
|
||||
programs using observable sequences and pipable query operators in Python. Using Rx,
|
||||
developers represent asynchronous data streams with Observables, query asynchronous data
|
||||
streams using operators, and parameterize concurrency in data/event streams using
|
||||
Schedulers.
|
||||
|
||||
.. code:: python
|
||||
|
||||
import reactivex as rx
|
||||
from reactivex import operators as ops
|
||||
|
||||
source = rx.of("Alpha", "Beta", "Gamma", "Delta", "Epsilon")
|
||||
|
||||
composed = source.pipe(
|
||||
ops.map(lambda s: len(s)),
|
||||
ops.filter(lambda i: i >= 5)
|
||||
)
|
||||
composed.subscribe(lambda value: print("Received {0}".format(value)))
|
||||
|
||||
|
||||
Learning ReactiveX
|
||||
------------------
|
||||
|
||||
Read the `documentation
|
||||
<https://rxpy.readthedocs.io/en/latest/>`_ to learn
|
||||
the principles of ReactiveX and get the complete reference of the available
|
||||
operators.
|
||||
|
||||
If you need to migrate code from RxPY v1.x or v3.x, read the `migration
|
||||
<https://rxpy.readthedocs.io/en/latest/migration.html>`_ section.
|
||||
|
||||
There is also a list of third party documentation available `here
|
||||
<https://rxpy.readthedocs.io/en/latest/additional_reading.html>`_.
|
||||
|
||||
|
||||
Community
|
||||
----------
|
||||
|
||||
Join the conversation on GitHub `Discussions
|
||||
<https://github.com/ReactiveX/RxPY/discussions>`_! if you have any questions or
|
||||
suggestions.
|
||||
|
||||
Differences from .NET and RxJS
|
||||
------------------------------
|
||||
|
||||
ReactiveX for Python is a fairly complete implementation of
|
||||
`Rx <http://reactivex.io/>`_ with more than
|
||||
`120 operators <https://rxpy.readthedocs.io/en/latest/operators.html>`_, and
|
||||
over `1300 passing unit-tests <https://coveralls.io/github/ReactiveX/RxPY>`_. RxPY
|
||||
is mostly a direct port of RxJS, but also borrows a bit from Rx.NET and RxJava in
|
||||
terms of threading and blocking operators.
|
||||
|
||||
ReactiveX for Python follows `PEP 8 <http://legacy.python.org/dev/peps/pep-0008/>`_, so
|
||||
all function and method names are ``snake_cased`` i.e lowercase with words separated by
|
||||
underscores as necessary to improve readability.
|
||||
|
||||
Thus .NET code such as:
|
||||
|
||||
.. code:: c#
|
||||
|
||||
var group = source.GroupBy(i => i % 3);
|
||||
|
||||
|
||||
need to be written with an ``_`` in Python:
|
||||
|
||||
.. code:: python
|
||||
|
||||
group = source.pipe(ops.group_by(lambda i: i % 3))
|
||||
|
||||
With ReactiveX for Python you should use `named keyword arguments
|
||||
<https://docs.python.org/3/glossary.html>`_ instead of positional arguments when an
|
||||
operator has multiple optional arguments. RxPY will not try to detect which arguments
|
||||
you are giving to the operator (or not).
|
||||
|
||||
Development
|
||||
-----------
|
||||
|
||||
This project is managed using `Poetry <https://python-poetry.org/>`_. Code is formatted
|
||||
using `Black <https://github.com/psf/black>`_, `isort
|
||||
<https://github.com/PyCQA/isort>`_. Code is statically type checked using `pyright
|
||||
<https://github.com/microsoft/pyright>`_ and `mypy <http://mypy-lang.org/>`_.
|
||||
|
||||
If you want to take advantage of the default VSCode integration, then
|
||||
first configure Poetry to make its virtual environment in the
|
||||
repository:
|
||||
|
||||
.. code:: console
|
||||
|
||||
poetry config virtualenvs.in-project true
|
||||
|
||||
After cloning the repository, activate the tooling:
|
||||
|
||||
.. code:: console
|
||||
|
||||
poetry install
|
||||
poetry run pre-commit install
|
||||
|
||||
Run unit tests:
|
||||
|
||||
.. code:: console
|
||||
|
||||
poetry run pytest
|
||||
|
||||
Run code checks (manually):
|
||||
|
||||
.. code:: console
|
||||
|
||||
poetry run pre-commit run --all-files
|
||||
|
||||
@@ -1,225 +0,0 @@
|
||||
reactivex-4.1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
reactivex-4.1.0.dist-info/METADATA,sha256=rSqPVN97BAmfb3t-XajHhZYG_BsViZQqFQsJaF3jXsc,5697
|
||||
reactivex-4.1.0.dist-info/RECORD,,
|
||||
reactivex-4.1.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
reactivex-4.1.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
||||
reactivex-4.1.0.dist-info/licenses/LICENSE,sha256=vModcyjYiECG6tvSqOZvENUzjfLXk0FeVtBS9pUy_zE,1112
|
||||
reactivex/__init__.py,sha256=xUhiKlZmQgCnlBvx_072mRMdisi_z9HuINSW7wvzgvY,39756
|
||||
reactivex/_version.py,sha256=jegJMYuSW90VKiMotVdNAakBvYVPirm-A5oeyJVuhH8,22
|
||||
reactivex/abc/__init__.py,sha256=qvD2QcDdd3vL89eEhzBqcRpDnHGHMAOLWYr4TqtJpdM,594
|
||||
reactivex/abc/disposable.py,sha256=DIE-c0MwHEmU1IYD_9v8WNisgn47X0VYJGCAIb9anBo,826
|
||||
reactivex/abc/observable.py,sha256=Q2UQLzOILTgEWmKa_coUB_YFV7U4Cytr9014mJdTXy0,1334
|
||||
reactivex/abc/observer.py,sha256=m8zfu2MR3Iuc0kIOfEVGzQUBIoKrmZGHRFLPd_Orhic,1150
|
||||
reactivex/abc/periodicscheduler.py,sha256=dviU37-fPN_rRR9g1OyOxrW5d3zP_AKIfcodoK_NDo8,1344
|
||||
reactivex/abc/scheduler.py,sha256=DLWlL5uhFClEE3OKIMraodxqP0qT_9spkC6kCLjowsM,4362
|
||||
reactivex/abc/startable.py,sha256=C_L9Q-ooHslSNthYapLwEJgG-KD5cSkOCnDeTa-rw0o,266
|
||||
reactivex/abc/subject.py,sha256=1j5jJrvdlYaK4oFeObjpD1M_gKkZBAPiVnqR9WjOL1w,1907
|
||||
reactivex/disposable/__init__.py,sha256=EqOgh0GrHv578Dwq3APgPjB8eYD4vVE1qQJ056LhCrs,658
|
||||
reactivex/disposable/booleandisposable.py,sha256=jbH7Qbkcjon7YkvbtWjHOd_h2DJaNg2NFd2tg0cwMh0,482
|
||||
reactivex/disposable/compositedisposable.py,sha256=nCinmCt--aCyltvZ5v2Kj8c4JddLx04Ihpd9zwmGhkw,2816
|
||||
reactivex/disposable/disposable.py,sha256=qJHh7EWE6k5zcI_p9BwUooFHAD3VkndgExvAbJSpEC0,1132
|
||||
reactivex/disposable/multipleassignmentdisposable.py,sha256=Xc-orSPzypavx2bvXFjzbEkF5ov-UPbOhMZpgir8ROY,1419
|
||||
reactivex/disposable/refcountdisposable.py,sha256=op7U4ZVPGz26qBCW-UWdV4GDoBqgztUxqcMzlurvEXU,2484
|
||||
reactivex/disposable/scheduleddisposable.py,sha256=BYaETQ9LysWPYc21XFiA0TLRbWMu-eDSXXdznSrAE8Y,1149
|
||||
reactivex/disposable/serialdisposable.py,sha256=pJsWQyTV2hCDWn8o8bY8MeL0ERYeqGpVV4OaRZHrUj4,1723
|
||||
reactivex/disposable/singleassignmentdisposable.py,sha256=pzCdcP-eJQGoXm24phls8QPAcLPS_hkcwOdxErv5O7s,1595
|
||||
reactivex/internal/__init__.py,sha256=P2T5xg1uq3zUHf5GRHZd4m2RxUH2Rpd_HPq0k7WC8L4,730
|
||||
reactivex/internal/basic.py,sha256=xi-tuNm2dScLEjZBWDqFV9jQ4MwOrRWu91zJI_GD_Rk,673
|
||||
reactivex/internal/concurrency.py,sha256=4j9LDDVZvaHgki3mSF01NCv8MOI_xEcPwVrDijfvxtM,691
|
||||
reactivex/internal/constants.py,sha256=mCLIqaIhFDTe83oAoPmRNdBHJFINCjvOKqJlgYMGSiI,132
|
||||
reactivex/internal/exceptions.py,sha256=eQ6z4Me2hdtRn3NGPGKZtB76TmI1R4nDIpnbxJQBY-s,1003
|
||||
reactivex/internal/priorityqueue.py,sha256=GC1OWyGHk3sDPCtBkgyJs5T1iadXLX6i8UtPcg6ibP4,1491
|
||||
reactivex/internal/utils.py,sha256=GtHsPfim2syw-q6_bpvoE40jdvAHL4Ag5A2veTvaNtw,1809
|
||||
reactivex/notification.py,sha256=O54boOqdr-_Uy4uTjqm9bCKdH1vxsr4Ln9rd4GR8ebA,6298
|
||||
reactivex/observable/__init__.py,sha256=rx4_4eShoAgulw7fgEHjP6o7kXMPKlPp0Ht9nvD9rOY,213
|
||||
reactivex/observable/amb.py,sha256=s82aaIXF94z8faaCahpfu7vATnhM2JX1I3QH8Iv4SZw,677
|
||||
reactivex/observable/case.py,sha256=nfG5i1j5L9oUJYEx3YlqjoA0IERz3jsdkFCWXAW9jIw,893
|
||||
reactivex/observable/catch.py,sha256=iV2TcivGIjHWb2S4lhlX84xkKOHfX7FFyLh-GJCn0YY,2566
|
||||
reactivex/observable/combinelatest.py,sha256=BBz05LZiFBov8-SvdpdORhU0VydgYzqPRaET16r8gkU,2223
|
||||
reactivex/observable/concat.py,sha256=UvMYssA20vhf-tkNAq9SDGIXWNH2D_Q6lxkLjgAVAZ8,1884
|
||||
reactivex/observable/connectableobservable.py,sha256=fh16uLWJSgDTTUtl_sUTWL9hPc-tWtfN4DK8-43oBq8,2756
|
||||
reactivex/observable/defer.py,sha256=sfHQm6IlrwwkY3bAkxOWLVvQJGLsLzTUytbN543KvmI,1408
|
||||
reactivex/observable/empty.py,sha256=jFELiog8feo5HxCLZ1BdetmRxKynypBUYdXoTh5Y5fg,616
|
||||
reactivex/observable/forkjoin.py,sha256=XEhWxx20gbT2ZL9slMT0QGWA45iniCq_egcZiOe4Sio,2189
|
||||
reactivex/observable/fromcallback.py,sha256=zZQu9UWOI1CfDzlcyoLae6qeZIFdxkWpu7HiGQw0OxY,1878
|
||||
reactivex/observable/fromfuture.py,sha256=tI7-HbCiA0hVoZZfpUPW-bRbX7XcHtRA93FmfX5m3wo,1405
|
||||
reactivex/observable/fromiterable.py,sha256=wgVVoYnSUGHNKBU6ZT7QAtjksQpDUvKcCWCO1NU6Uk0,1652
|
||||
reactivex/observable/generate.py,sha256=RWYxDukbOAtfFC5xPhjuH1OuDgw5x0frKW7uTRjdXp8,1647
|
||||
reactivex/observable/generatewithrelativetime.py,sha256=2L9pwfY2sx2T23B6P4ApV042UaS2UXFbc3a3UrGo3jI,2711
|
||||
reactivex/observable/groupedobservable.py,sha256=aaySQ7vx5bHwXsHZxpaCJjI5Y87baL07_PnZRjP7jQE,1300
|
||||
reactivex/observable/ifthen.py,sha256=fOoKAg9Rw7t6E83uM3aRoK8iEbLEwexab5mSBtpRHJg,1667
|
||||
reactivex/observable/interval.py,sha256=nE4p-DD1DjThkVYJ9SJWWGbWrNFkUV3DzVffk_A1L8I,271
|
||||
reactivex/observable/marbles.py,sha256=YLb9gsGWfynMtCO_9tmICUWlBulRTeY1erNvTUeMChM,9254
|
||||
reactivex/observable/merge.py,sha256=EOZONxkkgq20oB9Q1_lPch0BXwR3KU6FpG8FDnqZ-7M,284
|
||||
reactivex/observable/never.py,sha256=HmnZPq2b3bcJyKW2iZLeEAhH-gWxAZjcpeqirVpxFaE,605
|
||||
reactivex/observable/observable.py,sha256=3_BiiaSizmfaGb-nbICQAhf6MlH4hynM_5l63gwZZcM,11482
|
||||
reactivex/observable/onerrorresumenext.py,sha256=U095TAz5LQ_bi9k_Gsf0nwi6zlkNAeAFz6wpgO-Eh4I,2222
|
||||
reactivex/observable/range.py,sha256=fCpgUh8_R3UNBeuvy_sQPLvEui_qSASWEbXk-uZZqm4,2151
|
||||
reactivex/observable/repeat.py,sha256=gts_BxFEobJxr4RvB37g6iX9R4Vei0dYOogq1e7NmZk,890
|
||||
reactivex/observable/returnvalue.py,sha256=bmyU60ZBPgj_jB3II7CoYXitcahDOs8Nprgm579GfUI,1933
|
||||
reactivex/observable/start.py,sha256=PNbLPq_D5oV7T5TMIayBRCcYy9oalmBu5ea7noiB-4g,1091
|
||||
reactivex/observable/startasync.py,sha256=BOu75YH2oa0I23bsz89fVxtc7pZEqzgxIQQX3RpVZ_4,409
|
||||
reactivex/observable/throw.py,sha256=T8ccsu_ikGFk8incIrKFEng_TXojlPCdY_UiXEYzhn8,754
|
||||
reactivex/observable/timer.py,sha256=MkxxL3feuzG3kqpVHcoYXvTjfbzlliX3jVcIlPPy9Eg,4498
|
||||
reactivex/observable/toasync.py,sha256=AzUHl7-CFBTWsjWr15eIwNReZMMyXTnfJTDlJIzPwBw,1694
|
||||
reactivex/observable/using.py,sha256=Y3ZbxO_dS9SGaI6zwjVXFOZmtdtQ1FHadamoE03tTjg,1689
|
||||
reactivex/observable/withlatestfrom.py,sha256=wIs-YV8AD-dA60mtLLnRnIGUDF7IaVrRSnL3npD8dEU,1987
|
||||
reactivex/observable/zip.py,sha256=DHR_4WGQ8HTdZwvoKL-ykdTYArEvYA-PvYdzKSPEmKA,2828
|
||||
reactivex/observer/__init__.py,sha256=kzNSuynaSXVopszVbAHemaMi8QckLukg3HapjFd5qTg,268
|
||||
reactivex/observer/autodetachobserver.py,sha256=AtokqzYC9YoWmf4krJw3KoZU3o-l9QOG3BZokaSeuVs,1710
|
||||
reactivex/observer/observeonobserver.py,sha256=4VXsFvS9XLySlllx92G6XRbzXoymbDuge7wfGJUdrmM,494
|
||||
reactivex/observer/observer.py,sha256=LfG-WtWE9rReIxZcjsDGInbdOG8k6rLy4Jt9FzWExZA,3520
|
||||
reactivex/observer/scheduledobserver.py,sha256=EsaN8BP9ZaPbCzhMJbVjWxcoGk0-WHX3Z3MJrNrcd8k,2189
|
||||
reactivex/operators/__init__.py,sha256=25nkSxdpoFYqp25XakOGXYuHaHSRS1r_5drUm42vfnI,132458
|
||||
reactivex/operators/_all.py,sha256=Q_E4tAY6CNNqRxJAd-bkupKEwhj29CSR9VvFCjj-DTE,497
|
||||
reactivex/operators/_amb.py,sha256=ivtjF1nHWykfYuwRBVEj1RgsSueUftK6inmQ9zVIxsI,3076
|
||||
reactivex/operators/_asobservable.py,sha256=7XeRHYCbf0nRywnRBKOa6FeJZoUPpOdYas04IUiKH-8,821
|
||||
reactivex/operators/_average.py,sha256=E3WHAmQsa45QFbrkNrp2aW-hQJJdNXWe8ivOJ4Wkn1Y,1685
|
||||
reactivex/operators/_buffer.py,sha256=aoBaRCbQXZgaFSmO1Re6tMm4_TCLP0Lya5UKeEZdqXQ,2206
|
||||
reactivex/operators/_bufferwithtime.py,sha256=8IljnQa_nmm6_2GUbyKI3MEpHH5KbqTYix5dmiB3hGU,619
|
||||
reactivex/operators/_bufferwithtimeorcount.py,sha256=GvagRPU_gnM4xJ_HOdZ7XYmMf4FNGv0vCsP-nqWbNNc,557
|
||||
reactivex/operators/_catch.py,sha256=9ffgARW8H51S7dNB-ZThc28BNVZQXkfjQvVPqZ-sMco,2575
|
||||
reactivex/operators/_combinelatest.py,sha256=45UDZGrQtm0PX2gmaLexKNWWoVx01fR4MCWWtxnSmYk,798
|
||||
reactivex/operators/_concat.py,sha256=8ziLOjVcxs96Vc4msyP_11U7lYi7F9X1F6whXSYAHK0,695
|
||||
reactivex/operators/_contains.py,sha256=j3Iva5NadCLrzp0lu12OlRZZiNoVAxBWG9HTG5kGuy8,581
|
||||
reactivex/operators/_count.py,sha256=dwsii7oxDq2HRdSq7MOHzMHOgbjiBPHu3ZoLR2FCmuA,558
|
||||
reactivex/operators/_debounce.py,sha256=sNWOLGZmIunYjKfslzwNQqDqSO7WM1m8b6qATJ2A07w,5562
|
||||
reactivex/operators/_defaultifempty.py,sha256=Ld-4sxUO-yHHYQRHIMy4aCWasy1rDZJNV05Szjokk6k,1456
|
||||
reactivex/operators/_delay.py,sha256=uzyQywJAv5tiQ5DKknu6ESecW117eaXGIzUwf370JGI,4722
|
||||
reactivex/operators/_delaysubscription.py,sha256=xLSAFuGMtHQdWjw8S1h2o46255nkbd0chDuHSZw3sxA,994
|
||||
reactivex/operators/_delaywithmapper.py,sha256=ZoOjh8-ehIZKjN7lLmQ-7zVTf7US-CBusuYIsZuDnCQ,3511
|
||||
reactivex/operators/_dematerialize.py,sha256=Ai4yXRnbqs5qor3fy5PyUJkx9i-L09PuK5Uv9c20t1s,1091
|
||||
reactivex/operators/_distinct.py,sha256=q_Rb9uJz5gAf3QeNe2bg8U71T4My3QrnvTPZArBGcbg,2516
|
||||
reactivex/operators/_distinctuntilchanged.py,sha256=-SnZF4qheq3FwpFyk5ZZWCB6z6wT37xIwcrHZe6t5kc,2869
|
||||
reactivex/operators/_do.py,sha256=NaRy0fcHdzVPRLqLE1VSPLbZyYwWip3cPiiJTXnrVJI,10795
|
||||
reactivex/operators/_dowhile.py,sha256=uXEnZLz_tfSW8rUXVnki5UlP0tvRbZ3TPEC7q3QJ61s,817
|
||||
reactivex/operators/_elementatordefault.py,sha256=J1Nb2WpOs2iIxOnP84TdVuHPl4n9ySM_lVmAfdqR69E,1546
|
||||
reactivex/operators/_exclusive.py,sha256=Q5p_Duez_i2xxy0BkTyO_VdxVFBbWSAbhgWodgiY47k,2479
|
||||
reactivex/operators/_expand.py,sha256=q9aUkvffLhzam_O0-xhgGprvkhfmZNaXbtU2c4SCqTo,3078
|
||||
reactivex/operators/_filter.py,sha256=x4GU4BH0wRkh_xnA5Js3JaDQ_wZ7Krp0w99TnC-xir8,2807
|
||||
reactivex/operators/_finallyaction.py,sha256=GCF-sBwTg4aqh7cnyRbN4JIAnHZZQEPjWDXQdGsR9cs,1302
|
||||
reactivex/operators/_find.py,sha256=GE1xEG06I8ojugiTy6qCq4od15EWSPmGMCTz54Dawy0,1433
|
||||
reactivex/operators/_first.py,sha256=cvcl5Mx3btw9m48J3J5ubTobOTI0YYLxeFE6tSRKR74,1176
|
||||
reactivex/operators/_firstordefault.py,sha256=1ZMxi0mr5uuyUAz6XrA5Y3G94O18A1HnIjeFTWxiT-s,2557
|
||||
reactivex/operators/_flatmap.py,sha256=R9MnotDaMPTie7FK-fZcMkmke2KF42AZl6y5pAa410U,4279
|
||||
reactivex/operators/_forkjoin.py,sha256=qkQKndnP2DcY60nAp6Cjq_tJuyS9Z3IGwmGebD5Imk4,843
|
||||
reactivex/operators/_groupby.py,sha256=FLN5ykLpHalUQbk2H5ENm33tgoRYyDS6kBcQ0_-ZCM0,852
|
||||
reactivex/operators/_groupbyuntil.py,sha256=mO-xW1vBlBPMhw1fjOA7K3RRon9MIsrJy8jbRWw9jzY,6308
|
||||
reactivex/operators/_groupjoin.py,sha256=9N-WQsfOwFT0oqvcM5KyKj6wH6rY-5wLe6vo-8MDArY,5886
|
||||
reactivex/operators/_ignoreelements.py,sha256=6szHhX7hjEf5UBRBGQslyUHm03XeT5d41A_cWKKkoUs,929
|
||||
reactivex/operators/_isempty.py,sha256=jeVsO7KUJ3TrKns3616gGpGP7k8yOvj4pr0LZZQP9jc,534
|
||||
reactivex/operators/_join.py,sha256=7KZAECRvb339vlZYfAatrFLGGYSjYgN7adZvaSPs41E,4592
|
||||
reactivex/operators/_last.py,sha256=0DV-uHOH_0I6qR6shWISXi1-sb8Rk_5GrPUN28_-RA8,1138
|
||||
reactivex/operators/_lastordefault.py,sha256=DsgpzcoFqZ-dV4BafyR_fU5Gu6dJebuQd4Bhw-3aols,1968
|
||||
reactivex/operators/_map.py,sha256=lmBF2kPEJoNKqaxbUkF4J90s5rgCHWrv8mnDcql-lHk,2129
|
||||
reactivex/operators/_materialize.py,sha256=Su1xY0GrbjfuXi2WvDBSq3Far1M3ZpoXsmSfXN1GwKg,1455
|
||||
reactivex/operators/_max.py,sha256=ZgzlqX9zBqllmzVSbxjabRMMqk9s1uT_3IyUhEASY54,995
|
||||
reactivex/operators/_maxby.py,sha256=-0gH-YJuz-p8cQWXJOqAKn1s50vnvSbi5r32tJ92lHg,1018
|
||||
reactivex/operators/_merge.py,sha256=04vqPKtnLxpB9vUcHABsR7YWCGW4mycPWVtPp1Hu0r0,5185
|
||||
reactivex/operators/_min.py,sha256=jEd9YXx9_TATN33g17PSwEErLDpsxhMTb7sfoIQUOCQ,1173
|
||||
reactivex/operators/_minby.py,sha256=zAV1m2yG59hzJCGdsf_fayk0Inmw1pBm8e6fg-_rZhQ,2501
|
||||
reactivex/operators/_multicast.py,sha256=Spuwm-rwyaSgL5C-HPijjGmVavttQnHznovVCX6uqfg,2939
|
||||
reactivex/operators/_observeon.py,sha256=j-mneWR9fXq_XmOqdLvC0rn0FNhf8cbjsh09mFqT_4c,1212
|
||||
reactivex/operators/_onerrorresumenext.py,sha256=tGol6SbZlrQge2Je0HUfSvdN6rURAXe03K3EoY6Yr5U,419
|
||||
reactivex/operators/_pairwise.py,sha256=8Nx6OaDjTAxu-nK_nziObjt1-sQskH1EKFsiTBw91zI,1670
|
||||
reactivex/operators/_partition.py,sha256=O4mANzYnvFZZed6x92GK_oMV10zCkz6lTUD-5U7hjzk,3022
|
||||
reactivex/operators/_pluck.py,sha256=l6uteIyv2tVPxPDb36STgoumAIH9YmJNAcX3vRFyG0U,1208
|
||||
reactivex/operators/_publish.py,sha256=PFHQQInn6dYuKeSFn8oJX6NfsRQde5xNva1S0BGdbnU,2240
|
||||
reactivex/operators/_publishvalue.py,sha256=SVoAvEwF0re7U9oYNFVTb5NewpRTZY4Q-VvBFK5Un14,901
|
||||
reactivex/operators/_reduce.py,sha256=sKpDIPFr7pw8Gi1cz3HZbidRnc3-hKgb1Zq2FkcOQoQ,1570
|
||||
reactivex/operators/_repeat.py,sha256=ru1fh1IL-_l5AP2KawhsIK6nrPvnZrjxsX-cARWi8B4,1069
|
||||
reactivex/operators/_replay.py,sha256=pz4yYMQ4pRuEkZoXv4j0SBmTNNQ8xXBrTsvV2rI_b7E,2430
|
||||
reactivex/operators/_retry.py,sha256=xNdJe6OAhHgouYlso82bW-Ce-1scAXfa5GddfYVYilQ,1083
|
||||
reactivex/operators/_sample.py,sha256=t7V1V9I8giJjSgEKPTE-8sxX-4zUJipItEfPz0kAAEw,2123
|
||||
reactivex/operators/_scan.py,sha256=BpzkQl3FBQMWPWkc5gcc52pWLWnCiYiHErgq13od7ZA,1732
|
||||
reactivex/operators/_sequenceequal.py,sha256=I11OjMgjMUZOrqmCPYz1_5kDlpVxKnnou2YuhS2nOCQ,4148
|
||||
reactivex/operators/_single.py,sha256=oCDg0DPsGHWgWhVe4E1GHAOI0CGLRpwK4i3nxzo0iuo,1139
|
||||
reactivex/operators/_singleordefault.py,sha256=qWKXGNIuMdZkmZag-LNJSbmYtdxLy3sN3diKHFHCooM,2840
|
||||
reactivex/operators/_skip.py,sha256=rMZBIjjtg2eNDIWgXCMzPnTLXqC9d7vu1cZhgkHopBo,1332
|
||||
reactivex/operators/_skiplast.py,sha256=95Nq8Onfafjqyd_-0kjH_elFEYm9YDumTBfjsGoCPRs,1590
|
||||
reactivex/operators/_skiplastwithtime.py,sha256=MqEMeEEwI1wCfCK1eWYsqYntmYpoWWh8gozymfXaq4M,2352
|
||||
reactivex/operators/_skipuntil.py,sha256=UUYfpCHnXU4Eg7tS-ljRDIH_Zjzf79ckYBkb6ihZw68,2133
|
||||
reactivex/operators/_skipuntilwithtime.py,sha256=O3lC8eDkjUuQcTUsHJBNEjs6HXXCkkITEbXGuD6XSlc,2252
|
||||
reactivex/operators/_skipwhile.py,sha256=JDPrpNX9HS62GVyT422pznnXfpkO06xbR3JFll-tWfc,2205
|
||||
reactivex/operators/_skipwithtime.py,sha256=JtRB0BsPDDF_P32zJ0K1e6iF0H5f6ZgS7Ao2ULNrL9c,2220
|
||||
reactivex/operators/_slice.py,sha256=w4TutKAOt8IzNGANLv7RqDro5gOIdMaTCcLgVLV0gBs,2311
|
||||
reactivex/operators/_some.py,sha256=8RSPk3mX4hm8geo49CTu8UGVkQqMHChncr1y2RXIGnA,1656
|
||||
reactivex/operators/_startswith.py,sha256=wbhJz2cHLwPVnd9lsJAcdcgn0srSZks6pxIHElvE_Hc,689
|
||||
reactivex/operators/_subscribeon.py,sha256=WPL3l6F79pYH-__8oyy0hoCtI6JCQ6J6QBjFmE-rM5Q,1744
|
||||
reactivex/operators/_sum.py,sha256=xtgLpIgK7qh5tjh0WpefDns_LzpAGAX9sWRIOd_J3KE,511
|
||||
reactivex/operators/_switchlatest.py,sha256=FYEPWYipGrQb4sgNVRHdYyM7B3ybc5Hm_6su471TRr8,2908
|
||||
reactivex/operators/_take.py,sha256=xZZykFL90MOz7Uy7DtYHAc26QiRFNbgRNfpMFx5ijuQ,1437
|
||||
reactivex/operators/_takelast.py,sha256=WwkJKxdIg73qNF-mxQnUx6aTO1vYxn1p_q_9_11DPfI,1619
|
||||
reactivex/operators/_takelastbuffer.py,sha256=vGrQdVPblAHzbNVPMvzIlRkMafD5yoN30WJy5L5cwc0,1695
|
||||
reactivex/operators/_takelastwithtime.py,sha256=foNqsRSSrZYp2ixrenCR-xzED2HaYKNFxtecUGx6pb4,2338
|
||||
reactivex/operators/_takeuntil.py,sha256=LHq_Lr1l3nk_YBCPyP0vsemhSKRZpXWLumhPdbPpDjI,1515
|
||||
reactivex/operators/_takeuntilwithtime.py,sha256=094FkE1vH2fBkQAEC-fN9awc4gs1bmMU1Pu12L2raQk,1706
|
||||
reactivex/operators/_takewhile.py,sha256=ZmPTbx_ROPF9JS_fqcG3oqs2SsOoCiebOccFwNbZ-cM,3612
|
||||
reactivex/operators/_takewithtime.py,sha256=jajLiqRc4sIPsRIaqjcir5yCB3zSnrogoaMXMgDKF1s,1850
|
||||
reactivex/operators/_throttlefirst.py,sha256=HAHaIK1FQ8fSOkwsenemsDh4AdlVk8Yrd0bUYBlhWx8,1887
|
||||
reactivex/operators/_timeinterval.py,sha256=q7FqU8hWO9_-_FwckgoumeLYpCx4upeq_jsF0o_RTZ0,1553
|
||||
reactivex/operators/_timeout.py,sha256=6FfEwqmfodvqtXvBxEXCmpdTvsYCiQ_AnOOJAwxlqOE,3248
|
||||
reactivex/operators/_timeoutwithmapper.py,sha256=VjM_DoqylWBY7R6_tY2WtoLymml-yIqgfDCV28Pd23Q,4408
|
||||
reactivex/operators/_timestamp.py,sha256=P1_NUuEJiCSe9s0whhdfEyFvGdIhNB6aKNxkvkhd9FI,1347
|
||||
reactivex/operators/_todict.py,sha256=YIXOJLMW4NKXJOxkfXMyQdfT9slM8s8DGtdbXl_QlzY,1972
|
||||
reactivex/operators/_tofuture.py,sha256=iEcdUPqaGDweTvciRkTEqSR_Xk3zjSrNfC8ukOnn-Hc,2061
|
||||
reactivex/operators/_toiterable.py,sha256=6dw1ph6-cihnyEsnHULlyMzCx1wYkASx2alKDYZPvwU,1170
|
||||
reactivex/operators/_tomarbles.py,sha256=kmQmhK2qJtIRcWxIKY09vFXAcms_9XSd9lsXpMFf4ME,2314
|
||||
reactivex/operators/_toset.py,sha256=2XIcr5xUURaf6qlvy7590znLs2wyJuLTf5rm2alpd9s,996
|
||||
reactivex/operators/_whiledo.py,sha256=-3t6FTMTIGjZHE2vfdRsWzclzotYsQjI_hYV-eOLZfk,1071
|
||||
reactivex/operators/_window.py,sha256=dpBG0GK_nW8_fbC19ceCMl6A_Io9EkrCWtIClvrqVvM,5176
|
||||
reactivex/operators/_windowwithcount.py,sha256=9ueOFkZ3JtJ16Tn1Bsu3kqzgKoD1jV-h3SDCLqLMcyg,2698
|
||||
reactivex/operators/_windowwithtime.py,sha256=RFuyNs0pWqC7_FgCI9pJUp8PuLC2Q9un-uy-K3G34Rg,3859
|
||||
reactivex/operators/_windowwithtimeorcount.py,sha256=SUx5Id39IqjGSeAYa_qD5yrb_HOPUJOdNWHbvWKdtEk,3113
|
||||
reactivex/operators/_withlatestfrom.py,sha256=v7fwpdHcPBxP8Fvmf-4_XVo_K0rfhcC2i2hx8GQNmjE,898
|
||||
reactivex/operators/_zip.py,sha256=h0ay0I7OtWFyJpT5-8s_FG6YbWK0vJdS7xYMfGQLSu4,2383
|
||||
reactivex/operators/connectable/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
reactivex/operators/connectable/_refcount.py,sha256=f8d3B0lUrROMjX4sm7tvaCsyaBnRQm6S1HNmedXm_jg,1419
|
||||
reactivex/pipe.py,sha256=yO-T0-cNJwUR5hgPuu8zoOrRaVlplwK5WHw3I7wP5Fw,4207
|
||||
reactivex/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
reactivex/run.py,sha256=LKeIqZG8yMtu3vLBCtxWKa5RUYCTzZnuKdnQzDNciFM,1709
|
||||
reactivex/scheduler/__init__.py,sha256=N0qMXVK3FlQJ1h25kVr9dLshBMWayEeWcNcfFen4bnY,856
|
||||
reactivex/scheduler/catchscheduler.py,sha256=KoYfPlLyhQvNRC3ue9E74tAAJuy0GlZNgu04Q3RMnB0,6130
|
||||
reactivex/scheduler/currentthreadscheduler.py,sha256=cJv0UjzT92FSe3sWxRzi4b-irV-2_xsVhjjLV4lxoGA,2657
|
||||
reactivex/scheduler/eventloop/__init__.py,sha256=wyCjpar6vxFyPvv_FM0N56FTinxnTqGs9MMBWY_2Gsc,468
|
||||
reactivex/scheduler/eventloop/asyncioscheduler.py,sha256=rfG7D34YxbhuMtT4OoZlEjsDE6Sqo78IEG63pvDCD6k,3790
|
||||
reactivex/scheduler/eventloop/asynciothreadsafescheduler.py,sha256=WPWLsxnzRviwbdDfg5HnXISExXk0ZjouOVEMY4mQ36s,5026
|
||||
reactivex/scheduler/eventloop/eventletscheduler.py,sha256=5ENX1cEw1KPDXz4YmrWcfkKFs5VK9SI_xiBPa-Kmu1E,3660
|
||||
reactivex/scheduler/eventloop/geventscheduler.py,sha256=aZDZY3eUWE3rtBBNaVFBz-jpAX7TdqPh3l6p94MaWGo,3700
|
||||
reactivex/scheduler/eventloop/ioloopscheduler.py,sha256=FSu0ROfJ3RYBp6VeZlji23UjB7P0qlQUQl4hyS4GXsk,3941
|
||||
reactivex/scheduler/eventloop/twistedscheduler.py,sha256=ZDhU3cGwVzpnFZHtD7VSbGhZmv3AjwBWjQGHNOsoz74,3373
|
||||
reactivex/scheduler/eventloopscheduler.py,sha256=bWz0mIWu76lqnRV-zoZ9LLPXQJF-otm05vFHbGxJiok,7421
|
||||
reactivex/scheduler/historicalscheduler.py,sha256=7ytM1qNWBBSnxWMoiOUCtSnot8AfTKEz0f_nBzGjacM,620
|
||||
reactivex/scheduler/immediatescheduler.py,sha256=0ZZgDRcA3U89X-IP0vED711HHla8lxfuGAFFSuM4q3o,3121
|
||||
reactivex/scheduler/mainloop/__init__.py,sha256=Lwy7VFLsygEMpVUQ0wkOsdFe-slCHK1gedydyOA2Dwc,325
|
||||
reactivex/scheduler/mainloop/gtkscheduler.py,sha256=KLLa1B1SHh35HBHe5UZpjjk1D9KlBVAktyohlnnVbjw,4399
|
||||
reactivex/scheduler/mainloop/pygamescheduler.py,sha256=yAglz1rCFRUtKiI4Dfc32bKyls7-US7ELrTJHylVMDM,3514
|
||||
reactivex/scheduler/mainloop/qtscheduler.py,sha256=rI7MBuKtnyCAVoyLj9zUc1kWT4zWVd-mfpdUIYFcJ2A,4476
|
||||
reactivex/scheduler/mainloop/tkinterscheduler.py,sha256=PSmKn06nEo5HW4jNdqKTktZiSDM6z5JFBxcf3qw0vso,2987
|
||||
reactivex/scheduler/mainloop/wxscheduler.py,sha256=Z1SjND81O3DNgqNg7C-6xRCcvRVIDwFyM_YnmyMGJK8,5522
|
||||
reactivex/scheduler/newthreadscheduler.py,sha256=K7l0ovBthzpG3uxn3t1MQRHqlbRVyhI0Boko8-d4X-0,4199
|
||||
reactivex/scheduler/periodicscheduler.py,sha256=m4ghE-odJrhiJASy6U1yviVYu18olBvjDNgnTX2LMpk,1878
|
||||
reactivex/scheduler/scheduleditem.py,sha256=SnWep-Zk3o2EvgfcaHrJeAJqmSdt3LK3KSpNb8L6k80,1433
|
||||
reactivex/scheduler/scheduler.py,sha256=L5nIuOC-a3StedJErx4iL3FY9ayh3QntEwlZpA3h4bs,5400
|
||||
reactivex/scheduler/threadpoolscheduler.py,sha256=yAE_hgTlcvV4GIsgVwc5XxZmg13-1Hf8aWaoz3eKYXo,1254
|
||||
reactivex/scheduler/timeoutscheduler.py,sha256=IJUzB0yfCDF_aFRYONT4kifZx0wTGA0KMacT_TKlUt0,3516
|
||||
reactivex/scheduler/trampoline.py,sha256=3sp1sV1NgNJK78enC1jqbReSj7jf_j9GNfibM-SfKcs,1847
|
||||
reactivex/scheduler/trampolinescheduler.py,sha256=mcU14rsCf03kIDbsF0weWH-BJnGul4WoNUYx4yIh9f0,3788
|
||||
reactivex/scheduler/virtualtimescheduler.py,sha256=JbT8K7ewVzubQ3odxfpCI2FNRl3cIHfkv_-cZT10OTM,7693
|
||||
reactivex/subject/__init__.py,sha256=ICiGMqswVSo5wqaZzLF04Tz66pY_zAcyJRff2-XoT7A,229
|
||||
reactivex/subject/asyncsubject.py,sha256=4y7fIOSQmS7lhaEzg-3O7BOPJjRghV49OItPuhefK9g,2569
|
||||
reactivex/subject/behaviorsubject.py,sha256=1WY5d6ntgkUCnn3ZZ3ifvP4yoGUDH08ODVJN7dHRUQI,1997
|
||||
reactivex/subject/innersubscription.py,sha256=sukkq8AQ6WkJfTsLTYh51sUwB3BbR4DsJ9M2Vkyc0qg,703
|
||||
reactivex/subject/replaysubject.py,sha256=07yT1Aq8G5cSKvlsvE4OljKpMCDb3Myh3tCAqnDnMp4,4610
|
||||
reactivex/subject/subject.py,sha256=Q8nj-PHurq2QaNH_tbtJIZ5lRDkNUoen0NDDZjpF3bE,3148
|
||||
reactivex/testing/__init__.py,sha256=hPkeUUVcp0MiwNTn1jii5UZXkJaz51S44GV7U9SA86E,356
|
||||
reactivex/testing/coldobservable.py,sha256=IfXBEpHqD5XdfBsxg90UlVzIIiarew8NbyB6P9e294U,1943
|
||||
reactivex/testing/hotobservable.py,sha256=N89Kj7eS92b_xrSa8ACI9BiMrj-0Ze_gA4dv0GEwKFs,2081
|
||||
reactivex/testing/marbles.py,sha256=DQ9viMf-aqrpUKjLxE6exat9YUjmRBwokWDTK6vVxNI,5765
|
||||
reactivex/testing/mockdisposable.py,sha256=GZxvMeGSwwDI-N1C856XwGPkPdN0CNZkf7C80GQ3fPQ,436
|
||||
reactivex/testing/mockobserver.py,sha256=03y2EOIN5xdZYtEDWlvGQ-ZrTLUdFw3MZfjCDsmnKVs,780
|
||||
reactivex/testing/reactivetest.py,sha256=xgwA9RMu7lhyJVhh6c-QqGX5-CKJ8VWy-sipt-GlBH4,2119
|
||||
reactivex/testing/recorded.py,sha256=8eL6IOZuBb12rp_UAlWiU2YiiKOUkd92PQzBi5pXG8A,1095
|
||||
reactivex/testing/subscription.py,sha256=VCVc6kZJmR8c89rkaAECmFth8NOkz4tUs45PjnnUNnk,701
|
||||
reactivex/testing/testscheduler.py,sha256=CYlbxcFzdfdx2XVXkIVdWTVB9lSC5DoaoxfSRQw63HI,5881
|
||||
reactivex/typing.py,sha256=IRRs3TNKClakoVm26NHRei0ZtEFbKPC27AaKdp7ZzNI,1367
|
||||
@@ -1,20 +0,0 @@
|
||||
# The MIT License
|
||||
|
||||
Copyright 2013-2022, Dag Brattli, Microsoft Corp., and Contributors.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -0,0 +1,3 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: timezonefinder
|
||||
Version: 8.1.0
|
||||
@@ -0,0 +1 @@
|
||||
timezonefinder
|
||||
@@ -0,0 +1,25 @@
|
||||
from timezonefinder.timezonefinder import (
|
||||
TimezoneFinder,
|
||||
TimezoneFinderL,
|
||||
)
|
||||
|
||||
# Import module-level functions
|
||||
from timezonefinder.global_functions import (
|
||||
timezone_at,
|
||||
timezone_at_land,
|
||||
unique_timezone_at,
|
||||
certain_timezone_at,
|
||||
get_geometry,
|
||||
)
|
||||
|
||||
# https://docs.python.org/3/tutorial/modules.html#importing-from-a-package
|
||||
# determines which objects will be imported with "import *"
|
||||
__all__ = (
|
||||
"TimezoneFinder",
|
||||
"TimezoneFinderL",
|
||||
"timezone_at",
|
||||
"timezone_at_land",
|
||||
"unique_timezone_at",
|
||||
"certain_timezone_at",
|
||||
"get_geometry",
|
||||
)
|
||||
@@ -0,0 +1,52 @@
|
||||
"""'transparent' numba functionality replacements
|
||||
|
||||
njit decorator
|
||||
data types
|
||||
|
||||
dtype_2int_tuple = typeof((1, 1))
|
||||
@njit(b1(i4, i4, i4[:, :]), cache=True)
|
||||
@njit(dtype_2int_tuple(f8, f8), cache=True)
|
||||
"""
|
||||
|
||||
|
||||
# decorator
|
||||
def njit(*args, **kwargs):
|
||||
def wrapper(f):
|
||||
return f
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
class SubscriptAndCallable:
|
||||
def __init__(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def __class_getitem__(cls, item):
|
||||
return None
|
||||
|
||||
def __call__(self, arg):
|
||||
# for example int64(1) must work
|
||||
return arg
|
||||
|
||||
|
||||
# DTYPES
|
||||
|
||||
|
||||
class f8(SubscriptAndCallable):
|
||||
pass
|
||||
|
||||
|
||||
class i8(SubscriptAndCallable):
|
||||
pass
|
||||
|
||||
|
||||
class i4(SubscriptAndCallable):
|
||||
pass
|
||||
|
||||
|
||||
class boolean(SubscriptAndCallable):
|
||||
pass
|
||||
|
||||
|
||||
class Array(SubscriptAndCallable):
|
||||
pass
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
"""optionally builds inside polygon algorithm C extension
|
||||
|
||||
Resources:
|
||||
https://github.com/FirefoxMetzger/mini-extension
|
||||
https://stackoverflow.com/questions/60073711/how-to-build-c-extensions-via-poetry
|
||||
https://github.com/libmbd/libmbd/blob/master/build.py
|
||||
"""
|
||||
|
||||
import pathlib
|
||||
import re
|
||||
from typing import Optional
|
||||
import warnings
|
||||
|
||||
import cffi
|
||||
|
||||
EXTENSION_NAME = "inside_polygon_ext"
|
||||
H_FILE_NAME = "inside_polygon_int.h"
|
||||
C_FILE_NAME = "inside_polygon_int.c"
|
||||
EXTENSION_PATH = pathlib.Path("timezonefinder") / "inside_poly_extension"
|
||||
h_file_path = EXTENSION_PATH / H_FILE_NAME
|
||||
c_file_path = EXTENSION_PATH / C_FILE_NAME
|
||||
|
||||
ffibuilder: Optional[cffi.FFI] = None
|
||||
try:
|
||||
ffibuilder = cffi.FFI()
|
||||
except Exception as exc:
|
||||
# Clang extension should be fully optional
|
||||
warnings.warn(
|
||||
f"C lang extension cannot be build, since cffi failed with this error: {exc}"
|
||||
)
|
||||
|
||||
if ffibuilder is not None:
|
||||
ffibuilder.set_source(
|
||||
"timezonefinder." + EXTENSION_NAME,
|
||||
source='#include "inside_polygon_int.h"',
|
||||
sources=[str(c_file_path)],
|
||||
include_dirs=[str(EXTENSION_PATH)],
|
||||
)
|
||||
with open(h_file_path) as h_file:
|
||||
# cffi does not like our preprocessor directives, so we remove them
|
||||
lns = h_file.read().splitlines()
|
||||
flt = filter(lambda ln: not re.match(r" *#", ln), lns)
|
||||
|
||||
ffibuilder.cdef("\n".join(flt))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if ffibuilder:
|
||||
ffibuilder.compile(verbose=True)
|
||||
@@ -0,0 +1,122 @@
|
||||
import argparse
|
||||
import contextlib
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
from typing import Callable, Generator
|
||||
|
||||
from timezonefinder import (
|
||||
TimezoneFinderL,
|
||||
timezone_at,
|
||||
certain_timezone_at,
|
||||
timezone_at_land,
|
||||
)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def redirect_stdout_to_temp_file() -> Generator[str, None, None]:
|
||||
"""
|
||||
Context manager that redirects stdout to a temporary file for the duration of the context.
|
||||
The temporary file is created but not deleted when the context exits.
|
||||
Returns the path to the temporary file.
|
||||
"""
|
||||
# Save the original stdout
|
||||
original_stdout = sys.stdout
|
||||
|
||||
# Create a temporary file that will NOT be automatically deleted
|
||||
temp_fd, temp_path = tempfile.mkstemp(text=True)
|
||||
temp_file = os.fdopen(temp_fd, "w")
|
||||
|
||||
try:
|
||||
# Redirect stdout to the temporary file
|
||||
sys.stdout = temp_file
|
||||
yield temp_path
|
||||
finally:
|
||||
# Restore the original stdout and close the file
|
||||
sys.stdout = original_stdout
|
||||
temp_file.close()
|
||||
|
||||
|
||||
def get_timezone_function(function_id: int) -> Callable:
|
||||
"""
|
||||
Get the appropriate timezone function based on the function ID.
|
||||
Uses global functions when available, otherwise creates instances as needed.
|
||||
"""
|
||||
# Use global functions for TimezoneFinder methods
|
||||
if function_id == 0:
|
||||
return timezone_at
|
||||
elif function_id == 1:
|
||||
return certain_timezone_at
|
||||
elif function_id == 5:
|
||||
return timezone_at_land
|
||||
|
||||
# For TimezoneFinderL methods, still create an instance
|
||||
tf_instance = TimezoneFinderL()
|
||||
functions = {
|
||||
3: tf_instance.timezone_at,
|
||||
4: tf_instance.timezone_at_land,
|
||||
}
|
||||
return functions[function_id]
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description="parse TimezoneFinder parameters")
|
||||
parser.add_argument("lng", type=float, help="longitude to be queried")
|
||||
parser.add_argument("lat", type=float, help="latitude to be queried")
|
||||
parser.add_argument("-v", action="store_true", help="verbosity flag")
|
||||
parser.add_argument(
|
||||
"-f",
|
||||
"--function",
|
||||
type=int,
|
||||
choices=[0, 1, 3, 4, 5],
|
||||
default=0,
|
||||
help="function to be called:"
|
||||
"0: TimezoneFinder.timezone_at(), "
|
||||
"1: TimezoneFinder.certain_timezone_at(), "
|
||||
"2: removed, "
|
||||
"3: TimezoneFinderL.timezone_at(), "
|
||||
"4: TimezoneFinderL.timezone_at_land(), "
|
||||
"5: TimezoneFinder.timezone_at_land(), ",
|
||||
)
|
||||
parsed_args = parser.parse_args() # takes input from sys.argv
|
||||
timezone_function = get_timezone_function(parsed_args.function)
|
||||
|
||||
verbose_mode = parsed_args.v
|
||||
|
||||
# Always redirect stdout to a temp file
|
||||
with redirect_stdout_to_temp_file() as temp_file_path:
|
||||
print("\n" + "=" * 60)
|
||||
print("TIMEZONEFINDER LOOKUP DETAILS")
|
||||
print("-" * 60)
|
||||
print(f"Coordinates: {parsed_args.lat:.6f}°, {parsed_args.lng:.6f}° (lat, lng)")
|
||||
print(
|
||||
f"Function {timezone_function.__name__} (function ID: {parsed_args.function})"
|
||||
)
|
||||
|
||||
# Execute the timezone function
|
||||
tz = timezone_function(lng=parsed_args.lng, lat=parsed_args.lat)
|
||||
|
||||
if tz:
|
||||
print(f"Result: Found timezone '{tz}'")
|
||||
else:
|
||||
print("Result: No timezone found at this location")
|
||||
print("=" * 60)
|
||||
|
||||
if verbose_mode:
|
||||
# In verbose mode, print the contents of the temp file
|
||||
try:
|
||||
with open(temp_file_path) as f:
|
||||
captured_output = f.read().strip()
|
||||
if captured_output:
|
||||
print(captured_output)
|
||||
except Exception as e:
|
||||
print(f"Warning: Could not read captured output: {e}")
|
||||
else:
|
||||
# In non-verbose mode, just print the result
|
||||
print(tz if tz else "")
|
||||
|
||||
# Always clean up the temp file
|
||||
try:
|
||||
os.remove(temp_file_path)
|
||||
except Exception:
|
||||
pass
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Tuple, Union
|
||||
|
||||
import numpy as np
|
||||
|
||||
# SHORTCUT SETTINGS
|
||||
# h3 library
|
||||
SHORTCUT_H3_RES: int = 3
|
||||
|
||||
OCEAN_TIMEZONE_PREFIX = r"Etc/GMT"
|
||||
|
||||
# PATHS
|
||||
PACKAGE_DIR = Path(__file__).parent
|
||||
DEFAULT_DATA_DIR = PACKAGE_DIR / "data"
|
||||
|
||||
|
||||
# i = signed 4byte integer
|
||||
NR_BYTES_I = 4
|
||||
# IMPORTANT: all values between -180 and 180 degree must fit into the domain of i4!
|
||||
# is the same as testing if 360 fits into the domain of I4 (unsigned!)
|
||||
MAX_ALLOWED_COORD_VAL = 2 ** (8 * NR_BYTES_I - 1)
|
||||
|
||||
# from math import floor,log10
|
||||
# DECIMAL_PLACES_SHIFT = floor(log10(MAX_ALLOWED_COORD_VAL/180.0)) # == 7
|
||||
DECIMAL_PLACES_SHIFT = 7
|
||||
INT2COORD_FACTOR = 10 ** (-DECIMAL_PLACES_SHIFT)
|
||||
COORD2INT_FACTOR = 10**DECIMAL_PLACES_SHIFT
|
||||
MAX_LNG_VAL = 180.0
|
||||
MAX_LAT_VAL = 90.0
|
||||
MAX_LNG_VAL_INT = int(MAX_LNG_VAL * COORD2INT_FACTOR)
|
||||
MAX_LAT_VAL_INT = int(MAX_LAT_VAL * COORD2INT_FACTOR)
|
||||
MAX_INT_VAL = MAX_LNG_VAL_INT
|
||||
assert MAX_INT_VAL < MAX_ALLOWED_COORD_VAL
|
||||
|
||||
# TYPES
|
||||
# used in Numba JIT compiled function signatures in utils_numba.py
|
||||
# NOTE: Changes in the global settings might not immediately affect
|
||||
# the functions due to caching!
|
||||
|
||||
# Type alias for flexibility with integer types (pure int or numpy integer scalars)
|
||||
IntegerLike = Union[int, np.integer]
|
||||
|
||||
# hexagon id to list of polygon ids
|
||||
ShortcutMapping = Dict[int, np.ndarray]
|
||||
CoordPairs = List[Tuple[float, float]]
|
||||
CoordLists = List[List[float]]
|
||||
IntLists = List[List[int]]
|
||||
|
||||
|
||||
# zone id storage settings ---------------------------------------------------
|
||||
|
||||
_ZONE_ID_DTYPE_ALIASES: Dict[str, "np.dtype[Any]"] = {
|
||||
"uint8": np.dtype("<u1"),
|
||||
"uint16": np.dtype("<u2"),
|
||||
}
|
||||
|
||||
|
||||
def _normalise_zone_id_dtype_key(key: str) -> str:
|
||||
"""Normalise user provided dtype keys to canonical form."""
|
||||
return key.lower().strip()
|
||||
|
||||
|
||||
def get_zone_id_dtype(name: str) -> "np.dtype[Any]":
|
||||
"""Return the configured numpy dtype for storing zone IDs."""
|
||||
|
||||
try:
|
||||
return _ZONE_ID_DTYPE_ALIASES[_normalise_zone_id_dtype_key(name)]
|
||||
except KeyError as exc: # pragma: no cover - defensive, validated on import
|
||||
valid = ", ".join(sorted(_ZONE_ID_DTYPE_ALIASES))
|
||||
raise ValueError(
|
||||
f"Unsupported zone id dtype '{name}'. Choose one of: {valid}"
|
||||
) from exc
|
||||
|
||||
|
||||
def zone_id_dtype_to_string(dtype: np.dtype) -> str:
|
||||
"""Return the little-endian numpy dtype string for serialisation."""
|
||||
|
||||
return dtype.newbyteorder("<").str
|
||||
|
||||
|
||||
def available_zone_id_dtype_names() -> Tuple[str, ...]:
|
||||
"""Return the supported zone id dtype names."""
|
||||
|
||||
return tuple(sorted(_ZONE_ID_DTYPE_ALIASES))
|
||||
|
||||
|
||||
DEFAULT_ZONE_ID_DTYPE_NAME = os.getenv("TIMEZONEFINDER_ZONE_ID_DTYPE", "uint8")
|
||||
DEFAULT_ZONE_ID_DTYPE = get_zone_id_dtype(DEFAULT_ZONE_ID_DTYPE_NAME)
|
||||
@@ -0,0 +1,173 @@
|
||||
"""
|
||||
Coordinate accessors for timezonefinder.
|
||||
|
||||
This module provides classes for accessing polygon coordinates
|
||||
either directly from file or from preloaded memory.
|
||||
"""
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
import mmap
|
||||
from pathlib import Path
|
||||
from typing import Dict
|
||||
|
||||
import numpy as np
|
||||
|
||||
from timezonefinder import utils
|
||||
from timezonefinder.flatbuf.generated.polygons.PolygonCollection import (
|
||||
PolygonCollection,
|
||||
)
|
||||
from timezonefinder.flatbuf.io.polygons import (
|
||||
get_polygon_collection,
|
||||
read_polygon_array_from_binary,
|
||||
)
|
||||
|
||||
|
||||
class AbstractCoordAccessor(ABC):
|
||||
"""Abstract base class defining the interface for coordinate accessors."""
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self, coordinate_file_path: Path):
|
||||
"""
|
||||
Initialize the coordinate accessor.
|
||||
|
||||
Args:
|
||||
coordinate_file_path: Path to the coordinate file
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def __getitem__(self, idx: int) -> np.ndarray:
|
||||
"""
|
||||
Get the polygon coordinates for the given index.
|
||||
|
||||
Args:
|
||||
idx: The polygon index
|
||||
|
||||
Returns:
|
||||
A numpy array containing the polygon coordinates
|
||||
"""
|
||||
pass
|
||||
|
||||
def __del__(self):
|
||||
"""
|
||||
Ensure resources are cleaned up when the object is destroyed.
|
||||
"""
|
||||
self.cleanup()
|
||||
|
||||
@abstractmethod
|
||||
def cleanup(self) -> None:
|
||||
"""Clean up resources."""
|
||||
pass
|
||||
|
||||
|
||||
class FileCoordAccessor(AbstractCoordAccessor):
|
||||
"""Accessor that reads polygon coordinates from the file on demand."""
|
||||
|
||||
def __init__(self, coordinate_file_path: Path):
|
||||
"""
|
||||
Initialize the file-based coordinate accessor.
|
||||
|
||||
Args:
|
||||
coordinate_file_path: Path to the coordinate file
|
||||
"""
|
||||
self.coordinate_file_path = coordinate_file_path
|
||||
# Initialize file resources using proper resource management.
|
||||
try:
|
||||
# Use memory-mapped file for on-demand reading
|
||||
self.coord_file: object = open(self.coordinate_file_path, "rb")
|
||||
# Create memory map
|
||||
self.coord_buf: mmap.mmap = mmap.mmap(
|
||||
self.coord_file.fileno(), 0, access=mmap.ACCESS_READ
|
||||
)
|
||||
self.polygon_collection: PolygonCollection = get_polygon_collection(
|
||||
self.coord_buf
|
||||
)
|
||||
except Exception:
|
||||
# Clean up any partially initialized resources
|
||||
self.cleanup()
|
||||
raise
|
||||
|
||||
def __getitem__(self, idx: int) -> np.ndarray:
|
||||
"""
|
||||
Get the polygon coordinates for the given index.
|
||||
|
||||
Args:
|
||||
idx: The polygon index
|
||||
|
||||
Returns:
|
||||
A numpy array containing the polygon coordinates
|
||||
"""
|
||||
return read_polygon_array_from_binary(self.polygon_collection, idx)
|
||||
|
||||
def cleanup(self) -> None:
|
||||
"""Clean up resources."""
|
||||
utils.close_resource(self.coord_file)
|
||||
utils.close_resource(self.coord_buf)
|
||||
del self.polygon_collection
|
||||
|
||||
|
||||
class MemoryCoordAccessor(AbstractCoordAccessor):
|
||||
"""Accessor that preloads all polygon coordinates into memory."""
|
||||
|
||||
def __init__(self, coordinate_file_path: Path):
|
||||
"""
|
||||
Initialize the memory-based coordinate accessor.
|
||||
|
||||
Args:
|
||||
coordinate_file_path: Path to the coordinate file
|
||||
"""
|
||||
# Read entire file into memory
|
||||
with open(coordinate_file_path, "rb") as f:
|
||||
coord_buf = f.read()
|
||||
|
||||
# Initialize polygon collection
|
||||
polygon_collection = get_polygon_collection(coord_buf)
|
||||
|
||||
# Get number of polygons
|
||||
num_polygons = polygon_collection.PolygonsLength()
|
||||
|
||||
# Preload all polygons
|
||||
self.polygons: Dict[int, np.ndarray] = {}
|
||||
for idx in range(num_polygons):
|
||||
self.polygons[idx] = read_polygon_array_from_binary(polygon_collection, idx)
|
||||
|
||||
# Once polygons are loaded, we don't need to keep polygon_collection or coord_buf references
|
||||
# They'll be garbage collected
|
||||
|
||||
def __getitem__(self, idx: int) -> np.ndarray:
|
||||
"""
|
||||
Get the polygon coordinates for the given index.
|
||||
|
||||
Args:
|
||||
idx: The polygon index
|
||||
|
||||
Returns:
|
||||
A numpy array containing the polygon coordinates
|
||||
"""
|
||||
return self.polygons[idx]
|
||||
|
||||
def cleanup(self) -> None:
|
||||
"""Clean up resources."""
|
||||
del self.polygons
|
||||
# Just clear the dictionary, no file resources to clean up
|
||||
if hasattr(self, "polygons"):
|
||||
self.polygons.clear()
|
||||
|
||||
|
||||
def create_coord_accessor(
|
||||
coordinate_file_path: Path, in_memory: bool
|
||||
) -> AbstractCoordAccessor:
|
||||
"""
|
||||
Factory function to create the appropriate coordinate accessor.
|
||||
|
||||
Args:
|
||||
coordinate_file_path: Path to the coordinate file
|
||||
in_memory: Whether to use in-memory mode
|
||||
|
||||
Returns:
|
||||
An instance of a coordinate accessor
|
||||
"""
|
||||
if in_memory:
|
||||
return MemoryCoordAccessor(coordinate_file_path)
|
||||
else:
|
||||
return FileCoordAccessor(coordinate_file_path)
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,302 @@
|
||||
{
|
||||
"10": [
|
||||
1,
|
||||
0
|
||||
],
|
||||
"151": [
|
||||
2,
|
||||
21
|
||||
],
|
||||
"153": [
|
||||
1,
|
||||
23
|
||||
],
|
||||
"155": [
|
||||
2,
|
||||
24
|
||||
],
|
||||
"167": [
|
||||
1,
|
||||
26
|
||||
],
|
||||
"177": [
|
||||
1,
|
||||
27
|
||||
],
|
||||
"19": [
|
||||
3,
|
||||
1
|
||||
],
|
||||
"208": [
|
||||
1,
|
||||
28
|
||||
],
|
||||
"218": [
|
||||
21,
|
||||
29
|
||||
],
|
||||
"231": [
|
||||
1,
|
||||
50
|
||||
],
|
||||
"268": [
|
||||
2,
|
||||
51
|
||||
],
|
||||
"316": [
|
||||
8,
|
||||
53
|
||||
],
|
||||
"389": [
|
||||
3,
|
||||
61
|
||||
],
|
||||
"391": [
|
||||
2,
|
||||
64
|
||||
],
|
||||
"40": [
|
||||
8,
|
||||
4
|
||||
],
|
||||
"41": [
|
||||
6,
|
||||
12
|
||||
],
|
||||
"410": [
|
||||
5,
|
||||
66
|
||||
],
|
||||
"414": [
|
||||
2,
|
||||
71
|
||||
],
|
||||
"481": [
|
||||
1,
|
||||
73
|
||||
],
|
||||
"488": [
|
||||
2,
|
||||
74
|
||||
],
|
||||
"515": [
|
||||
1,
|
||||
76
|
||||
],
|
||||
"518": [
|
||||
1,
|
||||
77
|
||||
],
|
||||
"522": [
|
||||
16,
|
||||
78
|
||||
],
|
||||
"685": [
|
||||
2,
|
||||
94
|
||||
],
|
||||
"721": [
|
||||
15,
|
||||
96
|
||||
],
|
||||
"725": [
|
||||
44,
|
||||
111
|
||||
],
|
||||
"728": [
|
||||
2,
|
||||
155
|
||||
],
|
||||
"729": [
|
||||
37,
|
||||
157
|
||||
],
|
||||
"730": [
|
||||
20,
|
||||
194
|
||||
],
|
||||
"733": [
|
||||
1,
|
||||
214
|
||||
],
|
||||
"736": [
|
||||
28,
|
||||
215
|
||||
],
|
||||
"737": [
|
||||
3,
|
||||
243
|
||||
],
|
||||
"741": [
|
||||
1,
|
||||
246
|
||||
],
|
||||
"742": [
|
||||
17,
|
||||
247
|
||||
],
|
||||
"743": [
|
||||
4,
|
||||
264
|
||||
],
|
||||
"748": [
|
||||
2,
|
||||
268
|
||||
],
|
||||
"750": [
|
||||
1,
|
||||
270
|
||||
],
|
||||
"753": [
|
||||
2,
|
||||
271
|
||||
],
|
||||
"754": [
|
||||
5,
|
||||
273
|
||||
],
|
||||
"755": [
|
||||
3,
|
||||
278
|
||||
],
|
||||
"756": [
|
||||
14,
|
||||
281
|
||||
],
|
||||
"761": [
|
||||
12,
|
||||
295
|
||||
],
|
||||
"762": [
|
||||
3,
|
||||
307
|
||||
],
|
||||
"765": [
|
||||
1,
|
||||
310
|
||||
],
|
||||
"769": [
|
||||
1,
|
||||
311
|
||||
],
|
||||
"771": [
|
||||
7,
|
||||
312
|
||||
],
|
||||
"776": [
|
||||
21,
|
||||
319
|
||||
],
|
||||
"781": [
|
||||
3,
|
||||
340
|
||||
],
|
||||
"790": [
|
||||
1,
|
||||
343
|
||||
],
|
||||
"793": [
|
||||
5,
|
||||
344
|
||||
],
|
||||
"800": [
|
||||
2,
|
||||
349
|
||||
],
|
||||
"804": [
|
||||
1,
|
||||
351
|
||||
],
|
||||
"806": [
|
||||
2,
|
||||
352
|
||||
],
|
||||
"809": [
|
||||
2,
|
||||
354
|
||||
],
|
||||
"810": [
|
||||
4,
|
||||
356
|
||||
],
|
||||
"812": [
|
||||
13,
|
||||
360
|
||||
],
|
||||
"814": [
|
||||
17,
|
||||
373
|
||||
],
|
||||
"817": [
|
||||
2,
|
||||
390
|
||||
],
|
||||
"819": [
|
||||
1,
|
||||
392
|
||||
],
|
||||
"820": [
|
||||
11,
|
||||
393
|
||||
],
|
||||
"824": [
|
||||
2,
|
||||
404
|
||||
],
|
||||
"828": [
|
||||
13,
|
||||
406
|
||||
],
|
||||
"829": [
|
||||
1,
|
||||
419
|
||||
],
|
||||
"830": [
|
||||
4,
|
||||
420
|
||||
],
|
||||
"833": [
|
||||
6,
|
||||
424
|
||||
],
|
||||
"834": [
|
||||
13,
|
||||
430
|
||||
],
|
||||
"838": [
|
||||
6,
|
||||
443
|
||||
],
|
||||
"841": [
|
||||
4,
|
||||
449
|
||||
],
|
||||
"844": [
|
||||
32,
|
||||
453
|
||||
],
|
||||
"848": [
|
||||
34,
|
||||
485
|
||||
],
|
||||
"851": [
|
||||
37,
|
||||
519
|
||||
],
|
||||
"854": [
|
||||
22,
|
||||
556
|
||||
],
|
||||
"855": [
|
||||
1,
|
||||
578
|
||||
],
|
||||
"91": [
|
||||
1,
|
||||
18
|
||||
],
|
||||
"98": [
|
||||
2,
|
||||
19
|
||||
]
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,92 @@
|
||||
Etc/UTC
|
||||
Africa/Abidjan
|
||||
Europe/Moscow
|
||||
Africa/Lagos
|
||||
Africa/Johannesburg
|
||||
Africa/Cairo
|
||||
Africa/Casablanca
|
||||
Europe/Paris
|
||||
America/Adak
|
||||
America/Anchorage
|
||||
America/Caracas
|
||||
America/Sao_Paulo
|
||||
America/Lima
|
||||
America/Mexico_City
|
||||
America/Denver
|
||||
America/Chicago
|
||||
America/Phoenix
|
||||
America/New_York
|
||||
America/Halifax
|
||||
America/Havana
|
||||
America/Los_Angeles
|
||||
America/Miquelon
|
||||
America/Noronha
|
||||
America/Nuuk
|
||||
America/Santiago
|
||||
America/St_Johns
|
||||
Asia/Manila
|
||||
Asia/Jakarta
|
||||
Australia/Brisbane
|
||||
Australia/Sydney
|
||||
Asia/Karachi
|
||||
Pacific/Auckland
|
||||
Antarctica/Troll
|
||||
Pacific/Fiji
|
||||
Asia/Dubai
|
||||
Asia/Beirut
|
||||
Asia/Dhaka
|
||||
Asia/Tokyo
|
||||
Asia/Kolkata
|
||||
Europe/Athens
|
||||
Asia/Gaza
|
||||
Asia/Jerusalem
|
||||
Asia/Kabul
|
||||
Asia/Kathmandu
|
||||
Asia/Sakhalin
|
||||
Asia/Tehran
|
||||
Asia/Yangon
|
||||
Atlantic/Azores
|
||||
Europe/Lisbon
|
||||
Atlantic/Cape_Verde
|
||||
Australia/Adelaide
|
||||
Australia/Darwin
|
||||
Australia/Eucla
|
||||
Australia/Lord_Howe
|
||||
Europe/Chisinau
|
||||
Europe/Dublin
|
||||
Europe/London
|
||||
Pacific/Tongatapu
|
||||
Pacific/Chatham
|
||||
Pacific/Easter
|
||||
Pacific/Gambier
|
||||
Pacific/Honolulu
|
||||
Pacific/Kiritimati
|
||||
Pacific/Marquesas
|
||||
Pacific/Pago_Pago
|
||||
Pacific/Norfolk
|
||||
Pacific/Pitcairn
|
||||
Etc/GMT-12
|
||||
Etc/GMT-11
|
||||
Etc/GMT-10
|
||||
Etc/GMT-9
|
||||
Etc/GMT-8
|
||||
Etc/GMT-7
|
||||
Etc/GMT-6
|
||||
Etc/GMT-5
|
||||
Etc/GMT-4
|
||||
Etc/GMT-3
|
||||
Etc/GMT-2
|
||||
Etc/GMT-1
|
||||
Etc/GMT
|
||||
Etc/GMT+1
|
||||
Etc/GMT+2
|
||||
Etc/GMT+3
|
||||
Etc/GMT+4
|
||||
Etc/GMT+5
|
||||
Etc/GMT+6
|
||||
Etc/GMT+7
|
||||
Etc/GMT+8
|
||||
Etc/GMT+9
|
||||
Etc/GMT+10
|
||||
Etc/GMT+11
|
||||
Etc/GMT+12
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,5 @@
|
||||
"""FlatBuffer schemas, bindings, and IO helpers used by timezonefinder."""
|
||||
|
||||
from . import generated, io, schemas
|
||||
|
||||
__all__ = ["generated", "io", "schemas"]
|
||||
@@ -0,0 +1,7 @@
|
||||
"""Auto-generated FlatBuffer bindings grouped by domain."""
|
||||
|
||||
__all__ = [
|
||||
"polygons",
|
||||
"shortcuts_uint8",
|
||||
"shortcuts_uint16",
|
||||
]
|
||||
@@ -0,0 +1,92 @@
|
||||
# automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
# namespace: polygons
|
||||
|
||||
import flatbuffers
|
||||
from flatbuffers.compat import import_numpy
|
||||
|
||||
np = import_numpy()
|
||||
|
||||
|
||||
class Polygon:
|
||||
__slots__ = ["_tab"]
|
||||
|
||||
@classmethod
|
||||
def GetRootAs(cls, buf, offset=0):
|
||||
n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
|
||||
x = Polygon()
|
||||
x.Init(buf, n + offset)
|
||||
return x
|
||||
|
||||
@classmethod
|
||||
def GetRootAsPolygon(cls, buf, offset=0):
|
||||
"""This method is deprecated. Please switch to GetRootAs."""
|
||||
return cls.GetRootAs(buf, offset)
|
||||
|
||||
# Polygon
|
||||
def Init(self, buf, pos):
|
||||
self._tab = flatbuffers.table.Table(buf, pos)
|
||||
|
||||
# Polygon
|
||||
def Coords(self, j):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
|
||||
if o != 0:
|
||||
a = self._tab.Vector(o)
|
||||
return self._tab.Get(
|
||||
flatbuffers.number_types.Int32Flags,
|
||||
a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4),
|
||||
)
|
||||
return 0
|
||||
|
||||
# Polygon
|
||||
def CoordsAsNumpy(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
|
||||
if o != 0:
|
||||
return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int32Flags, o)
|
||||
return 0
|
||||
|
||||
# Polygon
|
||||
def CoordsLength(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
|
||||
if o != 0:
|
||||
return self._tab.VectorLen(o)
|
||||
return 0
|
||||
|
||||
# Polygon
|
||||
def CoordsIsNone(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
|
||||
return o == 0
|
||||
|
||||
|
||||
def PolygonStart(builder):
|
||||
builder.StartObject(1)
|
||||
|
||||
|
||||
def Start(builder):
|
||||
PolygonStart(builder)
|
||||
|
||||
|
||||
def PolygonAddCoords(builder, coords):
|
||||
builder.PrependUOffsetTRelativeSlot(
|
||||
0, flatbuffers.number_types.UOffsetTFlags.py_type(coords), 0
|
||||
)
|
||||
|
||||
|
||||
def AddCoords(builder, coords):
|
||||
PolygonAddCoords(builder, coords)
|
||||
|
||||
|
||||
def PolygonStartCoordsVector(builder, numElems):
|
||||
return builder.StartVector(4, numElems, 4)
|
||||
|
||||
|
||||
def StartCoordsVector(builder, numElems):
|
||||
return PolygonStartCoordsVector(builder, numElems)
|
||||
|
||||
|
||||
def PolygonEnd(builder):
|
||||
return builder.EndObject()
|
||||
|
||||
|
||||
def End(builder):
|
||||
return PolygonEnd(builder)
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
# automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
# namespace: polygons
|
||||
|
||||
import flatbuffers
|
||||
from flatbuffers.compat import import_numpy
|
||||
|
||||
np = import_numpy()
|
||||
|
||||
|
||||
class PolygonCollection:
|
||||
__slots__ = ["_tab"]
|
||||
|
||||
@classmethod
|
||||
def GetRootAs(cls, buf, offset=0):
|
||||
n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
|
||||
x = PolygonCollection()
|
||||
x.Init(buf, n + offset)
|
||||
return x
|
||||
|
||||
@classmethod
|
||||
def GetRootAsPolygonCollection(cls, buf, offset=0):
|
||||
"""This method is deprecated. Please switch to GetRootAs."""
|
||||
return cls.GetRootAs(buf, offset)
|
||||
|
||||
# PolygonCollection
|
||||
def Init(self, buf, pos):
|
||||
self._tab = flatbuffers.table.Table(buf, pos)
|
||||
|
||||
# PolygonCollection
|
||||
def Polygons(self, j):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
|
||||
if o != 0:
|
||||
x = self._tab.Vector(o)
|
||||
x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4
|
||||
x = self._tab.Indirect(x)
|
||||
from timezonefinder.flatbuf.generated.polygons.Polygon import Polygon
|
||||
|
||||
obj = Polygon()
|
||||
obj.Init(self._tab.Bytes, x)
|
||||
return obj
|
||||
return None
|
||||
|
||||
# PolygonCollection
|
||||
def PolygonsLength(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
|
||||
if o != 0:
|
||||
return self._tab.VectorLen(o)
|
||||
return 0
|
||||
|
||||
# PolygonCollection
|
||||
def PolygonsIsNone(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
|
||||
return o == 0
|
||||
|
||||
|
||||
def PolygonCollectionStart(builder):
|
||||
builder.StartObject(1)
|
||||
|
||||
|
||||
def Start(builder):
|
||||
PolygonCollectionStart(builder)
|
||||
|
||||
|
||||
def PolygonCollectionAddPolygons(builder, polygons):
|
||||
builder.PrependUOffsetTRelativeSlot(
|
||||
0, flatbuffers.number_types.UOffsetTFlags.py_type(polygons), 0
|
||||
)
|
||||
|
||||
|
||||
def AddPolygons(builder, polygons):
|
||||
PolygonCollectionAddPolygons(builder, polygons)
|
||||
|
||||
|
||||
def PolygonCollectionStartPolygonsVector(builder, numElems):
|
||||
return builder.StartVector(4, numElems, 4)
|
||||
|
||||
|
||||
def StartPolygonsVector(builder, numElems):
|
||||
return PolygonCollectionStartPolygonsVector(builder, numElems)
|
||||
|
||||
|
||||
def PolygonCollectionEnd(builder):
|
||||
return builder.EndObject()
|
||||
|
||||
|
||||
def End(builder):
|
||||
return PolygonCollectionEnd(builder)
|
||||
Vendored
+90
@@ -0,0 +1,90 @@
|
||||
# automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
# namespace: shortcuts_uint16
|
||||
|
||||
import flatbuffers
|
||||
from flatbuffers.compat import import_numpy
|
||||
|
||||
np = import_numpy()
|
||||
|
||||
|
||||
class HybridShortcutCollection:
|
||||
__slots__ = ["_tab"]
|
||||
|
||||
@classmethod
|
||||
def GetRootAs(cls, buf, offset=0):
|
||||
n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
|
||||
x = HybridShortcutCollection()
|
||||
x.Init(buf, n + offset)
|
||||
return x
|
||||
|
||||
@classmethod
|
||||
def GetRootAsHybridShortcutCollection(cls, buf, offset=0):
|
||||
"""This method is deprecated. Please switch to GetRootAs."""
|
||||
return cls.GetRootAs(buf, offset)
|
||||
|
||||
# HybridShortcutCollection
|
||||
def Init(self, buf, pos):
|
||||
self._tab = flatbuffers.table.Table(buf, pos)
|
||||
|
||||
# HybridShortcutCollection
|
||||
def Entries(self, j):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
|
||||
if o != 0:
|
||||
x = self._tab.Vector(o)
|
||||
x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4
|
||||
x = self._tab.Indirect(x)
|
||||
from timezonefinder.flatbuf.generated.shortcuts_uint16.HybridShortcutEntry import (
|
||||
HybridShortcutEntry,
|
||||
)
|
||||
|
||||
obj = HybridShortcutEntry()
|
||||
obj.Init(self._tab.Bytes, x)
|
||||
return obj
|
||||
return None
|
||||
|
||||
# HybridShortcutCollection
|
||||
def EntriesLength(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
|
||||
if o != 0:
|
||||
return self._tab.VectorLen(o)
|
||||
return 0
|
||||
|
||||
# HybridShortcutCollection
|
||||
def EntriesIsNone(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
|
||||
return o == 0
|
||||
|
||||
|
||||
def HybridShortcutCollectionStart(builder):
|
||||
builder.StartObject(1)
|
||||
|
||||
|
||||
def Start(builder):
|
||||
HybridShortcutCollectionStart(builder)
|
||||
|
||||
|
||||
def HybridShortcutCollectionAddEntries(builder, entries):
|
||||
builder.PrependUOffsetTRelativeSlot(
|
||||
0, flatbuffers.number_types.UOffsetTFlags.py_type(entries), 0
|
||||
)
|
||||
|
||||
|
||||
def AddEntries(builder, entries):
|
||||
HybridShortcutCollectionAddEntries(builder, entries)
|
||||
|
||||
|
||||
def HybridShortcutCollectionStartEntriesVector(builder, numElems):
|
||||
return builder.StartVector(4, numElems, 4)
|
||||
|
||||
|
||||
def StartEntriesVector(builder, numElems):
|
||||
return HybridShortcutCollectionStartEntriesVector(builder, numElems)
|
||||
|
||||
|
||||
def HybridShortcutCollectionEnd(builder):
|
||||
return builder.EndObject()
|
||||
|
||||
|
||||
def End(builder):
|
||||
return HybridShortcutCollectionEnd(builder)
|
||||
Vendored
+97
@@ -0,0 +1,97 @@
|
||||
# automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
# namespace: shortcuts_uint16
|
||||
|
||||
import flatbuffers
|
||||
from flatbuffers.compat import import_numpy
|
||||
|
||||
np = import_numpy()
|
||||
|
||||
|
||||
class HybridShortcutEntry:
|
||||
__slots__ = ["_tab"]
|
||||
|
||||
@classmethod
|
||||
def GetRootAs(cls, buf, offset=0):
|
||||
n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
|
||||
x = HybridShortcutEntry()
|
||||
x.Init(buf, n + offset)
|
||||
return x
|
||||
|
||||
@classmethod
|
||||
def GetRootAsHybridShortcutEntry(cls, buf, offset=0):
|
||||
"""This method is deprecated. Please switch to GetRootAs."""
|
||||
return cls.GetRootAs(buf, offset)
|
||||
|
||||
# HybridShortcutEntry
|
||||
def Init(self, buf, pos):
|
||||
self._tab = flatbuffers.table.Table(buf, pos)
|
||||
|
||||
# HybridShortcutEntry
|
||||
def HexId(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
|
||||
if o != 0:
|
||||
return self._tab.Get(
|
||||
flatbuffers.number_types.Uint64Flags, o + self._tab.Pos
|
||||
)
|
||||
return 0
|
||||
|
||||
# HybridShortcutEntry
|
||||
def ValueType(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
|
||||
if o != 0:
|
||||
return self._tab.Get(flatbuffers.number_types.Uint8Flags, o + self._tab.Pos)
|
||||
return 0
|
||||
|
||||
# HybridShortcutEntry
|
||||
def Value(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
|
||||
if o != 0:
|
||||
from flatbuffers.table import Table
|
||||
|
||||
obj = Table(bytearray(), 0)
|
||||
self._tab.Union(obj, o)
|
||||
return obj
|
||||
return None
|
||||
|
||||
|
||||
def HybridShortcutEntryStart(builder):
|
||||
builder.StartObject(3)
|
||||
|
||||
|
||||
def Start(builder):
|
||||
HybridShortcutEntryStart(builder)
|
||||
|
||||
|
||||
def HybridShortcutEntryAddHexId(builder, hexId):
|
||||
builder.PrependUint64Slot(0, hexId, 0)
|
||||
|
||||
|
||||
def AddHexId(builder, hexId):
|
||||
HybridShortcutEntryAddHexId(builder, hexId)
|
||||
|
||||
|
||||
def HybridShortcutEntryAddValueType(builder, valueType):
|
||||
builder.PrependUint8Slot(1, valueType, 0)
|
||||
|
||||
|
||||
def AddValueType(builder, valueType):
|
||||
HybridShortcutEntryAddValueType(builder, valueType)
|
||||
|
||||
|
||||
def HybridShortcutEntryAddValue(builder, value):
|
||||
builder.PrependUOffsetTRelativeSlot(
|
||||
2, flatbuffers.number_types.UOffsetTFlags.py_type(value), 0
|
||||
)
|
||||
|
||||
|
||||
def AddValue(builder, value):
|
||||
HybridShortcutEntryAddValue(builder, value)
|
||||
|
||||
|
||||
def HybridShortcutEntryEnd(builder):
|
||||
return builder.EndObject()
|
||||
|
||||
|
||||
def End(builder):
|
||||
return HybridShortcutEntryEnd(builder)
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
# automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
# namespace: shortcuts_uint16
|
||||
|
||||
import flatbuffers
|
||||
from flatbuffers.compat import import_numpy
|
||||
|
||||
np = import_numpy()
|
||||
|
||||
|
||||
class PolygonList:
|
||||
__slots__ = ["_tab"]
|
||||
|
||||
@classmethod
|
||||
def GetRootAs(cls, buf, offset=0):
|
||||
n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
|
||||
x = PolygonList()
|
||||
x.Init(buf, n + offset)
|
||||
return x
|
||||
|
||||
@classmethod
|
||||
def GetRootAsPolygonList(cls, buf, offset=0):
|
||||
"""This method is deprecated. Please switch to GetRootAs."""
|
||||
return cls.GetRootAs(buf, offset)
|
||||
|
||||
# PolygonList
|
||||
def Init(self, buf, pos):
|
||||
self._tab = flatbuffers.table.Table(buf, pos)
|
||||
|
||||
# PolygonList
|
||||
def PolyIds(self, j):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
|
||||
if o != 0:
|
||||
a = self._tab.Vector(o)
|
||||
return self._tab.Get(
|
||||
flatbuffers.number_types.Uint16Flags,
|
||||
a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 2),
|
||||
)
|
||||
return 0
|
||||
|
||||
# PolygonList
|
||||
def PolyIdsAsNumpy(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
|
||||
if o != 0:
|
||||
return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Uint16Flags, o)
|
||||
return 0
|
||||
|
||||
# PolygonList
|
||||
def PolyIdsLength(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
|
||||
if o != 0:
|
||||
return self._tab.VectorLen(o)
|
||||
return 0
|
||||
|
||||
# PolygonList
|
||||
def PolyIdsIsNone(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
|
||||
return o == 0
|
||||
|
||||
|
||||
def PolygonListStart(builder):
|
||||
builder.StartObject(1)
|
||||
|
||||
|
||||
def Start(builder):
|
||||
PolygonListStart(builder)
|
||||
|
||||
|
||||
def PolygonListAddPolyIds(builder, polyIds):
|
||||
builder.PrependUOffsetTRelativeSlot(
|
||||
0, flatbuffers.number_types.UOffsetTFlags.py_type(polyIds), 0
|
||||
)
|
||||
|
||||
|
||||
def AddPolyIds(builder, polyIds):
|
||||
PolygonListAddPolyIds(builder, polyIds)
|
||||
|
||||
|
||||
def PolygonListStartPolyIdsVector(builder, numElems):
|
||||
return builder.StartVector(2, numElems, 2)
|
||||
|
||||
|
||||
def StartPolyIdsVector(builder, numElems):
|
||||
return PolygonListStartPolyIdsVector(builder, numElems)
|
||||
|
||||
|
||||
def PolygonListEnd(builder):
|
||||
return builder.EndObject()
|
||||
|
||||
|
||||
def End(builder):
|
||||
return PolygonListEnd(builder)
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
# automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
# namespace: shortcuts_uint16
|
||||
|
||||
|
||||
class ShortcutValue:
|
||||
NONE = 0
|
||||
UniqueZone = 1
|
||||
PolygonList = 2
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
# automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
# namespace: shortcuts_uint16
|
||||
|
||||
import flatbuffers
|
||||
from flatbuffers.compat import import_numpy
|
||||
|
||||
np = import_numpy()
|
||||
|
||||
|
||||
class UniqueZone:
|
||||
__slots__ = ["_tab"]
|
||||
|
||||
@classmethod
|
||||
def GetRootAs(cls, buf, offset=0):
|
||||
n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
|
||||
x = UniqueZone()
|
||||
x.Init(buf, n + offset)
|
||||
return x
|
||||
|
||||
@classmethod
|
||||
def GetRootAsUniqueZone(cls, buf, offset=0):
|
||||
"""This method is deprecated. Please switch to GetRootAs."""
|
||||
return cls.GetRootAs(buf, offset)
|
||||
|
||||
# UniqueZone
|
||||
def Init(self, buf, pos):
|
||||
self._tab = flatbuffers.table.Table(buf, pos)
|
||||
|
||||
# UniqueZone
|
||||
def ZoneId(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
|
||||
if o != 0:
|
||||
return self._tab.Get(
|
||||
flatbuffers.number_types.Uint16Flags, o + self._tab.Pos
|
||||
)
|
||||
return 0
|
||||
|
||||
|
||||
def UniqueZoneStart(builder):
|
||||
builder.StartObject(1)
|
||||
|
||||
|
||||
def Start(builder):
|
||||
UniqueZoneStart(builder)
|
||||
|
||||
|
||||
def UniqueZoneAddZoneId(builder, zoneId):
|
||||
builder.PrependUint16Slot(0, zoneId, 0)
|
||||
|
||||
|
||||
def AddZoneId(builder, zoneId):
|
||||
UniqueZoneAddZoneId(builder, zoneId)
|
||||
|
||||
|
||||
def UniqueZoneEnd(builder):
|
||||
return builder.EndObject()
|
||||
|
||||
|
||||
def End(builder):
|
||||
return UniqueZoneEnd(builder)
|
||||
Vendored
+90
@@ -0,0 +1,90 @@
|
||||
# automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
# namespace: shortcuts_uint8
|
||||
|
||||
import flatbuffers
|
||||
from flatbuffers.compat import import_numpy
|
||||
|
||||
np = import_numpy()
|
||||
|
||||
|
||||
class HybridShortcutCollection:
|
||||
__slots__ = ["_tab"]
|
||||
|
||||
@classmethod
|
||||
def GetRootAs(cls, buf, offset=0):
|
||||
n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
|
||||
x = HybridShortcutCollection()
|
||||
x.Init(buf, n + offset)
|
||||
return x
|
||||
|
||||
@classmethod
|
||||
def GetRootAsHybridShortcutCollection(cls, buf, offset=0):
|
||||
"""This method is deprecated. Please switch to GetRootAs."""
|
||||
return cls.GetRootAs(buf, offset)
|
||||
|
||||
# HybridShortcutCollection
|
||||
def Init(self, buf, pos):
|
||||
self._tab = flatbuffers.table.Table(buf, pos)
|
||||
|
||||
# HybridShortcutCollection
|
||||
def Entries(self, j):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
|
||||
if o != 0:
|
||||
x = self._tab.Vector(o)
|
||||
x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4
|
||||
x = self._tab.Indirect(x)
|
||||
from timezonefinder.flatbuf.generated.shortcuts_uint8.HybridShortcutEntry import (
|
||||
HybridShortcutEntry,
|
||||
)
|
||||
|
||||
obj = HybridShortcutEntry()
|
||||
obj.Init(self._tab.Bytes, x)
|
||||
return obj
|
||||
return None
|
||||
|
||||
# HybridShortcutCollection
|
||||
def EntriesLength(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
|
||||
if o != 0:
|
||||
return self._tab.VectorLen(o)
|
||||
return 0
|
||||
|
||||
# HybridShortcutCollection
|
||||
def EntriesIsNone(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
|
||||
return o == 0
|
||||
|
||||
|
||||
def HybridShortcutCollectionStart(builder):
|
||||
builder.StartObject(1)
|
||||
|
||||
|
||||
def Start(builder):
|
||||
HybridShortcutCollectionStart(builder)
|
||||
|
||||
|
||||
def HybridShortcutCollectionAddEntries(builder, entries):
|
||||
builder.PrependUOffsetTRelativeSlot(
|
||||
0, flatbuffers.number_types.UOffsetTFlags.py_type(entries), 0
|
||||
)
|
||||
|
||||
|
||||
def AddEntries(builder, entries):
|
||||
HybridShortcutCollectionAddEntries(builder, entries)
|
||||
|
||||
|
||||
def HybridShortcutCollectionStartEntriesVector(builder, numElems):
|
||||
return builder.StartVector(4, numElems, 4)
|
||||
|
||||
|
||||
def StartEntriesVector(builder, numElems):
|
||||
return HybridShortcutCollectionStartEntriesVector(builder, numElems)
|
||||
|
||||
|
||||
def HybridShortcutCollectionEnd(builder):
|
||||
return builder.EndObject()
|
||||
|
||||
|
||||
def End(builder):
|
||||
return HybridShortcutCollectionEnd(builder)
|
||||
Vendored
+97
@@ -0,0 +1,97 @@
|
||||
# automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
# namespace: shortcuts_uint8
|
||||
|
||||
import flatbuffers
|
||||
from flatbuffers.compat import import_numpy
|
||||
|
||||
np = import_numpy()
|
||||
|
||||
|
||||
class HybridShortcutEntry:
|
||||
__slots__ = ["_tab"]
|
||||
|
||||
@classmethod
|
||||
def GetRootAs(cls, buf, offset=0):
|
||||
n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
|
||||
x = HybridShortcutEntry()
|
||||
x.Init(buf, n + offset)
|
||||
return x
|
||||
|
||||
@classmethod
|
||||
def GetRootAsHybridShortcutEntry(cls, buf, offset=0):
|
||||
"""This method is deprecated. Please switch to GetRootAs."""
|
||||
return cls.GetRootAs(buf, offset)
|
||||
|
||||
# HybridShortcutEntry
|
||||
def Init(self, buf, pos):
|
||||
self._tab = flatbuffers.table.Table(buf, pos)
|
||||
|
||||
# HybridShortcutEntry
|
||||
def HexId(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
|
||||
if o != 0:
|
||||
return self._tab.Get(
|
||||
flatbuffers.number_types.Uint64Flags, o + self._tab.Pos
|
||||
)
|
||||
return 0
|
||||
|
||||
# HybridShortcutEntry
|
||||
def ValueType(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
|
||||
if o != 0:
|
||||
return self._tab.Get(flatbuffers.number_types.Uint8Flags, o + self._tab.Pos)
|
||||
return 0
|
||||
|
||||
# HybridShortcutEntry
|
||||
def Value(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
|
||||
if o != 0:
|
||||
from flatbuffers.table import Table
|
||||
|
||||
obj = Table(bytearray(), 0)
|
||||
self._tab.Union(obj, o)
|
||||
return obj
|
||||
return None
|
||||
|
||||
|
||||
def HybridShortcutEntryStart(builder):
|
||||
builder.StartObject(3)
|
||||
|
||||
|
||||
def Start(builder):
|
||||
HybridShortcutEntryStart(builder)
|
||||
|
||||
|
||||
def HybridShortcutEntryAddHexId(builder, hexId):
|
||||
builder.PrependUint64Slot(0, hexId, 0)
|
||||
|
||||
|
||||
def AddHexId(builder, hexId):
|
||||
HybridShortcutEntryAddHexId(builder, hexId)
|
||||
|
||||
|
||||
def HybridShortcutEntryAddValueType(builder, valueType):
|
||||
builder.PrependUint8Slot(1, valueType, 0)
|
||||
|
||||
|
||||
def AddValueType(builder, valueType):
|
||||
HybridShortcutEntryAddValueType(builder, valueType)
|
||||
|
||||
|
||||
def HybridShortcutEntryAddValue(builder, value):
|
||||
builder.PrependUOffsetTRelativeSlot(
|
||||
2, flatbuffers.number_types.UOffsetTFlags.py_type(value), 0
|
||||
)
|
||||
|
||||
|
||||
def AddValue(builder, value):
|
||||
HybridShortcutEntryAddValue(builder, value)
|
||||
|
||||
|
||||
def HybridShortcutEntryEnd(builder):
|
||||
return builder.EndObject()
|
||||
|
||||
|
||||
def End(builder):
|
||||
return HybridShortcutEntryEnd(builder)
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
# automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
# namespace: shortcuts_uint8
|
||||
|
||||
import flatbuffers
|
||||
from flatbuffers.compat import import_numpy
|
||||
|
||||
np = import_numpy()
|
||||
|
||||
|
||||
class PolygonList:
|
||||
__slots__ = ["_tab"]
|
||||
|
||||
@classmethod
|
||||
def GetRootAs(cls, buf, offset=0):
|
||||
n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
|
||||
x = PolygonList()
|
||||
x.Init(buf, n + offset)
|
||||
return x
|
||||
|
||||
@classmethod
|
||||
def GetRootAsPolygonList(cls, buf, offset=0):
|
||||
"""This method is deprecated. Please switch to GetRootAs."""
|
||||
return cls.GetRootAs(buf, offset)
|
||||
|
||||
# PolygonList
|
||||
def Init(self, buf, pos):
|
||||
self._tab = flatbuffers.table.Table(buf, pos)
|
||||
|
||||
# PolygonList
|
||||
def PolyIds(self, j):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
|
||||
if o != 0:
|
||||
a = self._tab.Vector(o)
|
||||
return self._tab.Get(
|
||||
flatbuffers.number_types.Uint16Flags,
|
||||
a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 2),
|
||||
)
|
||||
return 0
|
||||
|
||||
# PolygonList
|
||||
def PolyIdsAsNumpy(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
|
||||
if o != 0:
|
||||
return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Uint16Flags, o)
|
||||
return 0
|
||||
|
||||
# PolygonList
|
||||
def PolyIdsLength(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
|
||||
if o != 0:
|
||||
return self._tab.VectorLen(o)
|
||||
return 0
|
||||
|
||||
# PolygonList
|
||||
def PolyIdsIsNone(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
|
||||
return o == 0
|
||||
|
||||
|
||||
def PolygonListStart(builder):
|
||||
builder.StartObject(1)
|
||||
|
||||
|
||||
def Start(builder):
|
||||
PolygonListStart(builder)
|
||||
|
||||
|
||||
def PolygonListAddPolyIds(builder, polyIds):
|
||||
builder.PrependUOffsetTRelativeSlot(
|
||||
0, flatbuffers.number_types.UOffsetTFlags.py_type(polyIds), 0
|
||||
)
|
||||
|
||||
|
||||
def AddPolyIds(builder, polyIds):
|
||||
PolygonListAddPolyIds(builder, polyIds)
|
||||
|
||||
|
||||
def PolygonListStartPolyIdsVector(builder, numElems):
|
||||
return builder.StartVector(2, numElems, 2)
|
||||
|
||||
|
||||
def StartPolyIdsVector(builder, numElems):
|
||||
return PolygonListStartPolyIdsVector(builder, numElems)
|
||||
|
||||
|
||||
def PolygonListEnd(builder):
|
||||
return builder.EndObject()
|
||||
|
||||
|
||||
def End(builder):
|
||||
return PolygonListEnd(builder)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user