diff --git a/.coveragerc b/.coveragerc index 634afa31..ab53045c 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,3 +1,5 @@ [run] -plugins = Cython.Coverage +plugins = + Cython.Coverage + coverage_excludes source = clickhouse_driver diff --git a/.flake8 b/.flake8 index 11257952..795748f6 100644 --- a/.flake8 +++ b/.flake8 @@ -6,3 +6,4 @@ per-file-ignores = clickhouse_driver/bufferedreader.pyx: E225, E226, E227, E999 clickhouse_driver/bufferedwriter.pyx: E225, E226, E227, E999 clickhouse_driver/varint.pyx: E225, E226, E227, E999 + tests/columns/test_newjson.py: E501 diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml index 36321297..d24cd805 100644 --- a/.github/workflows/actions.yml +++ b/.github/workflows/actions.yml @@ -1,12 +1,26 @@ -on: [push, pull_request] +on: + push: + branches: [master] + tags: ['*'] + pull_request: name: build + +concurrency: + # One lane per workflow + PR; non-PR pushes fall back to run_id (never cancel each other) + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + jobs: tests: runs-on: ubuntu-22.04 + env: + CLICKHOUSE_VERSION: ${{ matrix.clickhouse-version }} strategy: matrix: use-numpy: - 0 + use-arrow: + - 0 python-version: - "3.9" - "3.10" @@ -17,6 +31,7 @@ jobs: - "pypy-3.9" - "pypy-3.10" clickhouse-version: + - 25.5.6.14 - 24.4.1 - 24.1.8.22 - 24.1.7.18 @@ -48,8 +63,23 @@ jobs: - clickhouse-version: 20.3.20.6 use-numpy: 1 python-version: 3.9 + # Oldest supported server + oldest pyarrow/numpy resolvable + # on Python 3.9. + - clickhouse-version: 20.3.20.6 + use-numpy: 1 + use-arrow: 1 + python-version: 3.9 + - clickhouse-version: 25.5.6.14 + use-numpy: 1 + use-arrow: 1 + python-version: "3.12" + # PyArrow without numpy/pandas: plain conversion paths only. + - clickhouse-version: 25.5.6.14 + use-numpy: 0 + use-arrow: 1 + python-version: "3.13" - name: ${{ matrix.python-version }} CH=${{ matrix.clickhouse-version }} NUMPY=${{ matrix.use-numpy }} + name: ${{ matrix.python-version }} CH=${{ matrix.clickhouse-version }} NUMPY=${{ matrix.use-numpy }} ARROW=${{ matrix.use-arrow }} steps: - uses: actions/checkout@v4 - name: Set up Python @@ -70,7 +100,6 @@ jobs: run: flake8 - name: Start ClickHouse server and client containers run: | - echo "VERSION=${{ matrix.clickhouse-version }}" > tests/.env if [[ "21.7" = "`echo -e "21.7\n${{ matrix.clickhouse-version }}" | sort -V | head -n1`" ]]; then echo "ORG=clickhouse"; else echo "ORG=yandex" ; fi >> tests/.env if [[ "21.10" = "`echo -e "21.10\n${{ matrix.clickhouse-version }}" | sort -V | head -n1`" ]]; then echo "TOP_LEVEL=clickhouse"; else echo "TOP_LEVEL=yandex" ; fi >> tests/.env docker compose -f tests/docker-compose.yml up -d @@ -98,6 +127,7 @@ jobs: pip install pytest-timeout env: USE_NUMPY: ${{ matrix.use-numpy }} + USE_ARROW: ${{ matrix.use-arrow }} - name: Run tests run: coverage run -m pytest --timeout=10 -v timeout-minutes: 5 @@ -109,7 +139,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} COVERALLS_PARALLEL: true - COVERALLS_FLAG_NAME: ${{ matrix.python-version }} CH=${{ matrix.clickhouse-version }} NUMPY=${{ matrix.use-numpy }} + COVERALLS_FLAG_NAME: ${{ matrix.python-version }} CH=${{ matrix.clickhouse-version }} NUMPY=${{ matrix.use-numpy }} ARROW=${{ matrix.use-arrow }} coveralls-finished: name: Indicate completion to coveralls.io @@ -142,12 +172,11 @@ jobs: # password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} - name: Start ClickHouse server and client containers run: | - echo "VERSION=$VERSION" > tests/.env - if [[ "21.7" = "`echo -e "21.7\n$VERSION" | sort -V | head -n1`" ]]; then echo "ORG=clickhouse"; else echo "ORG=yandex" ; fi >> tests/.env - if [[ "21.10" = "`echo -e "21.10\n$VERSION" | sort -V | head -n1`" ]]; then echo "TOP_LEVEL=clickhouse"; else echo "TOP_LEVEL=yandex" ; fi >> tests/.env + if [[ "21.7" = "`echo -e "21.7\n$CLICKHOUSE_VERSION" | sort -V | head -n1`" ]]; then echo "ORG=clickhouse"; else echo "ORG=yandex" ; fi >> tests/.env + if [[ "21.10" = "`echo -e "21.10\n$CLICKHOUSE_VERSION" | sort -V | head -n1`" ]]; then echo "TOP_LEVEL=clickhouse"; else echo "TOP_LEVEL=yandex" ; fi >> tests/.env docker compose -f tests/docker-compose.yml up -d env: - VERSION: 20.3.7.46 + CLICKHOUSE_VERSION: 20.3.7.46 - name: Setup clickhouse-client proxy for docker run: | # Faking clickhouse-client real communication with container via docker exec. @@ -209,11 +238,17 @@ jobs: draft: true tag: Linux token: ${{ secrets.GITHUB_TOKEN }} + - uses: actions/upload-artifact@v4 + name: Store wheels + if: ${{ github.ref_type == 'tag' }} + with: + name: dist-linux + path: wheelhouse/*.whl wheels-macos: name: Wheels for OS X needs: valgrind - runs-on: macos-13 + runs-on: macos-latest steps: - uses: actions/checkout@v4 - name: Set up Python @@ -248,6 +283,12 @@ jobs: draft: true tag: OS X token: ${{ secrets.GITHUB_TOKEN }} + - uses: actions/upload-artifact@v4 + name: Store wheels + if: ${{ github.ref_type == 'tag' }} + with: + name: dist-macos + path: wheelhouse/*.whl wheels-windows: name: Wheels for Windows @@ -288,6 +329,12 @@ jobs: draft: true tag: Windows token: ${{ secrets.GITHUB_TOKEN }} + - uses: actions/upload-artifact@v4 + name: Store wheels + if: ${{ github.ref_type == 'tag' }} + with: + name: dist-windows + path: wheelhouse/*.whl wheels-linux-non-x86: name: Wheels for Linux non-x86 @@ -339,3 +386,52 @@ jobs: draft: true tag: Linux non-x86 token: ${{ secrets.GITHUB_TOKEN }} + - uses: actions/upload-artifact@v4 + name: Store wheels + if: ${{ github.ref_type == 'tag' }} + with: + name: dist-linux-${{ matrix.arch }} + path: wheelhouse/*.whl + + sdist: + name: Source distribution + needs: valgrind + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3.12 + - name: Build sdist + run: | + pip install --upgrade pip build + python -m build --sdist + - uses: actions/upload-artifact@v4 + name: Store sdist + if: ${{ github.ref_type == 'tag' }} + with: + name: dist-sdist + path: dist/*.tar.gz + + publish-pypi: + name: Publish to PyPI + if: ${{ github.ref_type == 'tag' }} + needs: + - sdist + - wheels-linux + - wheels-macos + - wheels-windows + - wheels-linux-non-x86 + runs-on: ubuntu-22.04 + environment: pypi + permissions: + id-token: write + steps: + - uses: actions/download-artifact@v4 + with: + pattern: dist-* + merge-multiple: true + path: dist + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 22cd2d7f..0a3e7fce 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -1,5 +1,15 @@ -on: [push, pull_request] +on: + push: + branches: [master] + tags: ['*'] + pull_request: name: build-docs + +concurrency: + # One lane per workflow + PR; non-PR pushes fall back to run_id (never cancel each other) + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + jobs: tests: runs-on: ubuntu-22.04 diff --git a/CHANGELOG.md b/CHANGELOG.md index 0de5a319..564a9e5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ ## Unreleased +- PyArrow support: `query_arrow` returns `pyarrow.Table`, `query_arrow_stream` returns `pyarrow.RecordBatchReader`. Install with `pip install clickhouse-driver[arrow]`. Solves issue [#375](https://github.com/mymarilyn/clickhouse-driver/issues/375). +- Native `JSON` support. Solves issue [#473](https://github.com/mymarilyn/clickhouse-driver/issues/473) and [#460](https://github.com/mymarilyn/clickhouse-driver/issues/460). Pull request [#503](https://github.com/mymarilyn/clickhouse-driver/pull/503/) by [khvn26](https://github.com/khvn26), [gsergey418](https://github.com/gsergey418). +- Writing `JSON` columns nested in `Array`, `Tuple` and `Map` columns. Solves issue [#511](https://github.com/mymarilyn/clickhouse-driver/issues/511). +- Vendored the CityHash 1.0.2 algorithm (from `clickhouse-cityhash` 1.0.2.6) directly into the driver. The `clickhouse-cityhash` dependency is dropped from the `lz4`/`zstd` extras; compression now works out of the box. Building from source now requires a C++ compiler. +- Escaping of `list`/`tuple` parameters with `server_side_params=True`: collections were sent in a form the server could not parse. Solves issue [#497](https://github.com/mymarilyn/clickhouse-driver/issues/497). Pull request [#507](https://github.com/mymarilyn/clickhouse-driver/pull/507) by [khvn26](https://github.com/khvn26). +- Sparse deserialization of `IPv6` columns. Solves issue [#480](https://github.com/mymarilyn/clickhouse-driver/issues/480). Pull request [#508](https://github.com/mymarilyn/clickhouse-driver/pull/508) by [khvn26](https://github.com/khvn26). + ## [0.2.10] - 2026-10-10 ### Added - Wheels for Python 3.13 and 3.14. diff --git a/MANIFEST.in b/MANIFEST.in index ea1e5c03..e6ac5ad7 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1 +1,2 @@ recursive-include clickhouse_driver *.pyx +recursive-include clickhouse_driver/_cityhash *.cc *.cpp *.h LICENSE diff --git a/README.rst b/README.rst index b739e32b..266c556c 100644 --- a/README.rst +++ b/README.rst @@ -52,6 +52,7 @@ Features * Tuple(T1, T2, ...) * Nested * Map(key, value) + * JSON - Query progress information. diff --git a/clickhouse_driver/_cityhash/LICENSE b/clickhouse_driver/_cityhash/LICENSE new file mode 100644 index 00000000..9db88535 --- /dev/null +++ b/clickhouse_driver/_cityhash/LICENSE @@ -0,0 +1,21 @@ +CityHash.py - Python-bindings for CityHash + +Copyright (c) 2011, Alexander Marshalov , +except where the file explicitly names other copyright holders and licenses. + +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. diff --git a/clickhouse_driver/_cityhash/__init__.py b/clickhouse_driver/_cityhash/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/clickhouse_driver/_cityhash/city.cc b/clickhouse_driver/_cityhash/city.cc new file mode 100644 index 00000000..211c5899 --- /dev/null +++ b/clickhouse_driver/_cityhash/city.cc @@ -0,0 +1,470 @@ +// Copyright (c) 2011 Google, Inc. +// +// 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. +// +// CityHash, by Geoff Pike and Jyrki Alakuijala +// +// This file provides CityHash64() and related functions. +// +// It's probably possible to create even faster hash functions by +// writing a program that systematically explores some of the space of +// possible hash functions, by using SIMD instructions, or by +// compromising on hash quality. + +#include "config.h" +#include + +#include +#include // for memcpy and memset + +using namespace std; + +static uint64 UNALIGNED_LOAD64(const char *p) { + uint64 result; + memcpy(&result, p, sizeof(result)); + return result; +} + +static uint32 UNALIGNED_LOAD32(const char *p) { + uint32 result; + memcpy(&result, p, sizeof(result)); + return result; +} + +#if !defined(WORDS_BIGENDIAN) + +#define uint32_in_expected_order(x) (x) +#define uint64_in_expected_order(x) (x) + +#else + +#ifdef _MSC_VER +#include +#define bswap_32(x) _byteswap_ulong(x) +#define bswap_64(x) _byteswap_uint64(x) + +#elif defined(__APPLE__) +// Mac OS X / Darwin features +#include +#define bswap_32(x) OSSwapInt32(x) +#define bswap_64(x) OSSwapInt64(x) + +#else +#include +#endif + +#define uint32_in_expected_order(x) (bswap_32(x)) +#define uint64_in_expected_order(x) (bswap_64(x)) + +#endif // WORDS_BIGENDIAN + +#if !defined(LIKELY) +#if HAVE_BUILTIN_EXPECT && !defined(_MSC_VER) +#define LIKELY(x) (__builtin_expect(!!(x), 1)) +#else +#define LIKELY(x) (x) +#endif +#endif + +static uint64 Fetch64(const char *p) { + return uint64_in_expected_order(UNALIGNED_LOAD64(p)); +} + +static uint32 Fetch32(const char *p) { + return uint32_in_expected_order(UNALIGNED_LOAD32(p)); +} + +// Some primes between 2^63 and 2^64 for various uses. +static const uint64 k0 = 0xc3a5c85c97cb3127ULL; +static const uint64 k1 = 0xb492b66fbe98f273ULL; +static const uint64 k2 = 0x9ae16a3b2f90404fULL; +static const uint64 k3 = 0xc949d7c7509e6557ULL; + +// Bitwise right rotate. Normally this will compile to a single +// instruction, especially if the shift is a manifest constant. +static uint64 Rotate(uint64 val, int shift) { + // Avoid shifting by 64: doing so yields an undefined result. + return shift == 0 ? val : ((val >> shift) | (val << (64 - shift))); +} + +// Equivalent to Rotate(), but requires the second arg to be non-zero. +// On x86-64, and probably others, it's possible for this to compile +// to a single instruction if both args are already in registers. +static uint64 RotateByAtLeast1(uint64 val, int shift) { + return (val >> shift) | (val << (64 - shift)); +} + +static uint64 ShiftMix(uint64 val) { + return val ^ (val >> 47); +} + +static uint64 HashLen16(uint64 u, uint64 v) { + return Hash128to64(uint128(u, v)); +} + +static uint64 HashLen0to16(const char *s, size_t len) { + if (len > 8) { + uint64 a = Fetch64(s); + uint64 b = Fetch64(s + len - 8); + return HashLen16(a, RotateByAtLeast1(b + len, len)) ^ b; + } + if (len >= 4) { + uint64 a = Fetch32(s); + return HashLen16(len + (a << 3), Fetch32(s + len - 4)); + } + if (len > 0) { + uint8 a = s[0]; + uint8 b = s[len >> 1]; + uint8 c = s[len - 1]; + uint32 y = static_cast(a) + (static_cast(b) << 8); + uint32 z = len + (static_cast(c) << 2); + return ShiftMix(y * k2 ^ z * k3) * k2; + } + return k2; +} + +// This probably works well for 16-byte strings as well, but it may be overkill +// in that case. +static uint64 HashLen17to32(const char *s, size_t len) { + uint64 a = Fetch64(s) * k1; + uint64 b = Fetch64(s + 8); + uint64 c = Fetch64(s + len - 8) * k2; + uint64 d = Fetch64(s + len - 16) * k0; + return HashLen16(Rotate(a - b, 43) + Rotate(c, 30) + d, + a + Rotate(b ^ k3, 20) - c + len); +} + +// Return a 16-byte hash for 48 bytes. Quick and dirty. +// Callers do best to use "random-looking" values for a and b. +static pair WeakHashLen32WithSeeds( + uint64 w, uint64 x, uint64 y, uint64 z, uint64 a, uint64 b) { + a += w; + b = Rotate(b + a + z, 21); + uint64 c = a; + a += x; + a += y; + b += Rotate(a, 44); + return make_pair(a + z, b + c); +} + +// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty. +static pair WeakHashLen32WithSeeds( + const char* s, uint64 a, uint64 b) { + return WeakHashLen32WithSeeds(Fetch64(s), + Fetch64(s + 8), + Fetch64(s + 16), + Fetch64(s + 24), + a, + b); +} + +// Return an 8-byte hash for 33 to 64 bytes. +static uint64 HashLen33to64(const char *s, size_t len) { + uint64 z = Fetch64(s + 24); + uint64 a = Fetch64(s) + (len + Fetch64(s + len - 16)) * k0; + uint64 b = Rotate(a + z, 52); + uint64 c = Rotate(a, 37); + a += Fetch64(s + 8); + c += Rotate(a, 7); + a += Fetch64(s + 16); + uint64 vf = a + z; + uint64 vs = b + Rotate(a, 31) + c; + a = Fetch64(s + 16) + Fetch64(s + len - 32); + z = Fetch64(s + len - 8); + b = Rotate(a + z, 52); + c = Rotate(a, 37); + a += Fetch64(s + len - 24); + c += Rotate(a, 7); + a += Fetch64(s + len - 16); + uint64 wf = a + z; + uint64 ws = b + Rotate(a, 31) + c; + uint64 r = ShiftMix((vf + ws) * k2 + (wf + vs) * k0); + return ShiftMix(r * k0 + vs) * k2; +} + +uint64 CityHash64(const char *s, size_t len) { + if (len <= 32) { + if (len <= 16) { + return HashLen0to16(s, len); + } else { + return HashLen17to32(s, len); + } + } else if (len <= 64) { + return HashLen33to64(s, len); + } + + // For strings over 64 bytes we hash the end first, and then as we + // loop we keep 56 bytes of state: v, w, x, y, and z. + uint64 x = Fetch64(s); + uint64 y = Fetch64(s + len - 16) ^ k1; + uint64 z = Fetch64(s + len - 56) ^ k0; + pair v = WeakHashLen32WithSeeds(s + len - 64, len, y); + pair w = WeakHashLen32WithSeeds(s + len - 32, len * k1, k0); + z += ShiftMix(v.second) * k1; + x = Rotate(z + x, 39) * k1; + y = Rotate(y, 33) * k1; + + // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks. + len = (len - 1) & ~static_cast(63); + do { + x = Rotate(x + y + v.first + Fetch64(s + 16), 37) * k1; + y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; + x ^= w.second; + y ^= v.first; + z = Rotate(z ^ w.first, 33); + v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first); + w = WeakHashLen32WithSeeds(s + 32, z + w.second, y); + std::swap(z, x); + s += 64; + len -= 64; + } while (len != 0); + return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z, + HashLen16(v.second, w.second) + x); +} + +uint64 CityHash64WithSeed(const char *s, size_t len, uint64 seed) { + return CityHash64WithSeeds(s, len, k2, seed); +} + +uint64 CityHash64WithSeeds(const char *s, size_t len, + uint64 seed0, uint64 seed1) { + return HashLen16(CityHash64(s, len) - seed0, seed1); +} + +// A subroutine for CityHash128(). Returns a decent 128-bit hash for strings +// of any length representable in signed long. Based on City and Murmur. +static uint128 CityMurmur(const char *s, size_t len, uint128 seed) { + uint64 a = Uint128Low64(seed); + uint64 b = Uint128High64(seed); + uint64 c = 0; + uint64 d = 0; + signed long l = len - 16; + if (l <= 0) { // len <= 16 + a = ShiftMix(a * k1) * k1; + c = b * k1 + HashLen0to16(s, len); + d = ShiftMix(a + (len >= 8 ? Fetch64(s) : c)); + } else { // len > 16 + c = HashLen16(Fetch64(s + len - 8) + k1, a); + d = HashLen16(b + len, c + Fetch64(s + len - 16)); + a += d; + do { + a ^= ShiftMix(Fetch64(s) * k1) * k1; + a *= k1; + b ^= a; + c ^= ShiftMix(Fetch64(s + 8) * k1) * k1; + c *= k1; + d ^= c; + s += 16; + l -= 16; + } while (l > 0); + } + a = HashLen16(a, c); + b = HashLen16(d, b); + return uint128(a ^ b, HashLen16(b, a)); +} + +uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) { + if (len < 128) { + return CityMurmur(s, len, seed); + } + + // We expect len >= 128 to be the common case. Keep 56 bytes of state: + // v, w, x, y, and z. + pair v, w; + uint64 x = Uint128Low64(seed); + uint64 y = Uint128High64(seed); + uint64 z = len * k1; + v.first = Rotate(y ^ k1, 49) * k1 + Fetch64(s); + v.second = Rotate(v.first, 42) * k1 + Fetch64(s + 8); + w.first = Rotate(y + z, 35) * k1 + x; + w.second = Rotate(x + Fetch64(s + 88), 53) * k1; + + // This is the same inner loop as CityHash64(), manually unrolled. + do { + x = Rotate(x + y + v.first + Fetch64(s + 16), 37) * k1; + y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; + x ^= w.second; + y ^= v.first; + z = Rotate(z ^ w.first, 33); + v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first); + w = WeakHashLen32WithSeeds(s + 32, z + w.second, y); + std::swap(z, x); + s += 64; + x = Rotate(x + y + v.first + Fetch64(s + 16), 37) * k1; + y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; + x ^= w.second; + y ^= v.first; + z = Rotate(z ^ w.first, 33); + v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first); + w = WeakHashLen32WithSeeds(s + 32, z + w.second, y); + std::swap(z, x); + s += 64; + len -= 128; + } while (LIKELY(len >= 128)); + y += Rotate(w.first, 37) * k0 + z; + x += Rotate(v.first + z, 49) * k0; + // If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s. + for (size_t tail_done = 0; tail_done < len; ) { + tail_done += 32; + y = Rotate(y - x, 42) * k0 + v.second; + w.first += Fetch64(s + len - tail_done + 16); + x = Rotate(x, 49) * k0 + w.first; + w.first += v.first; + v = WeakHashLen32WithSeeds(s + len - tail_done, v.first, v.second); + } + // At this point our 48 bytes of state should contain more than + // enough information for a strong 128-bit hash. We use two + // different 48-byte-to-8-byte hashes to get a 16-byte final result. + x = HashLen16(x, v.first); + y = HashLen16(y, w.first); + return uint128(HashLen16(x + v.second, w.second) + y, + HashLen16(x + w.second, y + v.second)); +} + +uint128 CityHash128(const char *s, size_t len) { + if (len >= 16) { + return CityHash128WithSeed(s + 16, + len - 16, + uint128(Fetch64(s) ^ k3, + Fetch64(s + 8))); + } else if (len >= 8) { + return CityHash128WithSeed(NULL, + 0, + uint128(Fetch64(s) ^ (len * k0), + Fetch64(s + len - 8) ^ k1)); + } else { + return CityHash128WithSeed(s, len, uint128(k0, k1)); + } +} + +#ifdef __SSE4_2__ +#include +#include + +// Requires len >= 240. +static void CityHashCrc256Long(const char *s, size_t len, + uint32 seed, uint64 *result) { + uint64 a = Fetch64(s + 56) + k0; + uint64 b = Fetch64(s + 96) + k0; + uint64 c = result[1] = HashLen16(b, len); + uint64 d = result[2] = Fetch64(s + 120) * k0 + len; + uint64 e = Fetch64(s + 184) + seed; + uint64 f = seed; + uint64 g = 0; + uint64 h = 0; + uint64 i = 0; + uint64 j = 0; + uint64 t = c + d; + + // 240 bytes of input per iter. + size_t iters = len / 240; + len -= iters * 240; + do { +#define CHUNK(multiplier, z) \ + { \ + uint64 old_a = a; \ + a = Rotate(b, 41 ^ z) * multiplier + Fetch64(s); \ + b = Rotate(c, 27 ^ z) * multiplier + Fetch64(s + 8); \ + c = Rotate(d, 41 ^ z) * multiplier + Fetch64(s + 16); \ + d = Rotate(e, 33 ^ z) * multiplier + Fetch64(s + 24); \ + e = Rotate(t, 25 ^ z) * multiplier + Fetch64(s + 32); \ + t = old_a; \ + } \ + f = _mm_crc32_u64(f, a); \ + g = _mm_crc32_u64(g, b); \ + h = _mm_crc32_u64(h, c); \ + i = _mm_crc32_u64(i, d); \ + j = _mm_crc32_u64(j, e); \ + s += 40 + + CHUNK(1, 1); CHUNK(k0, 0); + CHUNK(1, 1); CHUNK(k0, 0); + CHUNK(1, 1); CHUNK(k0, 0); + } while (--iters > 0); + j += i << 32; + a = HashLen16(a, j); + h += g << 32; + b = b * k0 + h; + c = HashLen16(c, f) + i; + d = HashLen16(d, e); + pair v(j + e, HashLen16(h, t)); + h = v.second + f; + // If 0 < len < 240, hash chunks of 32 bytes each from the end of s. + for (size_t tail_done = 0; tail_done < len; ) { + tail_done += 32; + c = Rotate(c - a, 42) * k0 + v.second; + d += Fetch64(s + len - tail_done + 16); + a = Rotate(a, 49) * k0 + d; + d += v.first; + v = WeakHashLen32WithSeeds(s + len - tail_done, v.first, v.second); + } + + // Final mix. + e = HashLen16(a, d) + v.first; + f = HashLen16(b, c) + a; + g = HashLen16(v.first, v.second) + c; + result[0] = e + f + g + h; + a = ShiftMix((a + g) * k0) * k0 + b; + result[1] += a + result[0]; + a = ShiftMix(a * k0) * k0 + c; + result[2] += a + result[1]; + a = ShiftMix((a + e) * k0) * k0; + result[3] = a + result[2]; +} + +// Requires len < 240. +static void CityHashCrc256Short(const char *s, size_t len, uint64 *result) { + char buf[240]; + memcpy(buf, s, len); + memset(buf + len, 0, 240 - len); + CityHashCrc256Long(buf, 240, ~static_cast(len), result); +} + +void CityHashCrc256(const char *s, size_t len, uint64 *result) { + if (LIKELY(len >= 240)) { + CityHashCrc256Long(s, len, 0, result); + } else { + CityHashCrc256Short(s, len, result); + } +} + +uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed) { + if (len <= 900) { + return CityHash128WithSeed(s, len, seed); + } else { + uint64 result[4]; + CityHashCrc256(s, len, result); + uint64 u = Uint128High64(seed) + result[0]; + uint64 v = Uint128Low64(seed) + result[1]; + return uint128(HashLen16(u, v + result[2]), + HashLen16(Rotate(v, 32), u * k0 + result[3])); + } +} + +uint128 CityHashCrc128(const char *s, size_t len) { + if (len <= 900) { + return CityHash128(s, len); + } else { + uint64 result[4]; + CityHashCrc256(s, len, result); + return uint128(result[2], result[3]); + } +} + +#endif diff --git a/clickhouse_driver/_cityhash/city.h b/clickhouse_driver/_cityhash/city.h new file mode 100644 index 00000000..c2ab352c --- /dev/null +++ b/clickhouse_driver/_cityhash/city.h @@ -0,0 +1,90 @@ +// Copyright (c) 2011 Google, Inc. +// +// 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. +// +// CityHash, by Geoff Pike and Jyrki Alakuijala +// +// This file provides a few functions for hashing strings. On x86-64 +// hardware in 2011, CityHash64() is faster than other high-quality +// hash functions, such as Murmur. This is largely due to higher +// instruction-level parallelism. CityHash64() and CityHash128() also perform +// well on hash-quality tests. +// +// CityHash128() is optimized for relatively long strings and returns +// a 128-bit hash. For strings more than about 2000 bytes it can be +// faster than CityHash64(). +// +// Functions in the CityHash family are not suitable for cryptography. +// +// WARNING: This code has not been tested on big-endian platforms! +// It is known to work well on little-endian platforms that have a small penalty +// for unaligned reads, such as current Intel and AMD moderate-to-high-end CPUs. +// +// By the way, for some hash functions, given strings a and b, the hash +// of a+b is easily derived from the hashes of a and b. This property +// doesn't hold for any hash functions in this file. + +#ifndef CITY_HASH_H_ +#define CITY_HASH_H_ + +#include // for size_t. +#include +#include + +typedef uint8_t uint8; +typedef uint32_t uint32; +typedef uint64_t uint64; +typedef std::pair uint128; + +inline uint64 Uint128Low64(const uint128& x) { return x.first; } +inline uint64 Uint128High64(const uint128& x) { return x.second; } + +// Hash function for a byte array. +uint64 CityHash64(const char *buf, size_t len); + +// Hash function for a byte array. For convenience, a 64-bit seed is also +// hashed into the result. +uint64 CityHash64WithSeed(const char *buf, size_t len, uint64 seed); + +// Hash function for a byte array. For convenience, two seeds are also +// hashed into the result. +uint64 CityHash64WithSeeds(const char *buf, size_t len, + uint64 seed0, uint64 seed1); + +// Hash function for a byte array. +uint128 CityHash128(const char *s, size_t len); + +// Hash function for a byte array. For convenience, a 128-bit seed is also +// hashed into the result. +uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed); + +// Hash 128 input bits down to 64 bits of output. +// This is intended to be a reasonably good hash function. +inline uint64 Hash128to64(const uint128& x) { + // Murmur-inspired hashing. + const uint64 kMul = 0x9ddfea08eb382d69ULL; + uint64 a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul; + a ^= (a >> 47); + uint64 b = (Uint128High64(x) ^ a) * kMul; + b ^= (b >> 47); + b *= kMul; + return b; +} + +#endif // CITY_HASH_H_ diff --git a/clickhouse_driver/_cityhash/citycrc.h b/clickhouse_driver/_cityhash/citycrc.h new file mode 100644 index 00000000..318e3917 --- /dev/null +++ b/clickhouse_driver/_cityhash/citycrc.h @@ -0,0 +1,43 @@ +// Copyright (c) 2011 Google, Inc. +// +// 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. +// +// CityHash, by Geoff Pike and Jyrki Alakuijala +// +// This file declares the subset of the CityHash functions that require +// _mm_crc32_u64(). See the CityHash README for details. +// +// Functions in the CityHash family are not suitable for cryptography. + +#ifndef CITY_HASH_CRC_H_ +#define CITY_HASH_CRC_H_ + +#include + +// Hash function for a byte array. +uint128 CityHashCrc128(const char *s, size_t len); + +// Hash function for a byte array. For convenience, a 128-bit seed is also +// hashed into the result. +uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed); + +// Hash function for a byte array. Sets result[0] ... result[3]. +void CityHashCrc256(const char *s, size_t len, uint64 *result); + +#endif // CITY_HASH_CRC_H_ diff --git a/clickhouse_driver/_cityhash/cityhash.cpp b/clickhouse_driver/_cityhash/cityhash.cpp new file mode 100644 index 00000000..96f2fe18 --- /dev/null +++ b/clickhouse_driver/_cityhash/cityhash.cpp @@ -0,0 +1,8997 @@ +/* Generated by Cython 3.2.0 */ + +#ifndef PY_SSIZE_T_CLEAN +#define PY_SSIZE_T_CLEAN +#endif /* PY_SSIZE_T_CLEAN */ +/* InitLimitedAPI */ +#if defined(Py_LIMITED_API) + #if !defined(CYTHON_LIMITED_API) + #define CYTHON_LIMITED_API 1 + #endif +#elif defined(CYTHON_LIMITED_API) + #ifdef _MSC_VER + #pragma message ("Limited API usage is enabled with 'CYTHON_LIMITED_API' but 'Py_LIMITED_API' does not define a Python target version. Consider setting 'Py_LIMITED_API' instead.") + #else + #warning Limited API usage is enabled with 'CYTHON_LIMITED_API' but 'Py_LIMITED_API' does not define a Python target version. Consider setting 'Py_LIMITED_API' instead. + #endif +#endif + +#include "Python.h" +#ifndef Py_PYTHON_H + #error Python headers needed to compile C extensions, please install development version of Python. +#elif PY_VERSION_HEX < 0x03080000 + #error Cython requires Python 3.8+. +#else +#define __PYX_ABI_VERSION "3_2_0" +#define CYTHON_HEX_VERSION 0x030200F0 +#define CYTHON_FUTURE_DIVISION 1 +/* CModulePreamble */ +#include +#ifndef offsetof + #define offsetof(type, member) ( (size_t) & ((type*)0) -> member ) +#endif +#if !defined(_WIN32) && !defined(WIN32) && !defined(MS_WINDOWS) + #ifndef __stdcall + #define __stdcall + #endif + #ifndef __cdecl + #define __cdecl + #endif + #ifndef __fastcall + #define __fastcall + #endif +#endif +#ifndef DL_IMPORT + #define DL_IMPORT(t) t +#endif +#ifndef DL_EXPORT + #define DL_EXPORT(t) t +#endif +#define __PYX_COMMA , +#ifndef PY_LONG_LONG + #define PY_LONG_LONG LONG_LONG +#endif +#ifndef Py_HUGE_VAL + #define Py_HUGE_VAL HUGE_VAL +#endif +#define __PYX_LIMITED_VERSION_HEX PY_VERSION_HEX +#if defined(GRAALVM_PYTHON) + /* For very preliminary testing purposes. Most variables are set the same as PyPy. + The existence of this section does not imply that anything works or is even tested */ + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_LIMITED_API 0 + #define CYTHON_COMPILING_IN_GRAAL 1 + #define CYTHON_COMPILING_IN_CPYTHON_FREETHREADING 0 + #undef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 0 + #undef CYTHON_USE_TYPE_SPECS + #define CYTHON_USE_TYPE_SPECS 0 + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #undef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 0 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #undef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 1 + #undef CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS + #define CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS 0 + #undef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 0 + #undef CYTHON_ASSUME_SAFE_SIZE + #define CYTHON_ASSUME_SAFE_SIZE 0 + #undef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 0 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_GIL + #define CYTHON_FAST_GIL 0 + #undef CYTHON_METH_FASTCALL + #define CYTHON_METH_FASTCALL 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #ifndef CYTHON_PEP487_INIT_SUBCLASS + #define CYTHON_PEP487_INIT_SUBCLASS 1 + #endif + #undef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 1 + #undef CYTHON_USE_MODULE_STATE + #define CYTHON_USE_MODULE_STATE 0 + #undef CYTHON_USE_SYS_MONITORING + #define CYTHON_USE_SYS_MONITORING 0 + #undef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 0 + #undef CYTHON_USE_AM_SEND + #define CYTHON_USE_AM_SEND 0 + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 1 + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC 0 + #endif + #undef CYTHON_USE_FREELISTS + #define CYTHON_USE_FREELISTS 0 + #undef CYTHON_IMMORTAL_CONSTANTS + #define CYTHON_IMMORTAL_CONSTANTS 0 +#elif defined(PYPY_VERSION) + #define CYTHON_COMPILING_IN_PYPY 1 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_LIMITED_API 0 + #define CYTHON_COMPILING_IN_GRAAL 0 + #define CYTHON_COMPILING_IN_CPYTHON_FREETHREADING 0 + #undef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #ifndef CYTHON_USE_TYPE_SPECS + #define CYTHON_USE_TYPE_SPECS 0 + #endif + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #undef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 0 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #undef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 1 + #undef CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS + #define CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS 1 + #undef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 0 + #ifndef CYTHON_ASSUME_SAFE_SIZE + #define CYTHON_ASSUME_SAFE_SIZE 1 + #endif + #undef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 0 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_GIL + #define CYTHON_FAST_GIL 0 + #undef CYTHON_METH_FASTCALL + #define CYTHON_METH_FASTCALL 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #ifndef CYTHON_PEP487_INIT_SUBCLASS + #define CYTHON_PEP487_INIT_SUBCLASS 1 + #endif + #if PY_VERSION_HEX < 0x03090000 + #undef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 0 + #elif !defined(CYTHON_PEP489_MULTI_PHASE_INIT) + #define CYTHON_PEP489_MULTI_PHASE_INIT 1 + #endif + #undef CYTHON_USE_MODULE_STATE + #define CYTHON_USE_MODULE_STATE 0 + #undef CYTHON_USE_SYS_MONITORING + #define CYTHON_USE_SYS_MONITORING 0 + #ifndef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE (PYPY_VERSION_NUM >= 0x07030C00) + #endif + #undef CYTHON_USE_AM_SEND + #define CYTHON_USE_AM_SEND 0 + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC (PYPY_VERSION_NUM >= 0x07031100) + #endif + #undef CYTHON_USE_FREELISTS + #define CYTHON_USE_FREELISTS 0 + #undef CYTHON_IMMORTAL_CONSTANTS + #define CYTHON_IMMORTAL_CONSTANTS 0 +#elif defined(CYTHON_LIMITED_API) + #ifdef Py_LIMITED_API + #undef __PYX_LIMITED_VERSION_HEX + #define __PYX_LIMITED_VERSION_HEX Py_LIMITED_API + #endif + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_LIMITED_API 1 + #define CYTHON_COMPILING_IN_GRAAL 0 + #define CYTHON_COMPILING_IN_CPYTHON_FREETHREADING 0 + #undef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 0 + #undef CYTHON_USE_TYPE_SPECS + #define CYTHON_USE_TYPE_SPECS 1 + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #undef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 0 + #ifndef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #endif + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS + #define CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS 0 + #endif + #undef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 0 + #undef CYTHON_ASSUME_SAFE_SIZE + #define CYTHON_ASSUME_SAFE_SIZE 0 + #undef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 0 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_GIL + #define CYTHON_FAST_GIL 0 + #undef CYTHON_METH_FASTCALL + #define CYTHON_METH_FASTCALL (__PYX_LIMITED_VERSION_HEX >= 0x030C0000) + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #ifndef CYTHON_PEP487_INIT_SUBCLASS + #define CYTHON_PEP487_INIT_SUBCLASS 1 + #endif + #ifndef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 1 + #endif + #ifndef CYTHON_USE_MODULE_STATE + #define CYTHON_USE_MODULE_STATE 0 + #endif + #undef CYTHON_USE_SYS_MONITORING + #define CYTHON_USE_SYS_MONITORING 0 + #ifndef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 0 + #endif + #ifndef CYTHON_USE_AM_SEND + #define CYTHON_USE_AM_SEND (__PYX_LIMITED_VERSION_HEX >= 0x030A0000) + #endif + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC 0 + #endif + #ifndef CYTHON_USE_FREELISTS + #define CYTHON_USE_FREELISTS 1 + #endif + #undef CYTHON_IMMORTAL_CONSTANTS + #define CYTHON_IMMORTAL_CONSTANTS 0 +#else + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_CPYTHON 1 + #define CYTHON_COMPILING_IN_LIMITED_API 0 + #define CYTHON_COMPILING_IN_GRAAL 0 + #ifdef Py_GIL_DISABLED + #define CYTHON_COMPILING_IN_CPYTHON_FREETHREADING 1 + #else + #define CYTHON_COMPILING_IN_CPYTHON_FREETHREADING 0 + #endif + #if PY_VERSION_HEX < 0x030A0000 + #undef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #elif !defined(CYTHON_USE_TYPE_SLOTS) + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #ifndef CYTHON_USE_TYPE_SPECS + #define CYTHON_USE_TYPE_SPECS 0 + #endif + #ifndef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 1 + #endif + #ifndef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 1 + #endif + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #elif !defined(CYTHON_USE_PYLIST_INTERNALS) + #define CYTHON_USE_PYLIST_INTERNALS 1 + #endif + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING || PY_VERSION_HEX >= 0x030B00A2 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #elif !defined(CYTHON_USE_UNICODE_WRITER) + #define CYTHON_USE_UNICODE_WRITER 1 + #endif + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + #undef CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS + #define CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS 1 + #elif !defined(CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS) + #define CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_ASSUME_SAFE_SIZE + #define CYTHON_ASSUME_SAFE_SIZE 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #ifndef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 1 + #endif + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + #undef CYTHON_FAST_GIL + #define CYTHON_FAST_GIL 0 + #elif !defined(CYTHON_FAST_GIL) + #define CYTHON_FAST_GIL (PY_VERSION_HEX < 0x030C00A6) + #endif + #ifndef CYTHON_METH_FASTCALL + #define CYTHON_METH_FASTCALL 1 + #endif + #ifndef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 1 + #endif + #ifndef CYTHON_PEP487_INIT_SUBCLASS + #define CYTHON_PEP487_INIT_SUBCLASS 1 + #endif + #ifndef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 1 + #endif + #ifndef CYTHON_USE_MODULE_STATE + #define CYTHON_USE_MODULE_STATE 0 + #endif + #ifndef CYTHON_USE_SYS_MONITORING + #define CYTHON_USE_SYS_MONITORING (PY_VERSION_HEX >= 0x030d00B1) + #endif + #ifndef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 1 + #endif + #ifndef CYTHON_USE_AM_SEND + #define CYTHON_USE_AM_SEND 1 + #endif + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #elif !defined(CYTHON_USE_DICT_VERSIONS) + #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX < 0x030C00A5 && !CYTHON_USE_MODULE_STATE) + #endif + #ifndef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 1 + #endif + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC 1 + #endif + #ifndef CYTHON_USE_FREELISTS + #define CYTHON_USE_FREELISTS (!CYTHON_COMPILING_IN_CPYTHON_FREETHREADING) + #endif + #if defined(CYTHON_IMMORTAL_CONSTANTS) && PY_VERSION_HEX < 0x030C0000 + #undef CYTHON_IMMORTAL_CONSTANTS + #define CYTHON_IMMORTAL_CONSTANTS 0 // definitely won't work + #elif !defined(CYTHON_IMMORTAL_CONSTANTS) + #define CYTHON_IMMORTAL_CONSTANTS (PY_VERSION_HEX >= 0x030C0000 && !CYTHON_USE_MODULE_STATE && CYTHON_COMPILING_IN_CPYTHON_FREETHREADING) + #endif +#endif +#ifndef CYTHON_COMPRESS_STRINGS + #define CYTHON_COMPRESS_STRINGS 1 +#endif +#ifndef CYTHON_FAST_PYCCALL +#define CYTHON_FAST_PYCCALL CYTHON_FAST_PYCALL +#endif +#ifndef CYTHON_VECTORCALL +#if CYTHON_COMPILING_IN_LIMITED_API +#define CYTHON_VECTORCALL (__PYX_LIMITED_VERSION_HEX >= 0x030C0000) +#else +#define CYTHON_VECTORCALL (CYTHON_FAST_PYCCALL) +#endif +#endif +#if CYTHON_USE_PYLONG_INTERNALS + #undef SHIFT + #undef BASE + #undef MASK + #ifdef SIZEOF_VOID_P + enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) }; + #endif +#endif +#ifndef __has_attribute + #define __has_attribute(x) 0 +#endif +#ifndef __has_cpp_attribute + #define __has_cpp_attribute(x) 0 +#endif +#ifndef CYTHON_RESTRICT + #if defined(__GNUC__) + #define CYTHON_RESTRICT __restrict__ + #elif defined(_MSC_VER) && _MSC_VER >= 1400 + #define CYTHON_RESTRICT __restrict + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define CYTHON_RESTRICT restrict + #else + #define CYTHON_RESTRICT + #endif +#endif +#ifndef CYTHON_UNUSED + #if defined(__cplusplus) + /* for clang __has_cpp_attribute(maybe_unused) is true even before C++17 + * but leads to warnings with -pedantic, since it is a C++17 feature */ + #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) + #if __has_cpp_attribute(maybe_unused) + #define CYTHON_UNUSED [[maybe_unused]] + #endif + #endif + #endif +#endif +#ifndef CYTHON_UNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +#endif +#ifndef CYTHON_UNUSED_VAR +# if defined(__cplusplus) + template void CYTHON_UNUSED_VAR( const T& ) { } +# else +# define CYTHON_UNUSED_VAR(x) (void)(x) +# endif +#endif +#ifndef CYTHON_MAYBE_UNUSED_VAR + #define CYTHON_MAYBE_UNUSED_VAR(x) CYTHON_UNUSED_VAR(x) +#endif +#ifndef CYTHON_NCP_UNUSED +# if CYTHON_COMPILING_IN_CPYTHON && !CYTHON_COMPILING_IN_CPYTHON_FREETHREADING +# define CYTHON_NCP_UNUSED +# else +# define CYTHON_NCP_UNUSED CYTHON_UNUSED +# endif +#endif +#ifndef CYTHON_USE_CPP_STD_MOVE + #if defined(__cplusplus) && (\ + __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600)) + #define CYTHON_USE_CPP_STD_MOVE 1 + #else + #define CYTHON_USE_CPP_STD_MOVE 0 + #endif +#endif +#define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None) +#include +typedef uintptr_t __pyx_uintptr_t; +#ifndef CYTHON_FALLTHROUGH + #if defined(__cplusplus) + /* for clang __has_cpp_attribute(fallthrough) is true even before C++17 + * but leads to warnings with -pedantic, since it is a C++17 feature */ + #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) + #if __has_cpp_attribute(fallthrough) + #define CYTHON_FALLTHROUGH [[fallthrough]] + #endif + #endif + #ifndef CYTHON_FALLTHROUGH + #if __has_cpp_attribute(clang::fallthrough) + #define CYTHON_FALLTHROUGH [[clang::fallthrough]] + #elif __has_cpp_attribute(gnu::fallthrough) + #define CYTHON_FALLTHROUGH [[gnu::fallthrough]] + #endif + #endif + #endif + #ifndef CYTHON_FALLTHROUGH + #if __has_attribute(fallthrough) + #define CYTHON_FALLTHROUGH __attribute__((fallthrough)) + #else + #define CYTHON_FALLTHROUGH + #endif + #endif + #if defined(__clang__) && defined(__apple_build_version__) + #if __apple_build_version__ < 7000000 + #undef CYTHON_FALLTHROUGH + #define CYTHON_FALLTHROUGH + #endif + #endif +#endif +#ifndef Py_UNREACHABLE + #define Py_UNREACHABLE() assert(0); abort() +#endif +#ifdef __cplusplus + template + struct __PYX_IS_UNSIGNED_IMPL {static const bool value = T(0) < T(-1);}; + #define __PYX_IS_UNSIGNED(type) (__PYX_IS_UNSIGNED_IMPL::value) +#else + #define __PYX_IS_UNSIGNED(type) (((type)-1) > 0) +#endif +#if CYTHON_COMPILING_IN_PYPY == 1 + #define __PYX_NEED_TP_PRINT_SLOT (PY_VERSION_HEX < 0x030A0000) +#else + #define __PYX_NEED_TP_PRINT_SLOT (PY_VERSION_HEX < 0x03090000) +#endif +#define __PYX_REINTERPRET_FUNCION(func_pointer, other_pointer) ((func_pointer)(void(*)(void))(other_pointer)) + +/* CppInitCode */ +#ifndef __cplusplus + #error "Cython files generated with the C++ option must be compiled with a C++ compiler." +#endif +#ifndef CYTHON_INLINE + #if defined(__clang__) + #define CYTHON_INLINE __inline__ __attribute__ ((__unused__)) + #else + #define CYTHON_INLINE inline + #endif +#endif +template +void __Pyx_call_destructor(T& x) { + x.~T(); +} +template +class __Pyx_FakeReference { + public: + __Pyx_FakeReference() : ptr(NULL) { } + __Pyx_FakeReference(const T& ref) : ptr(const_cast(&ref)) { } + T *operator->() { return ptr; } + T *operator&() { return ptr; } + operator T&() { return *ptr; } + template bool operator ==(const U& other) const { return *ptr == other; } + template bool operator !=(const U& other) const { return *ptr != other; } + template bool operator==(const __Pyx_FakeReference& other) const { return *ptr == *other.ptr; } + template bool operator!=(const __Pyx_FakeReference& other) const { return *ptr != *other.ptr; } + private: + T *ptr; +}; + +/* PythonCompatibility */ +#define __PYX_BUILD_PY_SSIZE_T "n" +#define CYTHON_FORMAT_SSIZE_T "z" +#define __Pyx_BUILTIN_MODULE_NAME "builtins" +#define __Pyx_DefaultClassType PyType_Type +#if CYTHON_COMPILING_IN_LIMITED_API + #ifndef CO_OPTIMIZED + static int CO_OPTIMIZED; + #endif + #ifndef CO_NEWLOCALS + static int CO_NEWLOCALS; + #endif + #ifndef CO_VARARGS + static int CO_VARARGS; + #endif + #ifndef CO_VARKEYWORDS + static int CO_VARKEYWORDS; + #endif + #ifndef CO_ASYNC_GENERATOR + static int CO_ASYNC_GENERATOR; + #endif + #ifndef CO_GENERATOR + static int CO_GENERATOR; + #endif + #ifndef CO_COROUTINE + static int CO_COROUTINE; + #endif +#else + #ifndef CO_COROUTINE + #define CO_COROUTINE 0x80 + #endif + #ifndef CO_ASYNC_GENERATOR + #define CO_ASYNC_GENERATOR 0x200 + #endif +#endif +static int __Pyx_init_co_variables(void); +#if PY_VERSION_HEX >= 0x030900A4 || defined(Py_IS_TYPE) + #define __Pyx_IS_TYPE(ob, type) Py_IS_TYPE(ob, type) +#else + #define __Pyx_IS_TYPE(ob, type) (((const PyObject*)ob)->ob_type == (type)) +#endif +#if PY_VERSION_HEX >= 0x030A00B1 || defined(Py_Is) + #define __Pyx_Py_Is(x, y) Py_Is(x, y) +#else + #define __Pyx_Py_Is(x, y) ((x) == (y)) +#endif +#if PY_VERSION_HEX >= 0x030A00B1 || defined(Py_IsNone) + #define __Pyx_Py_IsNone(ob) Py_IsNone(ob) +#else + #define __Pyx_Py_IsNone(ob) __Pyx_Py_Is((ob), Py_None) +#endif +#if PY_VERSION_HEX >= 0x030A00B1 || defined(Py_IsTrue) + #define __Pyx_Py_IsTrue(ob) Py_IsTrue(ob) +#else + #define __Pyx_Py_IsTrue(ob) __Pyx_Py_Is((ob), Py_True) +#endif +#if PY_VERSION_HEX >= 0x030A00B1 || defined(Py_IsFalse) + #define __Pyx_Py_IsFalse(ob) Py_IsFalse(ob) +#else + #define __Pyx_Py_IsFalse(ob) __Pyx_Py_Is((ob), Py_False) +#endif +#define __Pyx_NoneAsNull(obj) (__Pyx_Py_IsNone(obj) ? NULL : (obj)) +#if PY_VERSION_HEX >= 0x030900F0 && !CYTHON_COMPILING_IN_PYPY + #define __Pyx_PyObject_GC_IsFinalized(o) PyObject_GC_IsFinalized(o) +#else + #define __Pyx_PyObject_GC_IsFinalized(o) _PyGC_FINALIZED(o) +#endif +#ifndef Py_TPFLAGS_CHECKTYPES + #define Py_TPFLAGS_CHECKTYPES 0 +#endif +#ifndef Py_TPFLAGS_HAVE_INDEX + #define Py_TPFLAGS_HAVE_INDEX 0 +#endif +#ifndef Py_TPFLAGS_HAVE_NEWBUFFER + #define Py_TPFLAGS_HAVE_NEWBUFFER 0 +#endif +#ifndef Py_TPFLAGS_HAVE_FINALIZE + #define Py_TPFLAGS_HAVE_FINALIZE 0 +#endif +#ifndef Py_TPFLAGS_SEQUENCE + #define Py_TPFLAGS_SEQUENCE 0 +#endif +#ifndef Py_TPFLAGS_MAPPING + #define Py_TPFLAGS_MAPPING 0 +#endif +#ifndef Py_TPFLAGS_IMMUTABLETYPE + #define Py_TPFLAGS_IMMUTABLETYPE (1UL << 8) +#endif +#ifndef Py_TPFLAGS_DISALLOW_INSTANTIATION + #define Py_TPFLAGS_DISALLOW_INSTANTIATION (1UL << 7) +#endif +#ifndef METH_STACKLESS + #define METH_STACKLESS 0 +#endif +#ifndef METH_FASTCALL + #ifndef METH_FASTCALL + #define METH_FASTCALL 0x80 + #endif + typedef PyObject *(*__Pyx_PyCFunctionFast) (PyObject *self, PyObject *const *args, Py_ssize_t nargs); + typedef PyObject *(*__Pyx_PyCFunctionFastWithKeywords) (PyObject *self, PyObject *const *args, + Py_ssize_t nargs, PyObject *kwnames); +#else + #if PY_VERSION_HEX >= 0x030d00A4 + # define __Pyx_PyCFunctionFast PyCFunctionFast + # define __Pyx_PyCFunctionFastWithKeywords PyCFunctionFastWithKeywords + #else + # define __Pyx_PyCFunctionFast _PyCFunctionFast + # define __Pyx_PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords + #endif +#endif +#if CYTHON_METH_FASTCALL + #define __Pyx_METH_FASTCALL METH_FASTCALL + #define __Pyx_PyCFunction_FastCall __Pyx_PyCFunctionFast + #define __Pyx_PyCFunction_FastCallWithKeywords __Pyx_PyCFunctionFastWithKeywords +#else + #define __Pyx_METH_FASTCALL METH_VARARGS + #define __Pyx_PyCFunction_FastCall PyCFunction + #define __Pyx_PyCFunction_FastCallWithKeywords PyCFunctionWithKeywords +#endif +#if CYTHON_VECTORCALL + #define __pyx_vectorcallfunc vectorcallfunc + #define __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET PY_VECTORCALL_ARGUMENTS_OFFSET + #define __Pyx_PyVectorcall_NARGS(n) PyVectorcall_NARGS((size_t)(n)) +#else + #define __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET 0 + #define __Pyx_PyVectorcall_NARGS(n) ((Py_ssize_t)(n)) +#endif +#if PY_VERSION_HEX >= 0x030900B1 +#define __Pyx_PyCFunction_CheckExact(func) PyCFunction_CheckExact(func) +#else +#define __Pyx_PyCFunction_CheckExact(func) PyCFunction_Check(func) +#endif +#define __Pyx_CyOrPyCFunction_Check(func) PyCFunction_Check(func) +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_CyOrPyCFunction_GET_FUNCTION(func) (((PyCFunctionObject*)(func))->m_ml->ml_meth) +#elif !CYTHON_COMPILING_IN_LIMITED_API +#define __Pyx_CyOrPyCFunction_GET_FUNCTION(func) PyCFunction_GET_FUNCTION(func) +#endif +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_CyOrPyCFunction_GET_FLAGS(func) (((PyCFunctionObject*)(func))->m_ml->ml_flags) +static CYTHON_INLINE PyObject* __Pyx_CyOrPyCFunction_GET_SELF(PyObject *func) { + return (__Pyx_CyOrPyCFunction_GET_FLAGS(func) & METH_STATIC) ? NULL : ((PyCFunctionObject*)func)->m_self; +} +#endif +static CYTHON_INLINE int __Pyx__IsSameCFunction(PyObject *func, void (*cfunc)(void)) { +#if CYTHON_COMPILING_IN_LIMITED_API + return PyCFunction_Check(func) && PyCFunction_GetFunction(func) == (PyCFunction) cfunc; +#else + return PyCFunction_Check(func) && PyCFunction_GET_FUNCTION(func) == (PyCFunction) cfunc; +#endif +} +#define __Pyx_IsSameCFunction(func, cfunc) __Pyx__IsSameCFunction(func, cfunc) +#if PY_VERSION_HEX < 0x03090000 || (CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030A0000) + #define __Pyx_PyType_FromModuleAndSpec(m, s, b) ((void)m, PyType_FromSpecWithBases(s, b)) + typedef PyObject *(*__Pyx_PyCMethod)(PyObject *, PyTypeObject *, PyObject *const *, size_t, PyObject *); +#else + #define __Pyx_PyType_FromModuleAndSpec(m, s, b) PyType_FromModuleAndSpec(m, s, b) + #define __Pyx_PyCMethod PyCMethod +#endif +#ifndef METH_METHOD + #define METH_METHOD 0x200 +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) + #define PyObject_Malloc(s) PyMem_Malloc(s) + #define PyObject_Free(p) PyMem_Free(p) + #define PyObject_Realloc(p) PyMem_Realloc(p) +#endif +#if CYTHON_COMPILING_IN_LIMITED_API + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) +#elif CYTHON_COMPILING_IN_GRAAL && defined(GRAALPY_VERSION_NUM) && GRAALPY_VERSION_NUM > 0x19000000 + #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) GraalPyFrame_SetLineNumber((frame), (lineno)) +#elif CYTHON_COMPILING_IN_GRAAL + #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) _PyFrame_SetLineNumber((frame), (lineno)) +#else + #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) (frame)->f_lineno = (lineno) +#endif +#if CYTHON_COMPILING_IN_LIMITED_API + #define __Pyx_PyThreadState_Current PyThreadState_Get() +#elif !CYTHON_FAST_THREAD_STATE + #define __Pyx_PyThreadState_Current PyThreadState_GET() +#elif PY_VERSION_HEX >= 0x030d00A1 + #define __Pyx_PyThreadState_Current PyThreadState_GetUnchecked() +#else + #define __Pyx_PyThreadState_Current _PyThreadState_UncheckedGet() +#endif +#if CYTHON_USE_MODULE_STATE +static CYTHON_INLINE void *__Pyx__PyModule_GetState(PyObject *op) +{ + void *result; + result = PyModule_GetState(op); + if (!result) + Py_FatalError("Couldn't find the module state"); + return result; +} +#define __Pyx_PyModule_GetState(o) (__pyx_mstatetype *)__Pyx__PyModule_GetState(o) +#else +#define __Pyx_PyModule_GetState(op) ((void)op,__pyx_mstate_global) +#endif +#define __Pyx_PyObject_GetSlot(obj, name, func_ctype) __Pyx_PyType_GetSlot(Py_TYPE((PyObject *) obj), name, func_ctype) +#define __Pyx_PyObject_TryGetSlot(obj, name, func_ctype) __Pyx_PyType_TryGetSlot(Py_TYPE(obj), name, func_ctype) +#define __Pyx_PyObject_GetSubSlot(obj, sub, name, func_ctype) __Pyx_PyType_GetSubSlot(Py_TYPE(obj), sub, name, func_ctype) +#define __Pyx_PyObject_TryGetSubSlot(obj, sub, name, func_ctype) __Pyx_PyType_TryGetSubSlot(Py_TYPE(obj), sub, name, func_ctype) +#if CYTHON_USE_TYPE_SLOTS + #define __Pyx_PyType_GetSlot(type, name, func_ctype) ((type)->name) + #define __Pyx_PyType_TryGetSlot(type, name, func_ctype) __Pyx_PyType_GetSlot(type, name, func_ctype) + #define __Pyx_PyType_GetSubSlot(type, sub, name, func_ctype) (((type)->sub) ? ((type)->sub->name) : NULL) + #define __Pyx_PyType_TryGetSubSlot(type, sub, name, func_ctype) __Pyx_PyType_GetSubSlot(type, sub, name, func_ctype) +#else + #define __Pyx_PyType_GetSlot(type, name, func_ctype) ((func_ctype) PyType_GetSlot((type), Py_##name)) + #define __Pyx_PyType_TryGetSlot(type, name, func_ctype)\ + ((__PYX_LIMITED_VERSION_HEX >= 0x030A0000 ||\ + (PyType_GetFlags(type) & Py_TPFLAGS_HEAPTYPE) || __Pyx_get_runtime_version() >= 0x030A0000) ?\ + __Pyx_PyType_GetSlot(type, name, func_ctype) : NULL) + #define __Pyx_PyType_GetSubSlot(obj, sub, name, func_ctype) __Pyx_PyType_GetSlot(obj, name, func_ctype) + #define __Pyx_PyType_TryGetSubSlot(obj, sub, name, func_ctype) __Pyx_PyType_TryGetSlot(obj, name, func_ctype) +#endif +#if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized) +#define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n)) +#else +#define __Pyx_PyDict_NewPresized(n) PyDict_New() +#endif +#define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) +#define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) +#if CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_UNICODE_INTERNALS +#define __Pyx_PyDict_GetItemStrWithError(dict, name) _PyDict_GetItem_KnownHash(dict, name, ((PyASCIIObject *) name)->hash) +static CYTHON_INLINE PyObject * __Pyx_PyDict_GetItemStr(PyObject *dict, PyObject *name) { + PyObject *res = __Pyx_PyDict_GetItemStrWithError(dict, name); + if (res == NULL) PyErr_Clear(); + return res; +} +#elif !CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07020000 +#define __Pyx_PyDict_GetItemStrWithError PyDict_GetItemWithError +#define __Pyx_PyDict_GetItemStr PyDict_GetItem +#else +static CYTHON_INLINE PyObject * __Pyx_PyDict_GetItemStrWithError(PyObject *dict, PyObject *name) { +#if CYTHON_COMPILING_IN_PYPY + return PyDict_GetItem(dict, name); +#else + PyDictEntry *ep; + PyDictObject *mp = (PyDictObject*) dict; + long hash = ((PyStringObject *) name)->ob_shash; + assert(hash != -1); + ep = (mp->ma_lookup)(mp, name, hash); + if (ep == NULL) { + return NULL; + } + return ep->me_value; +#endif +} +#define __Pyx_PyDict_GetItemStr PyDict_GetItem +#endif +#if CYTHON_USE_TYPE_SLOTS + #define __Pyx_PyType_GetFlags(tp) (((PyTypeObject *)tp)->tp_flags) + #define __Pyx_PyType_HasFeature(type, feature) ((__Pyx_PyType_GetFlags(type) & (feature)) != 0) +#else + #define __Pyx_PyType_GetFlags(tp) (PyType_GetFlags((PyTypeObject *)tp)) + #define __Pyx_PyType_HasFeature(type, feature) PyType_HasFeature(type, feature) +#endif +#define __Pyx_PyObject_GetIterNextFunc(iterator) __Pyx_PyObject_GetSlot(iterator, tp_iternext, iternextfunc) +#if CYTHON_USE_TYPE_SPECS +#define __Pyx_PyHeapTypeObject_GC_Del(obj) {\ + PyTypeObject *type = Py_TYPE((PyObject*)obj);\ + assert(__Pyx_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE));\ + PyObject_GC_Del(obj);\ + Py_DECREF(type);\ +} +#else +#define __Pyx_PyHeapTypeObject_GC_Del(obj) PyObject_GC_Del(obj) +#endif +#if CYTHON_COMPILING_IN_LIMITED_API + #define __Pyx_PyUnicode_READY(op) (0) + #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_ReadChar(u, i) + #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((void)u, 1114111U) + #define __Pyx_PyUnicode_KIND(u) ((void)u, (0)) + #define __Pyx_PyUnicode_DATA(u) ((void*)u) + #define __Pyx_PyUnicode_READ(k, d, i) ((void)k, PyUnicode_ReadChar((PyObject*)(d), i)) + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GetLength(u)) +#else + #if PY_VERSION_HEX >= 0x030C0000 + #define __Pyx_PyUnicode_READY(op) (0) + #else + #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ + 0 : _PyUnicode_Ready((PyObject *)(op))) + #endif + #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) + #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) + #define __Pyx_PyUnicode_KIND(u) ((int)PyUnicode_KIND(u)) + #define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u) + #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) + #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, (Py_UCS4) ch) + #if PY_VERSION_HEX >= 0x030C0000 + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_LENGTH(u)) + #else + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03090000 + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : ((PyCompactUnicodeObject *)(u))->wstr_length)) + #else + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) + #endif + #endif +#endif +#if CYTHON_COMPILING_IN_PYPY + #define __Pyx_PyUnicode_Concat(a, b) PyNumber_Add(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) PyNumber_Add(a, b) +#else + #define __Pyx_PyUnicode_Concat(a, b) PyUnicode_Concat(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ?\ + PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b)) +#endif +#if CYTHON_COMPILING_IN_PYPY + #if !defined(PyUnicode_DecodeUnicodeEscape) + #define PyUnicode_DecodeUnicodeEscape(s, size, errors) PyUnicode_Decode(s, size, "unicode_escape", errors) + #endif + #if !defined(PyUnicode_Contains) + #define PyUnicode_Contains(u, s) PySequence_Contains(u, s) + #endif + #if !defined(PyByteArray_Check) + #define PyByteArray_Check(obj) PyObject_TypeCheck(obj, &PyByteArray_Type) + #endif + #if !defined(PyObject_Format) + #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt) + #endif +#endif +#define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyUnicode_Check(b) && !PyUnicode_CheckExact(b)))) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b)) +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000 + #define __Pyx_PySequence_ListKeepNew(obj)\ + (likely(PyList_CheckExact(obj) && PyUnstable_Object_IsUniquelyReferenced(obj)) ? __Pyx_NewRef(obj) : PySequence_List(obj)) +#elif CYTHON_COMPILING_IN_CPYTHON + #define __Pyx_PySequence_ListKeepNew(obj)\ + (likely(PyList_CheckExact(obj) && Py_REFCNT(obj) == 1) ? __Pyx_NewRef(obj) : PySequence_List(obj)) +#else + #define __Pyx_PySequence_ListKeepNew(obj) PySequence_List(obj) +#endif +#ifndef PySet_CheckExact + #define PySet_CheckExact(obj) __Pyx_IS_TYPE(obj, &PySet_Type) +#endif +#if PY_VERSION_HEX >= 0x030900A4 + #define __Pyx_SET_REFCNT(obj, refcnt) Py_SET_REFCNT(obj, refcnt) + #define __Pyx_SET_SIZE(obj, size) Py_SET_SIZE(obj, size) +#else + #define __Pyx_SET_REFCNT(obj, refcnt) Py_REFCNT(obj) = (refcnt) + #define __Pyx_SET_SIZE(obj, size) Py_SIZE(obj) = (size) +#endif +enum __Pyx_ReferenceSharing { + __Pyx_ReferenceSharing_DefinitelyUnique, // We created it so we know it's unshared - no need to check + __Pyx_ReferenceSharing_OwnStrongReference, + __Pyx_ReferenceSharing_FunctionArgument, + __Pyx_ReferenceSharing_SharedReference, // Never trust it to be unshared because it's a global or similar +}; +#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING && PY_VERSION_HEX >= 0x030E0000 +#define __Pyx_IS_UNIQUELY_REFERENCED(o, sharing)\ + (sharing == __Pyx_ReferenceSharing_DefinitelyUnique ? 1 :\ + (sharing == __Pyx_ReferenceSharing_FunctionArgument ? PyUnstable_Object_IsUniqueReferencedTemporary(o) :\ + (sharing == __Pyx_ReferenceSharing_OwnStrongReference ? PyUnstable_Object_IsUniquelyReferenced(o) : 0))) +#elif (CYTHON_COMPILING_IN_CPYTHON && !CYTHON_COMPILING_IN_CPYTHON_FREETHREADING) || CYTHON_COMPILING_IN_LIMITED_API +#define __Pyx_IS_UNIQUELY_REFERENCED(o, sharing) (((void)sharing), Py_REFCNT(o) == 1) +#else +#define __Pyx_IS_UNIQUELY_REFERENCED(o, sharing) (((void)o), ((void)sharing), 0) +#endif +#if CYTHON_AVOID_BORROWED_REFS || CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS + #if __PYX_LIMITED_VERSION_HEX >= 0x030d0000 + #define __Pyx_PyList_GetItemRef(o, i) PyList_GetItemRef(o, i) + #elif CYTHON_COMPILING_IN_LIMITED_API || !CYTHON_ASSUME_SAFE_MACROS + #define __Pyx_PyList_GetItemRef(o, i) (likely((i) >= 0) ? PySequence_GetItem(o, i) : (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL)) + #else + #define __Pyx_PyList_GetItemRef(o, i) PySequence_ITEM(o, i) + #endif +#elif CYTHON_COMPILING_IN_LIMITED_API || !CYTHON_ASSUME_SAFE_MACROS + #if __PYX_LIMITED_VERSION_HEX >= 0x030d0000 + #define __Pyx_PyList_GetItemRef(o, i) PyList_GetItemRef(o, i) + #else + #define __Pyx_PyList_GetItemRef(o, i) __Pyx_XNewRef(PyList_GetItem(o, i)) + #endif +#else + #define __Pyx_PyList_GetItemRef(o, i) __Pyx_NewRef(PyList_GET_ITEM(o, i)) +#endif +#if CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS && !CYTHON_COMPILING_IN_LIMITED_API && CYTHON_ASSUME_SAFE_MACROS + #define __Pyx_PyList_GetItemRefFast(o, i, unsafe_shared) (__Pyx_IS_UNIQUELY_REFERENCED(o, unsafe_shared) ?\ + __Pyx_NewRef(PyList_GET_ITEM(o, i)) : __Pyx_PyList_GetItemRef(o, i)) +#else + #define __Pyx_PyList_GetItemRefFast(o, i, unsafe_shared) __Pyx_PyList_GetItemRef(o, i) +#endif +#if __PYX_LIMITED_VERSION_HEX >= 0x030d0000 +#define __Pyx_PyDict_GetItemRef(dict, key, result) PyDict_GetItemRef(dict, key, result) +#elif CYTHON_AVOID_BORROWED_REFS || CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS +static CYTHON_INLINE int __Pyx_PyDict_GetItemRef(PyObject *dict, PyObject *key, PyObject **result) { + *result = PyObject_GetItem(dict, key); + if (*result == NULL) { + if (PyErr_ExceptionMatches(PyExc_KeyError)) { + PyErr_Clear(); + return 0; + } + return -1; + } + return 1; +} +#else +static CYTHON_INLINE int __Pyx_PyDict_GetItemRef(PyObject *dict, PyObject *key, PyObject **result) { + *result = PyDict_GetItemWithError(dict, key); + if (*result == NULL) { + return PyErr_Occurred() ? -1 : 0; + } + Py_INCREF(*result); + return 1; +} +#endif +#if defined(CYTHON_DEBUG_VISIT_CONST) && CYTHON_DEBUG_VISIT_CONST + #define __Pyx_VISIT_CONST(obj) Py_VISIT(obj) +#else + #define __Pyx_VISIT_CONST(obj) +#endif +#if CYTHON_ASSUME_SAFE_MACROS + #define __Pyx_PySequence_ITEM(o, i) PySequence_ITEM(o, i) + #define __Pyx_PySequence_SIZE(seq) Py_SIZE(seq) + #define __Pyx_PyTuple_SET_ITEM(o, i, v) (PyTuple_SET_ITEM(o, i, v), (0)) + #define __Pyx_PyTuple_GET_ITEM(o, i) PyTuple_GET_ITEM(o, i) + #define __Pyx_PyList_SET_ITEM(o, i, v) (PyList_SET_ITEM(o, i, v), (0)) + #define __Pyx_PyList_GET_ITEM(o, i) PyList_GET_ITEM(o, i) +#else + #define __Pyx_PySequence_ITEM(o, i) PySequence_GetItem(o, i) + #define __Pyx_PySequence_SIZE(seq) PySequence_Size(seq) + #define __Pyx_PyTuple_SET_ITEM(o, i, v) PyTuple_SetItem(o, i, v) + #define __Pyx_PyTuple_GET_ITEM(o, i) PyTuple_GetItem(o, i) + #define __Pyx_PyList_SET_ITEM(o, i, v) PyList_SetItem(o, i, v) + #define __Pyx_PyList_GET_ITEM(o, i) PyList_GetItem(o, i) +#endif +#if CYTHON_ASSUME_SAFE_SIZE + #define __Pyx_PyTuple_GET_SIZE(o) PyTuple_GET_SIZE(o) + #define __Pyx_PyList_GET_SIZE(o) PyList_GET_SIZE(o) + #define __Pyx_PySet_GET_SIZE(o) PySet_GET_SIZE(o) + #define __Pyx_PyBytes_GET_SIZE(o) PyBytes_GET_SIZE(o) + #define __Pyx_PyByteArray_GET_SIZE(o) PyByteArray_GET_SIZE(o) + #define __Pyx_PyUnicode_GET_LENGTH(o) PyUnicode_GET_LENGTH(o) +#else + #define __Pyx_PyTuple_GET_SIZE(o) PyTuple_Size(o) + #define __Pyx_PyList_GET_SIZE(o) PyList_Size(o) + #define __Pyx_PySet_GET_SIZE(o) PySet_Size(o) + #define __Pyx_PyBytes_GET_SIZE(o) PyBytes_Size(o) + #define __Pyx_PyByteArray_GET_SIZE(o) PyByteArray_Size(o) + #define __Pyx_PyUnicode_GET_LENGTH(o) PyUnicode_GetLength(o) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyUnicode_InternFromString) + #define PyUnicode_InternFromString(s) PyUnicode_FromString(s) +#endif +#define __Pyx_PyLong_FromHash_t PyLong_FromSsize_t +#define __Pyx_PyLong_AsHash_t __Pyx_PyIndex_AsSsize_t +#if __PYX_LIMITED_VERSION_HEX >= 0x030A0000 + #define __Pyx_PySendResult PySendResult +#else + typedef enum { + PYGEN_RETURN = 0, + PYGEN_ERROR = -1, + PYGEN_NEXT = 1, + } __Pyx_PySendResult; +#endif +#if CYTHON_COMPILING_IN_LIMITED_API || PY_VERSION_HEX < 0x030A00A3 + typedef __Pyx_PySendResult (*__Pyx_pyiter_sendfunc)(PyObject *iter, PyObject *value, PyObject **result); +#else + #define __Pyx_pyiter_sendfunc sendfunc +#endif +#if !CYTHON_USE_AM_SEND +#define __PYX_HAS_PY_AM_SEND 0 +#elif __PYX_LIMITED_VERSION_HEX >= 0x030A0000 +#define __PYX_HAS_PY_AM_SEND 1 +#else +#define __PYX_HAS_PY_AM_SEND 2 // our own backported implementation +#endif +#if __PYX_HAS_PY_AM_SEND < 2 + #define __Pyx_PyAsyncMethodsStruct PyAsyncMethods +#else + typedef struct { + unaryfunc am_await; + unaryfunc am_aiter; + unaryfunc am_anext; + __Pyx_pyiter_sendfunc am_send; + } __Pyx_PyAsyncMethodsStruct; + #define __Pyx_SlotTpAsAsync(s) ((PyAsyncMethods*)(s)) +#endif +#if CYTHON_USE_AM_SEND && PY_VERSION_HEX < 0x030A00F0 + #define __Pyx_TPFLAGS_HAVE_AM_SEND (1UL << 21) +#else + #define __Pyx_TPFLAGS_HAVE_AM_SEND (0) +#endif +#if PY_VERSION_HEX >= 0x03090000 +#define __Pyx_PyInterpreterState_Get() PyInterpreterState_Get() +#else +#define __Pyx_PyInterpreterState_Get() PyThreadState_Get()->interp +#endif +#if CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX < 0x030A0000 +#ifdef __cplusplus +extern "C" +#endif +PyAPI_FUNC(void *) PyMem_Calloc(size_t nelem, size_t elsize); +#endif +#if CYTHON_COMPILING_IN_LIMITED_API +static int __Pyx_init_co_variable(PyObject *inspect, const char* name, int *write_to) { + int value; + PyObject *py_value = PyObject_GetAttrString(inspect, name); + if (!py_value) return 0; + value = (int) PyLong_AsLong(py_value); + Py_DECREF(py_value); + *write_to = value; + return value != -1 || !PyErr_Occurred(); +} +static int __Pyx_init_co_variables(void) { + PyObject *inspect; + int result; + inspect = PyImport_ImportModule("inspect"); + result = +#if !defined(CO_OPTIMIZED) + __Pyx_init_co_variable(inspect, "CO_OPTIMIZED", &CO_OPTIMIZED) && +#endif +#if !defined(CO_NEWLOCALS) + __Pyx_init_co_variable(inspect, "CO_NEWLOCALS", &CO_NEWLOCALS) && +#endif +#if !defined(CO_VARARGS) + __Pyx_init_co_variable(inspect, "CO_VARARGS", &CO_VARARGS) && +#endif +#if !defined(CO_VARKEYWORDS) + __Pyx_init_co_variable(inspect, "CO_VARKEYWORDS", &CO_VARKEYWORDS) && +#endif +#if !defined(CO_ASYNC_GENERATOR) + __Pyx_init_co_variable(inspect, "CO_ASYNC_GENERATOR", &CO_ASYNC_GENERATOR) && +#endif +#if !defined(CO_GENERATOR) + __Pyx_init_co_variable(inspect, "CO_GENERATOR", &CO_GENERATOR) && +#endif +#if !defined(CO_COROUTINE) + __Pyx_init_co_variable(inspect, "CO_COROUTINE", &CO_COROUTINE) && +#endif + 1; + Py_DECREF(inspect); + return result ? 0 : -1; +} +#else +static int __Pyx_init_co_variables(void) { + return 0; // It's a limited API-only feature +} +#endif + +/* MathInitCode */ +#if defined(_WIN32) || defined(WIN32) || defined(MS_WINDOWS) + #ifndef _USE_MATH_DEFINES + #define _USE_MATH_DEFINES + #endif +#endif +#include +#if defined(__CYGWIN__) && defined(_LDBL_EQ_DBL) +#define __Pyx_truncl trunc +#else +#define __Pyx_truncl truncl +#endif + +#ifndef CYTHON_CLINE_IN_TRACEBACK_RUNTIME +#define CYTHON_CLINE_IN_TRACEBACK_RUNTIME 0 +#endif +#ifndef CYTHON_CLINE_IN_TRACEBACK +#define CYTHON_CLINE_IN_TRACEBACK CYTHON_CLINE_IN_TRACEBACK_RUNTIME +#endif +#if CYTHON_CLINE_IN_TRACEBACK +#define __PYX_MARK_ERR_POS(f_index, lineno) { __pyx_filename = __pyx_f[f_index]; (void) __pyx_filename; __pyx_lineno = lineno; (void) __pyx_lineno; __pyx_clineno = __LINE__; (void) __pyx_clineno; } +#else +#define __PYX_MARK_ERR_POS(f_index, lineno) { __pyx_filename = __pyx_f[f_index]; (void) __pyx_filename; __pyx_lineno = lineno; (void) __pyx_lineno; (void) __pyx_clineno; } +#endif +#define __PYX_ERR(f_index, lineno, Ln_error) \ + { __PYX_MARK_ERR_POS(f_index, lineno) goto Ln_error; } + +#ifdef CYTHON_EXTERN_C + #undef __PYX_EXTERN_C + #define __PYX_EXTERN_C CYTHON_EXTERN_C +#elif defined(__PYX_EXTERN_C) + #ifdef _MSC_VER + #pragma message ("Please do not define the '__PYX_EXTERN_C' macro externally. Use 'CYTHON_EXTERN_C' instead.") + #else + #warning Please do not define the '__PYX_EXTERN_C' macro externally. Use 'CYTHON_EXTERN_C' instead. + #endif +#else + #define __PYX_EXTERN_C extern "C++" +#endif + +#define __PYX_HAVE__clickhouse_driver___cityhash__cityhash +#define __PYX_HAVE_API__clickhouse_driver___cityhash__cityhash +/* Early includes */ +#include +#include "city.h" +#include +#include +#include + + #if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyFloat_FromString(obj) PyFloat_FromString(obj) + #else + #define __Pyx_PyFloat_FromString(obj) PyFloat_FromString(obj, NULL) + #endif + + + #if PY_MAJOR_VERSION <= 2 + #define PyDict_GetItemWithError _PyDict_GetItemWithError + #endif + + + #if PY_VERSION_HEX < 0x030d0000 + static CYTHON_INLINE int __Pyx_PyWeakref_GetRef(PyObject *ref, PyObject **pobj) + { + PyObject *obj = PyWeakref_GetObject(ref); + if (obj == NULL) { + // SystemError if ref is NULL + *pobj = NULL; + return -1; + } + if (obj == Py_None) { + *pobj = NULL; + return 0; + } + Py_INCREF(obj); + *pobj = obj; + return 1; + } + #else + #define __Pyx_PyWeakref_GetRef PyWeakref_GetRef + #endif + +#include "pythread.h" + + #if (CYTHON_COMPILING_IN_PYPY && PYPY_VERSION_NUM < 0x07030600) && !defined(PyContextVar_Get) + #define PyContextVar_Get(var, d, v) ((d) ? ((void)(var), Py_INCREF(d), (v)[0] = (d), 0) : ((v)[0] = NULL, 0) ) + #endif + +#ifdef _OPENMP +#include +#endif /* _OPENMP */ + +#if defined(PYREX_WITHOUT_ASSERTIONS) && !defined(CYTHON_WITHOUT_ASSERTIONS) +#define CYTHON_WITHOUT_ASSERTIONS +#endif + +#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0 +#define __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 0 +#define __PYX_DEFAULT_STRING_ENCODING "" +#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString +#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize +#define __Pyx_uchar_cast(c) ((unsigned char)c) +#define __Pyx_long_cast(x) ((long)x) +#define __Pyx_fits_Py_ssize_t(v, type, is_signed) (\ + (sizeof(type) < sizeof(Py_ssize_t)) ||\ + (sizeof(type) > sizeof(Py_ssize_t) &&\ + likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX) &&\ + (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||\ + v == (type)PY_SSIZE_T_MIN))) ||\ + (sizeof(type) == sizeof(Py_ssize_t) &&\ + (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX))) ) +static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) { + return (size_t) i < (size_t) limit; +} +#if defined (__cplusplus) && __cplusplus >= 201103L + #include + #define __Pyx_sst_abs(value) std::abs(value) +#elif SIZEOF_INT >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) abs(value) +#elif SIZEOF_LONG >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) labs(value) +#elif defined (_MSC_VER) + #define __Pyx_sst_abs(value) ((Py_ssize_t)_abs64(value)) +#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define __Pyx_sst_abs(value) llabs(value) +#elif defined (__GNUC__) + #define __Pyx_sst_abs(value) __builtin_llabs(value) +#else + #define __Pyx_sst_abs(value) ((value<0) ? -value : value) +#endif +static CYTHON_INLINE Py_ssize_t __Pyx_ssize_strlen(const char *s); +static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject*); +static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length); +static CYTHON_INLINE PyObject* __Pyx_PyByteArray_FromString(const char*); +#define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l) +#define __Pyx_PyBytes_FromString PyBytes_FromString +#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*); +#if CYTHON_ASSUME_SAFE_MACROS + #define __Pyx_PyBytes_AsWritableString(s) ((char*) PyBytes_AS_STRING(s)) + #define __Pyx_PyBytes_AsWritableSString(s) ((signed char*) PyBytes_AS_STRING(s)) + #define __Pyx_PyBytes_AsWritableUString(s) ((unsigned char*) PyBytes_AS_STRING(s)) + #define __Pyx_PyBytes_AsString(s) ((const char*) PyBytes_AS_STRING(s)) + #define __Pyx_PyBytes_AsSString(s) ((const signed char*) PyBytes_AS_STRING(s)) + #define __Pyx_PyBytes_AsUString(s) ((const unsigned char*) PyBytes_AS_STRING(s)) + #define __Pyx_PyByteArray_AsString(s) PyByteArray_AS_STRING(s) +#else + #define __Pyx_PyBytes_AsWritableString(s) ((char*) PyBytes_AsString(s)) + #define __Pyx_PyBytes_AsWritableSString(s) ((signed char*) PyBytes_AsString(s)) + #define __Pyx_PyBytes_AsWritableUString(s) ((unsigned char*) PyBytes_AsString(s)) + #define __Pyx_PyBytes_AsString(s) ((const char*) PyBytes_AsString(s)) + #define __Pyx_PyBytes_AsSString(s) ((const signed char*) PyBytes_AsString(s)) + #define __Pyx_PyBytes_AsUString(s) ((const unsigned char*) PyBytes_AsString(s)) + #define __Pyx_PyByteArray_AsString(s) PyByteArray_AsString(s) +#endif +#define __Pyx_PyObject_AsWritableString(s) ((char*)(__pyx_uintptr_t) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsWritableSString(s) ((signed char*)(__pyx_uintptr_t) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsWritableUString(s) ((unsigned char*)(__pyx_uintptr_t) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsSString(s) ((const signed char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsUString(s) ((const unsigned char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s) +#define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s) +#define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s) +#define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s) +#define __Pyx_PyUnicode_FromOrdinal(o) PyUnicode_FromOrdinal((int)o) +#define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode +static CYTHON_INLINE PyObject *__Pyx_NewRef(PyObject *obj) { +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030a0000 || defined(Py_NewRef) + return Py_NewRef(obj); +#else + Py_INCREF(obj); + return obj; +#endif +} +static CYTHON_INLINE PyObject *__Pyx_XNewRef(PyObject *obj) { +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030a0000 || defined(Py_XNewRef) + return Py_XNewRef(obj); +#else + Py_XINCREF(obj); + return obj; +#endif +} +static CYTHON_INLINE PyObject *__Pyx_Owned_Py_None(int b); +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b); +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); +static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject*); +static CYTHON_INLINE PyObject* __Pyx_PyNumber_Long(PyObject* x); +#define __Pyx_PySequence_Tuple(obj)\ + (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); +static CYTHON_INLINE PyObject * __Pyx_PyLong_FromSize_t(size_t); +static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject*); +#if CYTHON_ASSUME_SAFE_MACROS +#define __Pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) +#define __Pyx_PyFloat_AS_DOUBLE(x) PyFloat_AS_DOUBLE(x) +#else +#define __Pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x) +#define __Pyx_PyFloat_AS_DOUBLE(x) PyFloat_AsDouble(x) +#endif +#define __Pyx_PyFloat_AsFloat(x) ((float) __Pyx_PyFloat_AsDouble(x)) +#define __Pyx_PyNumber_Int(x) (PyLong_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Long(x)) +#if CYTHON_USE_PYLONG_INTERNALS + #if PY_VERSION_HEX >= 0x030C00A7 + #ifndef _PyLong_SIGN_MASK + #define _PyLong_SIGN_MASK 3 + #endif + #ifndef _PyLong_NON_SIZE_BITS + #define _PyLong_NON_SIZE_BITS 3 + #endif + #define __Pyx_PyLong_Sign(x) (((PyLongObject*)x)->long_value.lv_tag & _PyLong_SIGN_MASK) + #define __Pyx_PyLong_IsNeg(x) ((__Pyx_PyLong_Sign(x) & 2) != 0) + #define __Pyx_PyLong_IsNonNeg(x) (!__Pyx_PyLong_IsNeg(x)) + #define __Pyx_PyLong_IsZero(x) (__Pyx_PyLong_Sign(x) & 1) + #define __Pyx_PyLong_IsPos(x) (__Pyx_PyLong_Sign(x) == 0) + #define __Pyx_PyLong_CompactValueUnsigned(x) (__Pyx_PyLong_Digits(x)[0]) + #define __Pyx_PyLong_DigitCount(x) ((Py_ssize_t) (((PyLongObject*)x)->long_value.lv_tag >> _PyLong_NON_SIZE_BITS)) + #define __Pyx_PyLong_SignedDigitCount(x)\ + ((1 - (Py_ssize_t) __Pyx_PyLong_Sign(x)) * __Pyx_PyLong_DigitCount(x)) + #if defined(PyUnstable_Long_IsCompact) && defined(PyUnstable_Long_CompactValue) + #define __Pyx_PyLong_IsCompact(x) PyUnstable_Long_IsCompact((PyLongObject*) x) + #define __Pyx_PyLong_CompactValue(x) PyUnstable_Long_CompactValue((PyLongObject*) x) + #else + #define __Pyx_PyLong_IsCompact(x) (((PyLongObject*)x)->long_value.lv_tag < (2 << _PyLong_NON_SIZE_BITS)) + #define __Pyx_PyLong_CompactValue(x) ((1 - (Py_ssize_t) __Pyx_PyLong_Sign(x)) * (Py_ssize_t) __Pyx_PyLong_Digits(x)[0]) + #endif + typedef Py_ssize_t __Pyx_compact_pylong; + typedef size_t __Pyx_compact_upylong; + #else + #define __Pyx_PyLong_IsNeg(x) (Py_SIZE(x) < 0) + #define __Pyx_PyLong_IsNonNeg(x) (Py_SIZE(x) >= 0) + #define __Pyx_PyLong_IsZero(x) (Py_SIZE(x) == 0) + #define __Pyx_PyLong_IsPos(x) (Py_SIZE(x) > 0) + #define __Pyx_PyLong_CompactValueUnsigned(x) ((Py_SIZE(x) == 0) ? 0 : __Pyx_PyLong_Digits(x)[0]) + #define __Pyx_PyLong_DigitCount(x) __Pyx_sst_abs(Py_SIZE(x)) + #define __Pyx_PyLong_SignedDigitCount(x) Py_SIZE(x) + #define __Pyx_PyLong_IsCompact(x) (Py_SIZE(x) == 0 || Py_SIZE(x) == 1 || Py_SIZE(x) == -1) + #define __Pyx_PyLong_CompactValue(x)\ + ((Py_SIZE(x) == 0) ? (sdigit) 0 : ((Py_SIZE(x) < 0) ? -(sdigit)__Pyx_PyLong_Digits(x)[0] : (sdigit)__Pyx_PyLong_Digits(x)[0])) + typedef sdigit __Pyx_compact_pylong; + typedef digit __Pyx_compact_upylong; + #endif + #if PY_VERSION_HEX >= 0x030C00A5 + #define __Pyx_PyLong_Digits(x) (((PyLongObject*)x)->long_value.ob_digit) + #else + #define __Pyx_PyLong_Digits(x) (((PyLongObject*)x)->ob_digit) + #endif +#endif +#if __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 + #define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL) +#elif __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + #define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeASCII(c_str, size, NULL) +#else + #define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL) +#endif + + +/* Test for GCC > 2.95 */ +#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))) + #define likely(x) __builtin_expect(!!(x), 1) + #define unlikely(x) __builtin_expect(!!(x), 0) +#else /* !__GNUC__ or GCC < 2.95 */ + #define likely(x) (x) + #define unlikely(x) (x) +#endif /* __GNUC__ */ +/* PretendToInitialize */ +#ifdef __cplusplus +#if __cplusplus > 201103L +#include +#endif +template +static void __Pyx_pretend_to_initialize(T* ptr) { +#if __cplusplus > 201103L + if ((std::is_trivially_default_constructible::value)) +#endif + *ptr = T(); + (void)ptr; +} +#else +static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; } +#endif + + +#if !CYTHON_USE_MODULE_STATE +static PyObject *__pyx_m = NULL; +#endif +static int __pyx_lineno; +static int __pyx_clineno = 0; +static const char * const __pyx_cfilenm = __FILE__; +static const char *__pyx_filename; + +/* #### Code section: filename_table ### */ + +static const char* const __pyx_f[] = { + "clickhouse_driver/_cityhash/cityhash.pyx", + ".covenv/lib/python3.11/site-packages/Cython/Includes/cpython/contextvars.pxd", + ".covenv/lib/python3.11/site-packages/Cython/Includes/cpython/type.pxd", + ".covenv/lib/python3.11/site-packages/Cython/Includes/cpython/bool.pxd", + ".covenv/lib/python3.11/site-packages/Cython/Includes/cpython/complex.pxd", +}; +/* #### Code section: utility_code_proto_before_types ### */ +/* Atomics.proto */ +#include +#ifndef CYTHON_ATOMICS + #define CYTHON_ATOMICS 1 +#endif +#define __PYX_CYTHON_ATOMICS_ENABLED() CYTHON_ATOMICS +#define __PYX_GET_CYTHON_COMPILING_IN_CPYTHON_FREETHREADING() CYTHON_COMPILING_IN_CPYTHON_FREETHREADING +#define __pyx_atomic_int_type int +#define __pyx_nonatomic_int_type int +#if CYTHON_ATOMICS && (defined(__STDC_VERSION__) &&\ + (__STDC_VERSION__ >= 201112L) &&\ + !defined(__STDC_NO_ATOMICS__)) + #include +#elif CYTHON_ATOMICS && (defined(__cplusplus) && (\ + (__cplusplus >= 201103L) ||\ + (defined(_MSC_VER) && _MSC_VER >= 1700))) + #include +#endif +#if CYTHON_ATOMICS && (defined(__STDC_VERSION__) &&\ + (__STDC_VERSION__ >= 201112L) &&\ + !defined(__STDC_NO_ATOMICS__) &&\ + ATOMIC_INT_LOCK_FREE == 2) + #undef __pyx_atomic_int_type + #define __pyx_atomic_int_type atomic_int + #define __pyx_atomic_ptr_type atomic_uintptr_t + #define __pyx_nonatomic_ptr_type uintptr_t + #define __pyx_atomic_incr_relaxed(value) atomic_fetch_add_explicit(value, 1, memory_order_relaxed) + #define __pyx_atomic_incr_acq_rel(value) atomic_fetch_add_explicit(value, 1, memory_order_acq_rel) + #define __pyx_atomic_decr_acq_rel(value) atomic_fetch_sub_explicit(value, 1, memory_order_acq_rel) + #define __pyx_atomic_sub(value, arg) atomic_fetch_sub(value, arg) + #define __pyx_atomic_int_cmp_exchange(value, expected, desired) atomic_compare_exchange_strong(value, expected, desired) + #define __pyx_atomic_load(value) atomic_load(value) + #define __pyx_atomic_store(value, new_value) atomic_store(value, new_value) + #define __pyx_atomic_pointer_load_relaxed(value) atomic_load_explicit(value, memory_order_relaxed) + #define __pyx_atomic_pointer_load_acquire(value) atomic_load_explicit(value, memory_order_acquire) + #define __pyx_atomic_pointer_exchange(value, new_value) atomic_exchange(value, (__pyx_nonatomic_ptr_type)new_value) + #define __pyx_atomic_pointer_cmp_exchange(value, expected, desired) atomic_compare_exchange_strong(value, expected, desired) + #if defined(__PYX_DEBUG_ATOMICS) && defined(_MSC_VER) + #pragma message ("Using standard C atomics") + #elif defined(__PYX_DEBUG_ATOMICS) + #warning "Using standard C atomics" + #endif +#elif CYTHON_ATOMICS && (defined(__cplusplus) && (\ + (__cplusplus >= 201103L) ||\ +\ + (defined(_MSC_VER) && _MSC_VER >= 1700)) &&\ + ATOMIC_INT_LOCK_FREE == 2) + #undef __pyx_atomic_int_type + #define __pyx_atomic_int_type std::atomic_int + #define __pyx_atomic_ptr_type std::atomic_uintptr_t + #define __pyx_nonatomic_ptr_type uintptr_t + #define __pyx_atomic_incr_relaxed(value) std::atomic_fetch_add_explicit(value, 1, std::memory_order_relaxed) + #define __pyx_atomic_incr_acq_rel(value) std::atomic_fetch_add_explicit(value, 1, std::memory_order_acq_rel) + #define __pyx_atomic_decr_acq_rel(value) std::atomic_fetch_sub_explicit(value, 1, std::memory_order_acq_rel) + #define __pyx_atomic_sub(value, arg) std::atomic_fetch_sub(value, arg) + #define __pyx_atomic_int_cmp_exchange(value, expected, desired) std::atomic_compare_exchange_strong(value, expected, desired) + #define __pyx_atomic_load(value) std::atomic_load(value) + #define __pyx_atomic_store(value, new_value) std::atomic_store(value, new_value) + #define __pyx_atomic_pointer_load_relaxed(value) std::atomic_load_explicit(value, std::memory_order_relaxed) + #define __pyx_atomic_pointer_load_acquire(value) std::atomic_load_explicit(value, std::memory_order_acquire) + #define __pyx_atomic_pointer_exchange(value, new_value) std::atomic_exchange(value, (__pyx_nonatomic_ptr_type)new_value) + #define __pyx_atomic_pointer_cmp_exchange(value, expected, desired) std::atomic_compare_exchange_strong(value, expected, desired) + #if defined(__PYX_DEBUG_ATOMICS) && defined(_MSC_VER) + #pragma message ("Using standard C++ atomics") + #elif defined(__PYX_DEBUG_ATOMICS) + #warning "Using standard C++ atomics" + #endif +#elif CYTHON_ATOMICS && (__GNUC__ >= 5 || (__GNUC__ == 4 &&\ + (__GNUC_MINOR__ > 1 ||\ + (__GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ >= 2)))) + #define __pyx_atomic_ptr_type void* + #define __pyx_nonatomic_ptr_type void* + #define __pyx_atomic_incr_relaxed(value) __sync_fetch_and_add(value, 1) + #define __pyx_atomic_incr_acq_rel(value) __sync_fetch_and_add(value, 1) + #define __pyx_atomic_decr_acq_rel(value) __sync_fetch_and_sub(value, 1) + #define __pyx_atomic_sub(value, arg) __sync_fetch_and_sub(value, arg) + static CYTHON_INLINE int __pyx_atomic_int_cmp_exchange(__pyx_atomic_int_type* value, __pyx_nonatomic_int_type* expected, __pyx_nonatomic_int_type desired) { + __pyx_nonatomic_int_type old = __sync_val_compare_and_swap(value, *expected, desired); + int result = old == *expected; + *expected = old; + return result; + } + #define __pyx_atomic_load(value) __sync_fetch_and_add(value, 0) + #define __pyx_atomic_store(value, new_value) __sync_lock_test_and_set(value, new_value) + #define __pyx_atomic_pointer_load_relaxed(value) __sync_fetch_and_add(value, 0) + #define __pyx_atomic_pointer_load_acquire(value) __sync_fetch_and_add(value, 0) + #define __pyx_atomic_pointer_exchange(value, new_value) __sync_lock_test_and_set(value, (__pyx_atomic_ptr_type)new_value) + static CYTHON_INLINE int __pyx_atomic_pointer_cmp_exchange(__pyx_atomic_ptr_type* value, __pyx_nonatomic_ptr_type* expected, __pyx_nonatomic_ptr_type desired) { + __pyx_nonatomic_ptr_type old = __sync_val_compare_and_swap(value, *expected, desired); + int result = old == *expected; + *expected = old; + return result; + } + #ifdef __PYX_DEBUG_ATOMICS + #warning "Using GNU atomics" + #endif +#elif CYTHON_ATOMICS && defined(_MSC_VER) + #include + #undef __pyx_atomic_int_type + #define __pyx_atomic_int_type long + #define __pyx_atomic_ptr_type void* + #undef __pyx_nonatomic_int_type + #define __pyx_nonatomic_int_type long + #define __pyx_nonatomic_ptr_type void* + #pragma intrinsic (_InterlockedExchangeAdd, _InterlockedExchange, _InterlockedCompareExchange, _InterlockedCompareExchangePointer, _InterlockedExchangePointer) + #define __pyx_atomic_incr_relaxed(value) _InterlockedExchangeAdd(value, 1) + #define __pyx_atomic_incr_acq_rel(value) _InterlockedExchangeAdd(value, 1) + #define __pyx_atomic_decr_acq_rel(value) _InterlockedExchangeAdd(value, -1) + #define __pyx_atomic_sub(value, arg) _InterlockedExchangeAdd(value, -arg) + static CYTHON_INLINE int __pyx_atomic_int_cmp_exchange(__pyx_atomic_int_type* value, __pyx_nonatomic_int_type* expected, __pyx_nonatomic_int_type desired) { + __pyx_nonatomic_int_type old = _InterlockedCompareExchange(value, desired, *expected); + int result = old == *expected; + *expected = old; + return result; + } + #define __pyx_atomic_load(value) _InterlockedExchangeAdd(value, 0) + #define __pyx_atomic_store(value, new_value) _InterlockedExchange(value, new_value) + #define __pyx_atomic_pointer_load_relaxed(value) *(void * volatile *)value + #define __pyx_atomic_pointer_load_acquire(value) _InterlockedCompareExchangePointer(value, 0, 0) + #define __pyx_atomic_pointer_exchange(value, new_value) _InterlockedExchangePointer(value, (__pyx_atomic_ptr_type)new_value) + static CYTHON_INLINE int __pyx_atomic_pointer_cmp_exchange(__pyx_atomic_ptr_type* value, __pyx_nonatomic_ptr_type* expected, __pyx_nonatomic_ptr_type desired) { + __pyx_atomic_ptr_type old = _InterlockedCompareExchangePointer(value, desired, *expected); + int result = old == *expected; + *expected = old; + return result; + } + #ifdef __PYX_DEBUG_ATOMICS + #pragma message ("Using MSVC atomics") + #endif +#else + #undef CYTHON_ATOMICS + #define CYTHON_ATOMICS 0 + #ifdef __PYX_DEBUG_ATOMICS + #warning "Not using atomics" + #endif +#endif + +/* CriticalSectionsDefinition.proto */ +#if !CYTHON_COMPILING_IN_CPYTHON_FREETHREADING +#define __Pyx_PyCriticalSection void* +#define __Pyx_PyCriticalSection2 void* +#define __Pyx_PyCriticalSection_End(cs) +#define __Pyx_PyCriticalSection2_End(cs) +#else +#define __Pyx_PyCriticalSection PyCriticalSection +#define __Pyx_PyCriticalSection2 PyCriticalSection2 +#define __Pyx_PyCriticalSection_End PyCriticalSection_End +#define __Pyx_PyCriticalSection2_End PyCriticalSection2_End +#endif + +/* CriticalSections.proto */ +#if !CYTHON_COMPILING_IN_CPYTHON_FREETHREADING +#define __Pyx_PyCriticalSection_Begin(cs, arg) (void)(cs) +#define __Pyx_PyCriticalSection2_Begin(cs, arg1, arg2) (void)(cs) +#else +#define __Pyx_PyCriticalSection_Begin PyCriticalSection_Begin +#define __Pyx_PyCriticalSection2_Begin PyCriticalSection2_Begin +#endif +#if PY_VERSION_HEX < 0x030d0000 || CYTHON_COMPILING_IN_LIMITED_API +#define __Pyx_BEGIN_CRITICAL_SECTION(o) { +#define __Pyx_END_CRITICAL_SECTION() } +#else +#define __Pyx_BEGIN_CRITICAL_SECTION Py_BEGIN_CRITICAL_SECTION +#define __Pyx_END_CRITICAL_SECTION Py_END_CRITICAL_SECTION +#endif + +/* IncludeStructmemberH.proto */ +#include + +/* #### Code section: numeric_typedefs ### */ +/* #### Code section: complex_type_declarations ### */ +/* #### Code section: type_declarations ### */ + +/*--- Type declarations ---*/ +struct __pyx_opt_args_7cpython_11contextvars_get_value; +struct __pyx_opt_args_7cpython_11contextvars_get_value_no_default; + +/* "cpython/contextvars.pxd":116 + * + * @_cython.c_compile_guard("!CYTHON_COMPILING_IN_LIMITED_API") + * cdef inline object get_value(var, default_value=None): # <<<<<<<<<<<<<< + * """Return a new reference to the value of the context variable, + * or the default value of the context variable, +*/ +struct __pyx_opt_args_7cpython_11contextvars_get_value { + int __pyx_n; + PyObject *default_value; +}; + +/* "cpython/contextvars.pxd":134 + * + * @_cython.c_compile_guard("!CYTHON_COMPILING_IN_LIMITED_API") + * cdef inline object get_value_no_default(var, default_value=None): # <<<<<<<<<<<<<< + * """Return a new reference to the value of the context variable, + * or the provided default value if no such value was found. +*/ +struct __pyx_opt_args_7cpython_11contextvars_get_value_no_default { + int __pyx_n; + PyObject *default_value; +}; +/* #### Code section: utility_code_proto ### */ + +/* --- Runtime support code (head) --- */ +/* Refnanny.proto */ +#ifndef CYTHON_REFNANNY + #define CYTHON_REFNANNY 0 +#endif +#if CYTHON_REFNANNY + typedef struct { + void (*INCREF)(void*, PyObject*, Py_ssize_t); + void (*DECREF)(void*, PyObject*, Py_ssize_t); + void (*GOTREF)(void*, PyObject*, Py_ssize_t); + void (*GIVEREF)(void*, PyObject*, Py_ssize_t); + void* (*SetupContext)(const char*, Py_ssize_t, const char*); + void (*FinishContext)(void**); + } __Pyx_RefNannyAPIStruct; + static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; + static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); + #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL; + #define __Pyx_RefNannySetupContext(name, acquire_gil)\ + if (acquire_gil) {\ + PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), (__LINE__), (__FILE__));\ + PyGILState_Release(__pyx_gilstate_save);\ + } else {\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), (__LINE__), (__FILE__));\ + } + #define __Pyx_RefNannyFinishContextNogil() {\ + PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\ + __Pyx_RefNannyFinishContext();\ + PyGILState_Release(__pyx_gilstate_save);\ + } + #define __Pyx_RefNannyFinishContextNogil() {\ + PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\ + __Pyx_RefNannyFinishContext();\ + PyGILState_Release(__pyx_gilstate_save);\ + } + #define __Pyx_RefNannyFinishContext()\ + __Pyx_RefNanny->FinishContext(&__pyx_refnanny) + #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), (__LINE__)) + #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), (__LINE__)) + #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), (__LINE__)) + #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), (__LINE__)) + #define __Pyx_XINCREF(r) do { if((r) == NULL); else {__Pyx_INCREF(r); }} while(0) + #define __Pyx_XDECREF(r) do { if((r) == NULL); else {__Pyx_DECREF(r); }} while(0) + #define __Pyx_XGOTREF(r) do { if((r) == NULL); else {__Pyx_GOTREF(r); }} while(0) + #define __Pyx_XGIVEREF(r) do { if((r) == NULL); else {__Pyx_GIVEREF(r);}} while(0) +#else + #define __Pyx_RefNannyDeclarations + #define __Pyx_RefNannySetupContext(name, acquire_gil) + #define __Pyx_RefNannyFinishContextNogil() + #define __Pyx_RefNannyFinishContext() + #define __Pyx_INCREF(r) Py_INCREF(r) + #define __Pyx_DECREF(r) Py_DECREF(r) + #define __Pyx_GOTREF(r) + #define __Pyx_GIVEREF(r) + #define __Pyx_XINCREF(r) Py_XINCREF(r) + #define __Pyx_XDECREF(r) Py_XDECREF(r) + #define __Pyx_XGOTREF(r) + #define __Pyx_XGIVEREF(r) +#endif +#define __Pyx_Py_XDECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; Py_XDECREF(tmp);\ + } while (0) +#define __Pyx_XDECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_XDECREF(tmp);\ + } while (0) +#define __Pyx_DECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_DECREF(tmp);\ + } while (0) +#define __Pyx_CLEAR(r) do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0) +#define __Pyx_XCLEAR(r) do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0) + +/* PyTypeError_Check.proto */ +#define __Pyx_PyExc_TypeError_Check(obj) __Pyx_TypeCheck(obj, PyExc_TypeError) + +/* PyUnicode_Unicode.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_Unicode(PyObject *obj); + +/* PyObjectFormatAndDecref.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_FormatSimpleAndDecref(PyObject* s, PyObject* f); +static CYTHON_INLINE PyObject* __Pyx_PyObject_FormatAndDecref(PyObject* s, PyObject* f); + +/* IncludeStringH.proto */ +#include + +/* JoinPyUnicode.export */ +static PyObject* __Pyx_PyUnicode_Join(PyObject** values, Py_ssize_t value_count, Py_ssize_t result_ulength, + Py_UCS4 max_char); + +/* PyObjectCall.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw); +#else +#define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw) +#endif + +/* PyObjectCallMethO.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg); +#endif + +/* PyObjectFastCall.proto */ +#define __Pyx_PyObject_FastCall(func, args, nargs) __Pyx_PyObject_FastCallDict(func, args, (size_t)(nargs), NULL) +static CYTHON_INLINE PyObject* __Pyx_PyObject_FastCallDict(PyObject *func, PyObject * const*args, size_t nargs, PyObject *kwargs); + +/* PyThreadStateGet.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyThreadState_declare PyThreadState *__pyx_tstate; +#define __Pyx_PyThreadState_assign __pyx_tstate = __Pyx_PyThreadState_Current; +#if PY_VERSION_HEX >= 0x030C00A6 +#define __Pyx_PyErr_Occurred() (__pyx_tstate->current_exception != NULL) +#define __Pyx_PyErr_CurrentExceptionType() (__pyx_tstate->current_exception ? (PyObject*) Py_TYPE(__pyx_tstate->current_exception) : (PyObject*) NULL) +#else +#define __Pyx_PyErr_Occurred() (__pyx_tstate->curexc_type != NULL) +#define __Pyx_PyErr_CurrentExceptionType() (__pyx_tstate->curexc_type) +#endif +#else +#define __Pyx_PyThreadState_declare +#define __Pyx_PyThreadState_assign +#define __Pyx_PyErr_Occurred() (PyErr_Occurred() != NULL) +#define __Pyx_PyErr_CurrentExceptionType() PyErr_Occurred() +#endif + +/* PyErrFetchRestore.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyErr_Clear() __Pyx_ErrRestore(NULL, NULL, NULL) +#define __Pyx_ErrRestoreWithState(type, value, tb) __Pyx_ErrRestoreInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) __Pyx_ErrFetchInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) __Pyx_ErrRestoreInState(__pyx_tstate, type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) __Pyx_ErrFetchInState(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030C00A6 +#define __Pyx_PyErr_SetNone(exc) (Py_INCREF(exc), __Pyx_ErrRestore((exc), NULL, NULL)) +#else +#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) +#endif +#else +#define __Pyx_PyErr_Clear() PyErr_Clear() +#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) +#define __Pyx_ErrRestoreWithState(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) PyErr_Fetch(type, value, tb) +#define __Pyx_ErrRestoreInState(tstate, type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetchInState(tstate, type, value, tb) PyErr_Fetch(type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) PyErr_Fetch(type, value, tb) +#endif + +/* RaiseException.export */ +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause); + +/* TupleAndListFromArray.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyList_FromArray(PyObject *const *src, Py_ssize_t n); +#endif +#if CYTHON_COMPILING_IN_CPYTHON || CYTHON_METH_FASTCALL +static CYTHON_INLINE PyObject* __Pyx_PyTuple_FromArray(PyObject *const *src, Py_ssize_t n); +#endif + +/* BytesEquals.proto */ +static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int equals); + +/* UnicodeEquals.proto */ +static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int equals); + +/* fastcall.proto */ +#if CYTHON_AVOID_BORROWED_REFS + #define __Pyx_ArgRef_VARARGS(args, i) __Pyx_PySequence_ITEM(args, i) +#elif CYTHON_ASSUME_SAFE_MACROS + #define __Pyx_ArgRef_VARARGS(args, i) __Pyx_NewRef(__Pyx_PyTuple_GET_ITEM(args, i)) +#else + #define __Pyx_ArgRef_VARARGS(args, i) __Pyx_XNewRef(PyTuple_GetItem(args, i)) +#endif +#define __Pyx_NumKwargs_VARARGS(kwds) PyDict_Size(kwds) +#define __Pyx_KwValues_VARARGS(args, nargs) NULL +#define __Pyx_GetKwValue_VARARGS(kw, kwvalues, s) __Pyx_PyDict_GetItemStrWithError(kw, s) +#define __Pyx_KwargsAsDict_VARARGS(kw, kwvalues) PyDict_Copy(kw) +#if CYTHON_METH_FASTCALL + #define __Pyx_ArgRef_FASTCALL(args, i) __Pyx_NewRef(args[i]) + #define __Pyx_NumKwargs_FASTCALL(kwds) __Pyx_PyTuple_GET_SIZE(kwds) + #define __Pyx_KwValues_FASTCALL(args, nargs) ((args) + (nargs)) + static CYTHON_INLINE PyObject * __Pyx_GetKwValue_FASTCALL(PyObject *kwnames, PyObject *const *kwvalues, PyObject *s); + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030d0000 || CYTHON_COMPILING_IN_LIMITED_API + CYTHON_UNUSED static PyObject *__Pyx_KwargsAsDict_FASTCALL(PyObject *kwnames, PyObject *const *kwvalues); + #else + #define __Pyx_KwargsAsDict_FASTCALL(kw, kwvalues) _PyStack_AsDict(kwvalues, kw) + #endif +#else + #define __Pyx_ArgRef_FASTCALL __Pyx_ArgRef_VARARGS + #define __Pyx_NumKwargs_FASTCALL __Pyx_NumKwargs_VARARGS + #define __Pyx_KwValues_FASTCALL __Pyx_KwValues_VARARGS + #define __Pyx_GetKwValue_FASTCALL __Pyx_GetKwValue_VARARGS + #define __Pyx_KwargsAsDict_FASTCALL __Pyx_KwargsAsDict_VARARGS +#endif +#define __Pyx_ArgsSlice_VARARGS(args, start, stop) PyTuple_GetSlice(args, start, stop) +#if CYTHON_METH_FASTCALL || (CYTHON_COMPILING_IN_CPYTHON && CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS) +#define __Pyx_ArgsSlice_FASTCALL(args, start, stop) __Pyx_PyTuple_FromArray(args + start, stop - start) +#else +#define __Pyx_ArgsSlice_FASTCALL(args, start, stop) PyTuple_GetSlice(args, start, stop) +#endif + +/* py_dict_items.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyDict_Items(PyObject* d); + +/* CallCFunction.proto */ +#define __Pyx_CallCFunction(cfunc, self, args)\ + ((PyCFunction)(void(*)(void))(cfunc)->func)(self, args) +#define __Pyx_CallCFunctionWithKeywords(cfunc, self, args, kwargs)\ + ((PyCFunctionWithKeywords)(void(*)(void))(cfunc)->func)(self, args, kwargs) +#define __Pyx_CallCFunctionFast(cfunc, self, args, nargs)\ + ((__Pyx_PyCFunctionFast)(void(*)(void))(PyCFunction)(cfunc)->func)(self, args, nargs) +#define __Pyx_CallCFunctionFastWithKeywords(cfunc, self, args, nargs, kwnames)\ + ((__Pyx_PyCFunctionFastWithKeywords)(void(*)(void))(PyCFunction)(cfunc)->func)(self, args, nargs, kwnames) + +/* PyObjectCallOneArg.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg); + +/* PyObjectGetAttrStr.proto */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name); +#else +#define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n) +#endif + +/* UnpackUnboundCMethod.proto */ +typedef struct { + PyObject *type; + PyObject **method_name; +#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING && CYTHON_ATOMICS + __pyx_atomic_int_type initialized; +#endif + PyCFunction func; + PyObject *method; + int flag; +} __Pyx_CachedCFunction; +#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING +static CYTHON_INLINE int __Pyx_CachedCFunction_GetAndSetInitializing(__Pyx_CachedCFunction *cfunc) { +#if !CYTHON_ATOMICS + return 1; +#else + __pyx_nonatomic_int_type expected = 0; + if (__pyx_atomic_int_cmp_exchange(&cfunc->initialized, &expected, 1)) { + return 0; + } + return expected; +#endif +} +static CYTHON_INLINE void __Pyx_CachedCFunction_SetFinishedInitializing(__Pyx_CachedCFunction *cfunc) { +#if CYTHON_ATOMICS + __pyx_atomic_store(&cfunc->initialized, 2); +#endif +} +#else +#define __Pyx_CachedCFunction_GetAndSetInitializing(cfunc) 2 +#define __Pyx_CachedCFunction_SetFinishedInitializing(cfunc) +#endif + +/* CallUnboundCMethod0.proto */ +CYTHON_UNUSED +static PyObject* __Pyx__CallUnboundCMethod0(__Pyx_CachedCFunction* cfunc, PyObject* self); +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_CallUnboundCMethod0(__Pyx_CachedCFunction* cfunc, PyObject* self); +#else +#define __Pyx_CallUnboundCMethod0(cfunc, self) __Pyx__CallUnboundCMethod0(cfunc, self) +#endif + +/* py_dict_values.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyDict_Values(PyObject* d); + +/* OwnedDictNext.proto */ +#if CYTHON_AVOID_BORROWED_REFS +static int __Pyx_PyDict_NextRef(PyObject *p, PyObject **ppos, PyObject **pkey, PyObject **pvalue); +#else +CYTHON_INLINE +static int __Pyx_PyDict_NextRef(PyObject *p, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue); +#endif + +/* RaiseDoubleKeywords.proto */ +static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name); + +/* ParseKeywordsImpl.export */ +static int __Pyx_ParseKeywordsTuple( + PyObject *kwds, + PyObject * const *kwvalues, + PyObject ** const argnames[], + PyObject *kwds2, + PyObject *values[], + Py_ssize_t num_pos_args, + Py_ssize_t num_kwargs, + const char* function_name, + int ignore_unknown_kwargs +); +static int __Pyx_ParseKeywordDictToDict( + PyObject *kwds, + PyObject ** const argnames[], + PyObject *kwds2, + PyObject *values[], + Py_ssize_t num_pos_args, + const char* function_name +); +static int __Pyx_ParseKeywordDict( + PyObject *kwds, + PyObject ** const argnames[], + PyObject *values[], + Py_ssize_t num_pos_args, + Py_ssize_t num_kwargs, + const char* function_name, + int ignore_unknown_kwargs +); + +/* CallUnboundCMethod2.proto */ +CYTHON_UNUSED +static PyObject* __Pyx__CallUnboundCMethod2(__Pyx_CachedCFunction* cfunc, PyObject* self, PyObject* arg1, PyObject* arg2); +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject *__Pyx_CallUnboundCMethod2(__Pyx_CachedCFunction *cfunc, PyObject *self, PyObject *arg1, PyObject *arg2); +#else +#define __Pyx_CallUnboundCMethod2(cfunc, self, arg1, arg2) __Pyx__CallUnboundCMethod2(cfunc, self, arg1, arg2) +#endif + +/* ParseKeywords.proto */ +static CYTHON_INLINE int __Pyx_ParseKeywords( + PyObject *kwds, PyObject *const *kwvalues, PyObject ** const argnames[], + PyObject *kwds2, PyObject *values[], + Py_ssize_t num_pos_args, Py_ssize_t num_kwargs, + const char* function_name, + int ignore_unknown_kwargs +); + +/* RaiseArgTupleInvalid.proto */ +static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, + Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); + +/* TypeImport.proto */ +#ifndef __PYX_HAVE_RT_ImportType_proto_3_2_0 +#define __PYX_HAVE_RT_ImportType_proto_3_2_0 +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +#include +#endif +#if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || __cplusplus >= 201103L +#define __PYX_GET_STRUCT_ALIGNMENT_3_2_0(s) alignof(s) +#else +#define __PYX_GET_STRUCT_ALIGNMENT_3_2_0(s) sizeof(void*) +#endif +enum __Pyx_ImportType_CheckSize_3_2_0 { + __Pyx_ImportType_CheckSize_Error_3_2_0 = 0, + __Pyx_ImportType_CheckSize_Warn_3_2_0 = 1, + __Pyx_ImportType_CheckSize_Ignore_3_2_0 = 2 +}; +static PyTypeObject *__Pyx_ImportType_3_2_0(PyObject* module, const char *module_name, const char *class_name, size_t size, size_t alignment, enum __Pyx_ImportType_CheckSize_3_2_0 check_size); +#endif + +/* ListPack.proto */ +static PyObject *__Pyx_PyList_Pack(Py_ssize_t n, ...); + +/* dict_setdefault.proto */ +static CYTHON_INLINE PyObject *__Pyx_PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *default_value); + +/* LimitedApiGetTypeDict.proto */ +#if CYTHON_COMPILING_IN_LIMITED_API +static PyObject *__Pyx_GetTypeDict(PyTypeObject *tp); +#endif + +/* SetItemOnTypeDict.proto */ +static int __Pyx__SetItemOnTypeDict(PyTypeObject *tp, PyObject *k, PyObject *v); +#define __Pyx_SetItemOnTypeDict(tp, k, v) __Pyx__SetItemOnTypeDict((PyTypeObject*)tp, k, v) + +/* FixUpExtensionType.proto */ +static CYTHON_INLINE int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject *type); + +/* AddModuleRef.proto */ +#if ((CYTHON_COMPILING_IN_CPYTHON_FREETHREADING ) ||\ + __PYX_LIMITED_VERSION_HEX < 0x030d0000) + static PyObject *__Pyx_PyImport_AddModuleRef(const char *name); +#else + #define __Pyx_PyImport_AddModuleRef(name) PyImport_AddModuleRef(name) +#endif + +/* FetchSharedCythonModule.proto */ +static PyObject *__Pyx_FetchSharedCythonABIModule(void); + +/* FetchCommonType.proto */ +static PyTypeObject* __Pyx_FetchCommonTypeFromSpec(PyTypeObject *metaclass, PyObject *module, PyType_Spec *spec, PyObject *bases); + +/* CommonTypesMetaclass.proto */ +static int __pyx_CommonTypesMetaclass_init(PyObject *module); +#define __Pyx_CommonTypesMetaclass_USED + +/* CallTypeTraverse.proto */ +#if !CYTHON_USE_TYPE_SPECS || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX < 0x03090000) +#define __Pyx_call_type_traverse(o, always_call, visit, arg) 0 +#else +static int __Pyx_call_type_traverse(PyObject *o, int always_call, visitproc visit, void *arg); +#endif + +/* PyMethodNew.proto */ +static PyObject *__Pyx_PyMethod_New(PyObject *func, PyObject *self, PyObject *typ); + +/* PyVectorcallFastCallDict.proto */ +#if CYTHON_METH_FASTCALL && CYTHON_VECTORCALL +static CYTHON_INLINE PyObject *__Pyx_PyVectorcall_FastCallDict(PyObject *func, __pyx_vectorcallfunc vc, PyObject *const *args, size_t nargs, PyObject *kw); +#endif + +/* CythonFunctionShared.proto */ +#define __Pyx_CyFunction_USED +#define __Pyx_CYFUNCTION_STATICMETHOD 0x01 +#define __Pyx_CYFUNCTION_CLASSMETHOD 0x02 +#define __Pyx_CYFUNCTION_CCLASS 0x04 +#define __Pyx_CYFUNCTION_COROUTINE 0x08 +#define __Pyx_CyFunction_GetClosure(f)\ + (((__pyx_CyFunctionObject *) (f))->func_closure) +#if PY_VERSION_HEX < 0x030900B1 || CYTHON_COMPILING_IN_LIMITED_API + #define __Pyx_CyFunction_GetClassObj(f)\ + (((__pyx_CyFunctionObject *) (f))->func_classobj) +#else + #define __Pyx_CyFunction_GetClassObj(f)\ + ((PyObject*) ((PyCMethodObject *) (f))->mm_class) +#endif +#define __Pyx_CyFunction_SetClassObj(f, classobj)\ + __Pyx__CyFunction_SetClassObj((__pyx_CyFunctionObject *) (f), (classobj)) +#define __Pyx_CyFunction_Defaults(type, f)\ + ((type *)(((__pyx_CyFunctionObject *) (f))->defaults)) +#define __Pyx_CyFunction_SetDefaultsGetter(f, g)\ + ((__pyx_CyFunctionObject *) (f))->defaults_getter = (g) +typedef struct { +#if CYTHON_COMPILING_IN_LIMITED_API + PyObject_HEAD + PyObject *func; +#elif PY_VERSION_HEX < 0x030900B1 + PyCFunctionObject func; +#else + PyCMethodObject func; +#endif +#if CYTHON_COMPILING_IN_LIMITED_API && CYTHON_METH_FASTCALL + __pyx_vectorcallfunc func_vectorcall; +#endif +#if CYTHON_COMPILING_IN_LIMITED_API + PyObject *func_weakreflist; +#endif +#if PY_VERSION_HEX < 0x030C0000 || CYTHON_COMPILING_IN_LIMITED_API + PyObject *func_dict; +#endif + PyObject *func_name; + PyObject *func_qualname; + PyObject *func_doc; + PyObject *func_globals; + PyObject *func_code; + PyObject *func_closure; +#if PY_VERSION_HEX < 0x030900B1 || CYTHON_COMPILING_IN_LIMITED_API + PyObject *func_classobj; +#endif + PyObject *defaults; + int flags; + PyObject *defaults_tuple; + PyObject *defaults_kwdict; + PyObject *(*defaults_getter)(PyObject *); + PyObject *func_annotations; + PyObject *func_is_coroutine; +} __pyx_CyFunctionObject; +#undef __Pyx_CyOrPyCFunction_Check +#define __Pyx_CyFunction_Check(obj) __Pyx_TypeCheck(obj, __pyx_mstate_global->__pyx_CyFunctionType) +#define __Pyx_CyOrPyCFunction_Check(obj) __Pyx_TypeCheck2(obj, __pyx_mstate_global->__pyx_CyFunctionType, &PyCFunction_Type) +#define __Pyx_CyFunction_CheckExact(obj) __Pyx_IS_TYPE(obj, __pyx_mstate_global->__pyx_CyFunctionType) +static CYTHON_INLINE int __Pyx__IsSameCyOrCFunction(PyObject *func, void (*cfunc)(void)); +#undef __Pyx_IsSameCFunction +#define __Pyx_IsSameCFunction(func, cfunc) __Pyx__IsSameCyOrCFunction(func, cfunc) +static PyObject *__Pyx_CyFunction_Init(__pyx_CyFunctionObject* op, PyMethodDef *ml, + int flags, PyObject* qualname, + PyObject *closure, + PyObject *module, PyObject *globals, + PyObject* code); +static CYTHON_INLINE void __Pyx__CyFunction_SetClassObj(__pyx_CyFunctionObject* f, PyObject* classobj); +static CYTHON_INLINE PyObject *__Pyx_CyFunction_InitDefaults(PyObject *func, + PyTypeObject *defaults_type); +static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsTuple(PyObject *m, + PyObject *tuple); +static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsKwDict(PyObject *m, + PyObject *dict); +static CYTHON_INLINE void __Pyx_CyFunction_SetAnnotationsDict(PyObject *m, + PyObject *dict); +static int __pyx_CyFunction_init(PyObject *module); +#if CYTHON_METH_FASTCALL +static PyObject * __Pyx_CyFunction_Vectorcall_NOARGS(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); +static PyObject * __Pyx_CyFunction_Vectorcall_O(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); +static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); +static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS_METHOD(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); +#if CYTHON_COMPILING_IN_LIMITED_API +#define __Pyx_CyFunction_func_vectorcall(f) (((__pyx_CyFunctionObject*)f)->func_vectorcall) +#else +#define __Pyx_CyFunction_func_vectorcall(f) (((PyCFunctionObject*)f)->vectorcall) +#endif +#endif + +/* CythonFunction.proto */ +static PyObject *__Pyx_CyFunction_New(PyMethodDef *ml, + int flags, PyObject* qualname, + PyObject *closure, + PyObject *module, PyObject *globals, + PyObject* code); + +/* PyDictVersioning.proto */ +#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS +#define __PYX_DICT_VERSION_INIT ((PY_UINT64_T) -1) +#define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag) +#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\ + (version_var) = __PYX_GET_DICT_VERSION(dict);\ + (cache_var) = (value); +#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\ + static PY_UINT64_T __pyx_dict_version = 0;\ + static PyObject *__pyx_dict_cached_value = NULL;\ + if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\ + (VAR) = __Pyx_XNewRef(__pyx_dict_cached_value);\ + } else {\ + (VAR) = __pyx_dict_cached_value = (LOOKUP);\ + __pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\ + }\ +} +static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj); +static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj); +static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version); +#else +#define __PYX_GET_DICT_VERSION(dict) (0) +#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var) +#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP); +#endif + +/* PyErrExceptionMatches.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyErr_ExceptionMatches(err) __Pyx_PyErr_ExceptionMatchesInState(__pyx_tstate, err) +static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tstate, PyObject* err); +#else +#define __Pyx_PyErr_ExceptionMatches(err) PyErr_ExceptionMatches(err) +#endif + +/* PyObjectGetAttrStrNoError.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name); + +/* CLineInTraceback.proto */ +#if CYTHON_CLINE_IN_TRACEBACK && CYTHON_CLINE_IN_TRACEBACK_RUNTIME +static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line); +#else +#define __Pyx_CLineForTraceback(tstate, c_line) (((CYTHON_CLINE_IN_TRACEBACK)) ? c_line : 0) +#endif + +/* CodeObjectCache.proto */ +#if CYTHON_COMPILING_IN_LIMITED_API +typedef PyObject __Pyx_CachedCodeObjectType; +#else +typedef PyCodeObject __Pyx_CachedCodeObjectType; +#endif +typedef struct { + __Pyx_CachedCodeObjectType* code_object; + int code_line; +} __Pyx_CodeObjectCacheEntry; +struct __Pyx_CodeObjectCache { + int count; + int max_count; + __Pyx_CodeObjectCacheEntry* entries; + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + __pyx_atomic_int_type accessor_count; + #endif +}; +static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line); +static __Pyx_CachedCodeObjectType *__pyx_find_code_object(int code_line); +static void __pyx_insert_code_object(int code_line, __Pyx_CachedCodeObjectType* code_object); + +/* AddTraceback.proto */ +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename); + +/* GCCDiagnostics.proto */ +#if !defined(__INTEL_COMPILER) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +#define __Pyx_HAS_GCC_DIAGNOSTIC +#endif + +/* PyObjectVectorCallKwBuilder.proto */ +CYTHON_UNUSED static int __Pyx_VectorcallBuilder_AddArg_Check(PyObject *key, PyObject *value, PyObject *builder, PyObject **args, int n); +#if CYTHON_VECTORCALL +#if PY_VERSION_HEX >= 0x03090000 +#define __Pyx_Object_Vectorcall_CallFromBuilder PyObject_Vectorcall +#else +#define __Pyx_Object_Vectorcall_CallFromBuilder _PyObject_Vectorcall +#endif +#define __Pyx_MakeVectorcallBuilderKwds(n) PyTuple_New(n) +static int __Pyx_VectorcallBuilder_AddArg(PyObject *key, PyObject *value, PyObject *builder, PyObject **args, int n); +static int __Pyx_VectorcallBuilder_AddArgStr(const char *key, PyObject *value, PyObject *builder, PyObject **args, int n); +#else +#define __Pyx_Object_Vectorcall_CallFromBuilder __Pyx_PyObject_FastCallDict +#define __Pyx_MakeVectorcallBuilderKwds(n) __Pyx_PyDict_NewPresized(n) +#define __Pyx_VectorcallBuilder_AddArg(key, value, builder, args, n) PyDict_SetItem(builder, key, value) +#define __Pyx_VectorcallBuilder_AddArgStr(key, value, builder, args, n) PyDict_SetItemString(builder, key, value) +#endif + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyLong_From_uint64_t(uint64_t value); + +/* FormatTypeName.proto */ +#if CYTHON_COMPILING_IN_LIMITED_API +typedef PyObject *__Pyx_TypeName; +#define __Pyx_FMT_TYPENAME "%U" +#define __Pyx_DECREF_TypeName(obj) Py_XDECREF(obj) +#if __PYX_LIMITED_VERSION_HEX >= 0x030d0000 +#define __Pyx_PyType_GetFullyQualifiedName PyType_GetFullyQualifiedName +#else +static __Pyx_TypeName __Pyx_PyType_GetFullyQualifiedName(PyTypeObject* tp); +#endif +#else // !LIMITED_API +typedef const char *__Pyx_TypeName; +#define __Pyx_FMT_TYPENAME "%.200s" +#define __Pyx_PyType_GetFullyQualifiedName(tp) ((tp)->tp_name) +#define __Pyx_DECREF_TypeName(obj) +#endif + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyLong_From_long(long value); + +/* CIntFromPy.proto */ +static CYTHON_INLINE long __Pyx_PyLong_As_long(PyObject *); + +/* CIntFromPy.proto */ +static CYTHON_INLINE int __Pyx_PyLong_As_int(PyObject *); + +/* FastTypeChecks.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type) +#define __Pyx_TypeCheck2(obj, type1, type2) __Pyx_IsAnySubtype2(Py_TYPE(obj), (PyTypeObject *)type1, (PyTypeObject *)type2) +static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b); +static CYTHON_INLINE int __Pyx_IsAnySubtype2(PyTypeObject *cls, PyTypeObject *a, PyTypeObject *b); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2); +#else +#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) +#define __Pyx_TypeCheck2(obj, type1, type2) (PyObject_TypeCheck(obj, (PyTypeObject *)type1) || PyObject_TypeCheck(obj, (PyTypeObject *)type2)) +#define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type) +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2) { + return PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2); +} +#endif +#define __Pyx_PyErr_ExceptionMatches2(err1, err2) __Pyx_PyErr_GivenExceptionMatches2(__Pyx_PyErr_CurrentExceptionType(), err1, err2) +#define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception) +#ifdef PyExceptionInstance_Check + #define __Pyx_PyBaseException_Check(obj) PyExceptionInstance_Check(obj) +#else + #define __Pyx_PyBaseException_Check(obj) __Pyx_TypeCheck(obj, PyExc_BaseException) +#endif + +/* GetRuntimeVersion.proto */ +#if __PYX_LIMITED_VERSION_HEX < 0x030b0000 +static unsigned long __Pyx_cached_runtime_version = 0; +static void __Pyx_init_runtime_version(void); +#else +#define __Pyx_init_runtime_version() +#endif +static unsigned long __Pyx_get_runtime_version(void); + +/* CheckBinaryVersion.proto */ +static int __Pyx_check_binary_version(unsigned long ct_version, unsigned long rt_version, int allow_newer); + +/* DecompressString.proto */ +static PyObject *__Pyx_DecompressString(const char *s, Py_ssize_t length, int algo); + +/* MultiPhaseInitModuleState.proto */ +#if CYTHON_PEP489_MULTI_PHASE_INIT && CYTHON_USE_MODULE_STATE +static PyObject *__Pyx_State_FindModule(void*); +static int __Pyx_State_AddModule(PyObject* module, void*); +static int __Pyx_State_RemoveModule(void*); +#elif CYTHON_USE_MODULE_STATE +#define __Pyx_State_FindModule PyState_FindModule +#define __Pyx_State_AddModule PyState_AddModule +#define __Pyx_State_RemoveModule PyState_RemoveModule +#endif + +/* #### Code section: module_declarations ### */ +/* CythonABIVersion.proto */ +#if CYTHON_COMPILING_IN_LIMITED_API + #if CYTHON_METH_FASTCALL + #define __PYX_FASTCALL_ABI_SUFFIX "_fastcall" + #else + #define __PYX_FASTCALL_ABI_SUFFIX + #endif + #define __PYX_LIMITED_ABI_SUFFIX "limited" __PYX_FASTCALL_ABI_SUFFIX __PYX_AM_SEND_ABI_SUFFIX +#else + #define __PYX_LIMITED_ABI_SUFFIX +#endif +#if __PYX_HAS_PY_AM_SEND == 1 + #define __PYX_AM_SEND_ABI_SUFFIX +#elif __PYX_HAS_PY_AM_SEND == 2 + #define __PYX_AM_SEND_ABI_SUFFIX "amsendbackport" +#else + #define __PYX_AM_SEND_ABI_SUFFIX "noamsend" +#endif +#ifndef __PYX_MONITORING_ABI_SUFFIX + #define __PYX_MONITORING_ABI_SUFFIX +#endif +#if CYTHON_USE_TP_FINALIZE + #define __PYX_TP_FINALIZE_ABI_SUFFIX +#else + #define __PYX_TP_FINALIZE_ABI_SUFFIX "nofinalize" +#endif +#if CYTHON_USE_FREELISTS || !defined(__Pyx_AsyncGen_USED) + #define __PYX_FREELISTS_ABI_SUFFIX +#else + #define __PYX_FREELISTS_ABI_SUFFIX "nofreelists" +#endif +#define CYTHON_ABI __PYX_ABI_VERSION __PYX_LIMITED_ABI_SUFFIX __PYX_MONITORING_ABI_SUFFIX __PYX_TP_FINALIZE_ABI_SUFFIX __PYX_FREELISTS_ABI_SUFFIX __PYX_AM_SEND_ABI_SUFFIX +#define __PYX_ABI_MODULE_NAME "_cython_" CYTHON_ABI +#define __PYX_TYPE_MODULE_PREFIX __PYX_ABI_MODULE_NAME "." + +#if !CYTHON_COMPILING_IN_LIMITED_API +static CYTHON_INLINE double __pyx_f_7cpython_7complex_7complex_4real_real(PyComplexObject *__pyx_v_self); /* proto*/ +#endif +#if !CYTHON_COMPILING_IN_LIMITED_API +static CYTHON_INLINE double __pyx_f_7cpython_7complex_7complex_4imag_imag(PyComplexObject *__pyx_v_self); /* proto*/ +#endif + +/* Module declarations from "cpython.buffer" */ + +/* Module declarations from "libc.stddef" */ + +/* Module declarations from "cpython.unicode" */ + +/* Module declarations from "libc.string" */ + +/* Module declarations from "libc.stdio" */ + +/* Module declarations from "__builtin__" */ + +/* Module declarations from "cpython.type" */ + +/* Module declarations from "cpython.version" */ + +/* Module declarations from "cpython.ref" */ + +/* Module declarations from "cpython.exc" */ + +/* Module declarations from "cpython.module" */ + +/* Module declarations from "cpython.mem" */ + +/* Module declarations from "cpython.tuple" */ + +/* Module declarations from "cpython.list" */ + +/* Module declarations from "cpython.sequence" */ + +/* Module declarations from "cpython.mapping" */ + +/* Module declarations from "cpython.iterator" */ + +/* Module declarations from "cpython.number" */ + +/* Module declarations from "__builtin__" */ + +/* Module declarations from "cpython.bool" */ + +/* Module declarations from "cpython.long" */ + +/* Module declarations from "cpython.float" */ + +/* Module declarations from "cython" */ + +/* Module declarations from "__builtin__" */ + +/* Module declarations from "cpython.complex" */ + +/* Module declarations from "cpython.pyport" */ + +/* Module declarations from "cpython.dict" */ + +/* Module declarations from "cpython.instance" */ + +/* Module declarations from "cpython.function" */ + +/* Module declarations from "cpython.method" */ + +/* Module declarations from "cpython.weakref" */ + +/* Module declarations from "cpython.getargs" */ + +/* Module declarations from "cpython.pythread" */ + +/* Module declarations from "cpython.pystate" */ + +/* Module declarations from "cpython.set" */ + +/* Module declarations from "cpython.pycapsule" */ + +/* Module declarations from "cpython.contextvars" */ + +/* Module declarations from "cpython" */ + +/* Module declarations from "cpython.object" */ + +/* Module declarations from "cpython.bytes" */ + +/* Module declarations from "clickhouse_driver._cityhash.cityhash" */ +static PyObject *__pyx_f_17clickhouse_driver_9_cityhash_8cityhash__type_error(PyObject *, PyObject *, PyObject *); /*proto*/ +static PyObject *__pyx_f_17clickhouse_driver_9_cityhash_8cityhash_CityHash128(PyObject *, int __pyx_skip_dispatch); /*proto*/ +/* #### Code section: typeinfo ### */ +/* #### Code section: before_global_var ### */ +#define __Pyx_MODULE_NAME "clickhouse_driver._cityhash.cityhash" +extern int __pyx_module_is_main_clickhouse_driver___cityhash__cityhash; +int __pyx_module_is_main_clickhouse_driver___cityhash__cityhash = 0; + +/* Implementation of "clickhouse_driver._cityhash.cityhash" */ +/* #### Code section: global_var ### */ +/* #### Code section: string_decls ### */ +static const char __pyx_k_A_minimal_Python_wrapper_around[] = "\nA minimal Python wrapper around CityHash 1.0.2, the version of the\nnon-cryptographic hash algorithm used by ClickHouse for block checksums.\n\nVendored from the clickhouse-cityhash package; see LICENSE in this directory.\n"; +/* #### Code section: decls ### */ +static PyObject *__pyx_pf_17clickhouse_driver_9_cityhash_8cityhash_CityHash128(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_data); /* proto */ +/* #### Code section: late_includes ### */ +/* #### Code section: module_state ### */ +/* SmallCodeConfig */ +#ifndef CYTHON_SMALL_CODE +#if defined(__clang__) + #define CYTHON_SMALL_CODE +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) + #define CYTHON_SMALL_CODE __attribute__((cold)) +#else + #define CYTHON_SMALL_CODE +#endif +#endif + +typedef struct { + PyObject *__pyx_d; + PyObject *__pyx_b; + PyObject *__pyx_cython_runtime; + PyObject *__pyx_empty_tuple; + PyObject *__pyx_empty_bytes; + PyObject *__pyx_empty_unicode; + PyTypeObject *__pyx_ptype_7cpython_4type_type; + PyTypeObject *__pyx_ptype_7cpython_4bool_bool; + PyTypeObject *__pyx_ptype_7cpython_7complex_complex; + __Pyx_CachedCFunction __pyx_umethod_PyDict_Type_items; + __Pyx_CachedCFunction __pyx_umethod_PyDict_Type_pop; + __Pyx_CachedCFunction __pyx_umethod_PyDict_Type_values; + PyObject *__pyx_codeobj_tab[1]; + PyObject *__pyx_string_tab[30]; + PyObject *__pyx_number_tab[1]; +/* #### Code section: module_state_contents ### */ +/* CommonTypesMetaclass.module_state_decls */ +PyTypeObject *__pyx_CommonTypesMetaclassType; + +/* CachedMethodType.module_state_decls */ +#if CYTHON_COMPILING_IN_LIMITED_API +PyObject *__Pyx_CachedMethodType; +#endif + +/* CythonFunctionShared.module_state_decls */ +PyTypeObject *__pyx_CyFunctionType; + +/* CodeObjectCache.module_state_decls */ +struct __Pyx_CodeObjectCache __pyx_code_cache; + +/* #### Code section: module_state_end ### */ +} __pyx_mstatetype; + +#if CYTHON_USE_MODULE_STATE +#ifdef __cplusplus +namespace { +extern struct PyModuleDef __pyx_moduledef; +} /* anonymous namespace */ +#else +static struct PyModuleDef __pyx_moduledef; +#endif + +#define __pyx_mstate_global (__Pyx_PyModule_GetState(__Pyx_State_FindModule(&__pyx_moduledef))) + +#define __pyx_m (__Pyx_State_FindModule(&__pyx_moduledef)) +#else +static __pyx_mstatetype __pyx_mstate_global_static = +#ifdef __cplusplus + {}; +#else + {0}; +#endif +static __pyx_mstatetype * const __pyx_mstate_global = &__pyx_mstate_global_static; +#endif +/* #### Code section: constant_name_defines ### */ +#define __pyx_kp_u_ __pyx_string_tab[0] +#define __pyx_kp_u_Argument __pyx_string_tab[1] +#define __pyx_kp_u_None __pyx_string_tab[2] +#define __pyx_kp_u__2 __pyx_string_tab[3] +#define __pyx_kp_u_clickhouse_driver__cityhash_city_2 __pyx_string_tab[4] +#define __pyx_kp_u_got __pyx_string_tab[5] +#define __pyx_kp_u_has_incorrect_type_expected __pyx_string_tab[6] +#define __pyx_n_u_CityHash128 __pyx_string_tab[7] +#define __pyx_n_u_Pyx_PyDict_NextRef __pyx_string_tab[8] +#define __pyx_n_u_all __pyx_string_tab[9] +#define __pyx_n_u_asyncio_coroutines __pyx_string_tab[10] +#define __pyx_n_u_buffer __pyx_string_tab[11] +#define __pyx_n_u_bytes __pyx_string_tab[12] +#define __pyx_n_u_clickhouse_driver__cityhash_city __pyx_string_tab[13] +#define __pyx_n_u_cline_in_traceback __pyx_string_tab[14] +#define __pyx_n_u_data __pyx_string_tab[15] +#define __pyx_n_u_func __pyx_string_tab[16] +#define __pyx_n_u_is_coroutine __pyx_string_tab[17] +#define __pyx_n_u_items __pyx_string_tab[18] +#define __pyx_n_u_main __pyx_string_tab[19] +#define __pyx_n_u_module __pyx_string_tab[20] +#define __pyx_n_u_name __pyx_string_tab[21] +#define __pyx_n_u_pop __pyx_string_tab[22] +#define __pyx_n_u_qualname __pyx_string_tab[23] +#define __pyx_n_u_set_name __pyx_string_tab[24] +#define __pyx_n_u_setdefault __pyx_string_tab[25] +#define __pyx_n_u_str __pyx_string_tab[26] +#define __pyx_n_u_test __pyx_string_tab[27] +#define __pyx_n_u_values __pyx_string_tab[28] +#define __pyx_kp_b_iso88591_aq_AQ_5_a_a_CvS_aq_a_Qa_q_Qa_6 __pyx_string_tab[29] +#define __pyx_int_0x10000000000000000 __pyx_number_tab[0] +/* #### Code section: module_state_clear ### */ +#if CYTHON_USE_MODULE_STATE +static CYTHON_SMALL_CODE int __pyx_m_clear(PyObject *m) { + __pyx_mstatetype *clear_module_state = __Pyx_PyModule_GetState(m); + if (!clear_module_state) return 0; + Py_CLEAR(clear_module_state->__pyx_d); + Py_CLEAR(clear_module_state->__pyx_b); + Py_CLEAR(clear_module_state->__pyx_cython_runtime); + Py_CLEAR(clear_module_state->__pyx_empty_tuple); + Py_CLEAR(clear_module_state->__pyx_empty_bytes); + Py_CLEAR(clear_module_state->__pyx_empty_unicode); + #if CYTHON_PEP489_MULTI_PHASE_INIT + __Pyx_State_RemoveModule(NULL); + #endif + Py_CLEAR(clear_module_state->__pyx_ptype_7cpython_4type_type); + Py_CLEAR(clear_module_state->__pyx_ptype_7cpython_4bool_bool); + Py_CLEAR(clear_module_state->__pyx_ptype_7cpython_7complex_complex); + for (int i=0; i<1; ++i) { Py_CLEAR(clear_module_state->__pyx_codeobj_tab[i]); } + for (int i=0; i<30; ++i) { Py_CLEAR(clear_module_state->__pyx_string_tab[i]); } + for (int i=0; i<1; ++i) { Py_CLEAR(clear_module_state->__pyx_number_tab[i]); } +/* #### Code section: module_state_clear_contents ### */ +/* CommonTypesMetaclass.module_state_clear */ +Py_CLEAR(clear_module_state->__pyx_CommonTypesMetaclassType); + +/* CythonFunctionShared.module_state_clear */ +Py_CLEAR(clear_module_state->__pyx_CyFunctionType); + +/* #### Code section: module_state_clear_end ### */ +return 0; +} +#endif +/* #### Code section: module_state_traverse ### */ +#if CYTHON_USE_MODULE_STATE +static CYTHON_SMALL_CODE int __pyx_m_traverse(PyObject *m, visitproc visit, void *arg) { + __pyx_mstatetype *traverse_module_state = __Pyx_PyModule_GetState(m); + if (!traverse_module_state) return 0; + Py_VISIT(traverse_module_state->__pyx_d); + Py_VISIT(traverse_module_state->__pyx_b); + Py_VISIT(traverse_module_state->__pyx_cython_runtime); + __Pyx_VISIT_CONST(traverse_module_state->__pyx_empty_tuple); + __Pyx_VISIT_CONST(traverse_module_state->__pyx_empty_bytes); + __Pyx_VISIT_CONST(traverse_module_state->__pyx_empty_unicode); + Py_VISIT(traverse_module_state->__pyx_ptype_7cpython_4type_type); + Py_VISIT(traverse_module_state->__pyx_ptype_7cpython_4bool_bool); + Py_VISIT(traverse_module_state->__pyx_ptype_7cpython_7complex_complex); + for (int i=0; i<1; ++i) { __Pyx_VISIT_CONST(traverse_module_state->__pyx_codeobj_tab[i]); } + for (int i=0; i<30; ++i) { __Pyx_VISIT_CONST(traverse_module_state->__pyx_string_tab[i]); } + for (int i=0; i<1; ++i) { __Pyx_VISIT_CONST(traverse_module_state->__pyx_number_tab[i]); } +/* #### Code section: module_state_traverse_contents ### */ +/* CommonTypesMetaclass.module_state_traverse */ +Py_VISIT(traverse_module_state->__pyx_CommonTypesMetaclassType); + +/* CythonFunctionShared.module_state_traverse */ +Py_VISIT(traverse_module_state->__pyx_CyFunctionType); + +/* #### Code section: module_state_traverse_end ### */ +return 0; +} +#endif +/* #### Code section: module_code ### */ + +/* "cpython/complex.pxd":20 + * + * # unavailable in limited API + * @property # <<<<<<<<<<<<<< + * @_cython.c_compile_guard("!CYTHON_COMPILING_IN_LIMITED_API") + * cdef inline double real(self) noexcept: +*/ + +#if !CYTHON_COMPILING_IN_LIMITED_API +static CYTHON_INLINE double __pyx_f_7cpython_7complex_7complex_4real_real(PyComplexObject *__pyx_v_self) { + double __pyx_r; + + /* "cpython/complex.pxd":23 + * @_cython.c_compile_guard("!CYTHON_COMPILING_IN_LIMITED_API") + * cdef inline double real(self) noexcept: + * return self.cval.real # <<<<<<<<<<<<<< + * + * # unavailable in limited API +*/ + __pyx_r = __pyx_v_self->cval.real; + goto __pyx_L0; + + /* "cpython/complex.pxd":20 + * + * # unavailable in limited API + * @property # <<<<<<<<<<<<<< + * @_cython.c_compile_guard("!CYTHON_COMPILING_IN_LIMITED_API") + * cdef inline double real(self) noexcept: +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} +#endif /*!(#if !CYTHON_COMPILING_IN_LIMITED_API)*/ + +/* "cpython/complex.pxd":26 + * + * # unavailable in limited API + * @property # <<<<<<<<<<<<<< + * @_cython.c_compile_guard("!CYTHON_COMPILING_IN_LIMITED_API") + * cdef inline double imag(self) noexcept: +*/ + +#if !CYTHON_COMPILING_IN_LIMITED_API +static CYTHON_INLINE double __pyx_f_7cpython_7complex_7complex_4imag_imag(PyComplexObject *__pyx_v_self) { + double __pyx_r; + + /* "cpython/complex.pxd":29 + * @_cython.c_compile_guard("!CYTHON_COMPILING_IN_LIMITED_API") + * cdef inline double imag(self) noexcept: + * return self.cval.imag # <<<<<<<<<<<<<< + * + * # PyTypeObject PyComplex_Type +*/ + __pyx_r = __pyx_v_self->cval.imag; + goto __pyx_L0; + + /* "cpython/complex.pxd":26 + * + * # unavailable in limited API + * @property # <<<<<<<<<<<<<< + * @_cython.c_compile_guard("!CYTHON_COMPILING_IN_LIMITED_API") + * cdef inline double imag(self) noexcept: +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} +#endif /*!(#if !CYTHON_COMPILING_IN_LIMITED_API)*/ + +/* "cpython/contextvars.pxd":115 + * + * + * @_cython.c_compile_guard("!CYTHON_COMPILING_IN_LIMITED_API") # <<<<<<<<<<<<<< + * cdef inline object get_value(var, default_value=None): + * """Return a new reference to the value of the context variable, +*/ + +#if !CYTHON_COMPILING_IN_LIMITED_API +static CYTHON_INLINE PyObject *__pyx_f_7cpython_11contextvars_get_value(PyObject *__pyx_v_var, struct __pyx_opt_args_7cpython_11contextvars_get_value *__pyx_optional_args) { + + /* "cpython/contextvars.pxd":116 + * + * @_cython.c_compile_guard("!CYTHON_COMPILING_IN_LIMITED_API") + * cdef inline object get_value(var, default_value=None): # <<<<<<<<<<<<<< + * """Return a new reference to the value of the context variable, + * or the default value of the context variable, +*/ + PyObject *__pyx_v_default_value = ((PyObject *)Py_None); + PyObject *__pyx_v_value; + PyObject *__pyx_v_pyvalue = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_t_2; + PyObject *__pyx_t_3 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("get_value", 0); + if (__pyx_optional_args) { + if (__pyx_optional_args->__pyx_n > 0) { + __pyx_v_default_value = __pyx_optional_args->default_value; + } + } + + /* "cpython/contextvars.pxd":121 + * or None if no such value or default was found. + * """ + * cdef PyObject *value = NULL # <<<<<<<<<<<<<< + * PyContextVar_Get(var, NULL, &value) + * if value is NULL: +*/ + __pyx_v_value = NULL; + + /* "cpython/contextvars.pxd":122 + * """ + * cdef PyObject *value = NULL + * PyContextVar_Get(var, NULL, &value) # <<<<<<<<<<<<<< + * if value is NULL: + * # context variable does not have a default +*/ + __pyx_t_1 = PyContextVar_Get(__pyx_v_var, NULL, (&__pyx_v_value)); if (unlikely(__pyx_t_1 == ((int)-1))) __PYX_ERR(1, 122, __pyx_L1_error) + + /* "cpython/contextvars.pxd":123 + * cdef PyObject *value = NULL + * PyContextVar_Get(var, NULL, &value) + * if value is NULL: # <<<<<<<<<<<<<< + * # context variable does not have a default + * pyvalue = default_value +*/ + __pyx_t_2 = (__pyx_v_value == NULL); + if (__pyx_t_2) { + + /* "cpython/contextvars.pxd":125 + * if value is NULL: + * # context variable does not have a default + * pyvalue = default_value # <<<<<<<<<<<<<< + * else: + * # value or default value of context variable +*/ + __Pyx_INCREF(__pyx_v_default_value); + __pyx_v_pyvalue = __pyx_v_default_value; + + /* "cpython/contextvars.pxd":123 + * cdef PyObject *value = NULL + * PyContextVar_Get(var, NULL, &value) + * if value is NULL: # <<<<<<<<<<<<<< + * # context variable does not have a default + * pyvalue = default_value +*/ + goto __pyx_L3; + } + + /* "cpython/contextvars.pxd":128 + * else: + * # value or default value of context variable + * pyvalue = value # <<<<<<<<<<<<<< + * Py_XDECREF(value) # PyContextVar_Get() returned an owned reference as 'PyObject*' + * return pyvalue +*/ + /*else*/ { + __pyx_t_3 = ((PyObject *)__pyx_v_value); + __Pyx_INCREF(__pyx_t_3); + __pyx_v_pyvalue = __pyx_t_3; + __pyx_t_3 = 0; + + /* "cpython/contextvars.pxd":129 + * # value or default value of context variable + * pyvalue = value + * Py_XDECREF(value) # PyContextVar_Get() returned an owned reference as 'PyObject*' # <<<<<<<<<<<<<< + * return pyvalue + * +*/ + Py_XDECREF(__pyx_v_value); + } + __pyx_L3:; + + /* "cpython/contextvars.pxd":130 + * pyvalue = value + * Py_XDECREF(value) # PyContextVar_Get() returned an owned reference as 'PyObject*' + * return pyvalue # <<<<<<<<<<<<<< + * + * +*/ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_pyvalue); + __pyx_r = __pyx_v_pyvalue; + goto __pyx_L0; + + /* "cpython/contextvars.pxd":115 + * + * + * @_cython.c_compile_guard("!CYTHON_COMPILING_IN_LIMITED_API") # <<<<<<<<<<<<<< + * cdef inline object get_value(var, default_value=None): + * """Return a new reference to the value of the context variable, +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_3); + __Pyx_AddTraceback("cpython.contextvars.get_value", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_pyvalue); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} +#endif /*!(#if !CYTHON_COMPILING_IN_LIMITED_API)*/ + +/* "cpython/contextvars.pxd":133 + * + * + * @_cython.c_compile_guard("!CYTHON_COMPILING_IN_LIMITED_API") # <<<<<<<<<<<<<< + * cdef inline object get_value_no_default(var, default_value=None): + * """Return a new reference to the value of the context variable, +*/ + +#if !CYTHON_COMPILING_IN_LIMITED_API +static CYTHON_INLINE PyObject *__pyx_f_7cpython_11contextvars_get_value_no_default(PyObject *__pyx_v_var, struct __pyx_opt_args_7cpython_11contextvars_get_value_no_default *__pyx_optional_args) { + + /* "cpython/contextvars.pxd":134 + * + * @_cython.c_compile_guard("!CYTHON_COMPILING_IN_LIMITED_API") + * cdef inline object get_value_no_default(var, default_value=None): # <<<<<<<<<<<<<< + * """Return a new reference to the value of the context variable, + * or the provided default value if no such value was found. +*/ + PyObject *__pyx_v_default_value = ((PyObject *)Py_None); + PyObject *__pyx_v_value; + PyObject *__pyx_v_pyvalue = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + PyObject *__pyx_t_2 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("get_value_no_default", 0); + if (__pyx_optional_args) { + if (__pyx_optional_args->__pyx_n > 0) { + __pyx_v_default_value = __pyx_optional_args->default_value; + } + } + + /* "cpython/contextvars.pxd":140 + * Ignores the default value of the context variable, if any. + * """ + * cdef PyObject *value = NULL # <<<<<<<<<<<<<< + * PyContextVar_Get(var, default_value, &value) + * # value of context variable or 'default_value' +*/ + __pyx_v_value = NULL; + + /* "cpython/contextvars.pxd":141 + * """ + * cdef PyObject *value = NULL + * PyContextVar_Get(var, default_value, &value) # <<<<<<<<<<<<<< + * # value of context variable or 'default_value' + * pyvalue = value +*/ + __pyx_t_1 = PyContextVar_Get(__pyx_v_var, ((PyObject *)__pyx_v_default_value), (&__pyx_v_value)); if (unlikely(__pyx_t_1 == ((int)-1))) __PYX_ERR(1, 141, __pyx_L1_error) + + /* "cpython/contextvars.pxd":143 + * PyContextVar_Get(var, default_value, &value) + * # value of context variable or 'default_value' + * pyvalue = value # <<<<<<<<<<<<<< + * Py_XDECREF(value) # PyContextVar_Get() returned an owned reference as 'PyObject*' + * return pyvalue +*/ + __pyx_t_2 = ((PyObject *)__pyx_v_value); + __Pyx_INCREF(__pyx_t_2); + __pyx_v_pyvalue = __pyx_t_2; + __pyx_t_2 = 0; + + /* "cpython/contextvars.pxd":144 + * # value of context variable or 'default_value' + * pyvalue = value + * Py_XDECREF(value) # PyContextVar_Get() returned an owned reference as 'PyObject*' # <<<<<<<<<<<<<< + * return pyvalue +*/ + Py_XDECREF(__pyx_v_value); + + /* "cpython/contextvars.pxd":145 + * pyvalue = value + * Py_XDECREF(value) # PyContextVar_Get() returned an owned reference as 'PyObject*' + * return pyvalue # <<<<<<<<<<<<<< +*/ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_pyvalue); + __pyx_r = __pyx_v_pyvalue; + goto __pyx_L0; + + /* "cpython/contextvars.pxd":133 + * + * + * @_cython.c_compile_guard("!CYTHON_COMPILING_IN_LIMITED_API") # <<<<<<<<<<<<<< + * cdef inline object get_value_no_default(var, default_value=None): + * """Return a new reference to the value of the context variable, +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_AddTraceback("cpython.contextvars.get_value_no_default", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_pyvalue); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} +#endif /*!(#if !CYTHON_COMPILING_IN_LIMITED_API)*/ + +/* "clickhouse_driver/_cityhash/cityhash.pyx":46 + * + * + * cdef object _type_error(str argname, expected, value): # <<<<<<<<<<<<<< + * return TypeError( + * "Argument '%s' has incorrect type (expected %s, got %s)" % +*/ + +static PyObject *__pyx_f_17clickhouse_driver_9_cityhash_8cityhash__type_error(PyObject *__pyx_v_argname, PyObject *__pyx_v_expected, PyObject *__pyx_v_value) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6[7]; + PyObject *__pyx_t_7 = NULL; + size_t __pyx_t_8; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("_type_error", 0); + + /* "clickhouse_driver/_cityhash/cityhash.pyx":47 + * + * cdef object _type_error(str argname, expected, value): + * return TypeError( # <<<<<<<<<<<<<< + * "Argument '%s' has incorrect type (expected %s, got %s)" % + * (argname, expected, type(value)) +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_2 = NULL; + + /* "clickhouse_driver/_cityhash/cityhash.pyx":49 + * return TypeError( + * "Argument '%s' has incorrect type (expected %s, got %s)" % + * (argname, expected, type(value)) # <<<<<<<<<<<<<< + * ) + * +*/ + __pyx_t_3 = __Pyx_PyUnicode_Unicode(__pyx_v_argname); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 49, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = __Pyx_PyObject_FormatSimpleAndDecref(PyObject_Str(__pyx_v_expected), __pyx_mstate_global->__pyx_empty_unicode); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 49, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = __Pyx_PyObject_FormatSimpleAndDecref(PyObject_Str(((PyObject *)Py_TYPE(__pyx_v_value))), __pyx_mstate_global->__pyx_empty_unicode); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 49, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_6[0] = __pyx_mstate_global->__pyx_kp_u_Argument; + __pyx_t_6[1] = __pyx_t_3; + __pyx_t_6[2] = __pyx_mstate_global->__pyx_kp_u_has_incorrect_type_expected; + __pyx_t_6[3] = __pyx_t_4; + __pyx_t_6[4] = __pyx_mstate_global->__pyx_kp_u_got; + __pyx_t_6[5] = __pyx_t_5; + __pyx_t_6[6] = __pyx_mstate_global->__pyx_kp_u_; + + /* "clickhouse_driver/_cityhash/cityhash.pyx":48 + * cdef object _type_error(str argname, expected, value): + * return TypeError( + * "Argument '%s' has incorrect type (expected %s, got %s)" % # <<<<<<<<<<<<<< + * (argname, expected, type(value)) + * ) +*/ + __pyx_t_7 = __Pyx_PyUnicode_Join(__pyx_t_6, 7, 10 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_3) + 31 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_4) + 6 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_5) + 1, 127 | __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_3) | __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_4) | __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_5)); + if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 48, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_8 = 1; + { + PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_7}; + __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)(((PyTypeObject*)PyExc_TypeError)), __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 47, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + } + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "clickhouse_driver/_cityhash/cityhash.pyx":46 + * + * + * cdef object _type_error(str argname, expected, value): # <<<<<<<<<<<<<< + * return TypeError( + * "Argument '%s' has incorrect type (expected %s, got %s)" % +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_AddTraceback("clickhouse_driver._cityhash.cityhash._type_error", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "clickhouse_driver/_cityhash/cityhash.pyx":53 + * + * + * cpdef CityHash128(data): # <<<<<<<<<<<<<< + * """128-bit hash function for a bytes, str or buffer type.""" + * cdef Py_buffer buf +*/ + +static PyObject *__pyx_pw_17clickhouse_driver_9_cityhash_8cityhash_1CityHash128(PyObject *__pyx_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +); /*proto*/ +static PyObject *__pyx_f_17clickhouse_driver_9_cityhash_8cityhash_CityHash128(PyObject *__pyx_v_data, CYTHON_UNUSED int __pyx_skip_dispatch) { + Py_buffer __pyx_v_buf; + PyObject *__pyx_v_obj = 0; + std::pair __pyx_v_result; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + PyObject *__pyx_t_2 = NULL; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + size_t __pyx_t_6; + PyObject *__pyx_t_7 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("CityHash128", 0); + + /* "clickhouse_driver/_cityhash/cityhash.pyx":58 + * cdef object obj + * cdef pair[uint64, uint64] result + * if PyUnicode_Check(data): # <<<<<<<<<<<<<< + * obj = PyUnicode_AsUTF8String(data) + * PyObject_GetBuffer(obj, &buf, PyBUF_SIMPLE) +*/ + __pyx_t_1 = PyUnicode_Check(__pyx_v_data); + if (__pyx_t_1) { + + /* "clickhouse_driver/_cityhash/cityhash.pyx":59 + * cdef pair[uint64, uint64] result + * if PyUnicode_Check(data): + * obj = PyUnicode_AsUTF8String(data) # <<<<<<<<<<<<<< + * PyObject_GetBuffer(obj, &buf, PyBUF_SIMPLE) + * result = c_CityHash128(buf.buf, buf.len) +*/ + __pyx_t_2 = PyUnicode_AsUTF8String(__pyx_v_data); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 59, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_v_obj = __pyx_t_2; + __pyx_t_2 = 0; + + /* "clickhouse_driver/_cityhash/cityhash.pyx":60 + * if PyUnicode_Check(data): + * obj = PyUnicode_AsUTF8String(data) + * PyObject_GetBuffer(obj, &buf, PyBUF_SIMPLE) # <<<<<<<<<<<<<< + * result = c_CityHash128(buf.buf, buf.len) + * Py_DECREF(obj) +*/ + __pyx_t_3 = PyObject_GetBuffer(__pyx_v_obj, (&__pyx_v_buf), PyBUF_SIMPLE); if (unlikely(__pyx_t_3 == ((int)-1))) __PYX_ERR(0, 60, __pyx_L1_error) + + /* "clickhouse_driver/_cityhash/cityhash.pyx":61 + * obj = PyUnicode_AsUTF8String(data) + * PyObject_GetBuffer(obj, &buf, PyBUF_SIMPLE) + * result = c_CityHash128(buf.buf, buf.len) # <<<<<<<<<<<<<< + * Py_DECREF(obj) + * elif PyBytes_Check(data): +*/ + __pyx_v_result = CityHash128(((char const *)__pyx_v_buf.buf), __pyx_v_buf.len); + + /* "clickhouse_driver/_cityhash/cityhash.pyx":62 + * PyObject_GetBuffer(obj, &buf, PyBUF_SIMPLE) + * result = c_CityHash128(buf.buf, buf.len) + * Py_DECREF(obj) # <<<<<<<<<<<<<< + * elif PyBytes_Check(data): + * result = c_CityHash128(PyBytes_AS_STRING(data), +*/ + Py_DECREF(__pyx_v_obj); + + /* "clickhouse_driver/_cityhash/cityhash.pyx":58 + * cdef object obj + * cdef pair[uint64, uint64] result + * if PyUnicode_Check(data): # <<<<<<<<<<<<<< + * obj = PyUnicode_AsUTF8String(data) + * PyObject_GetBuffer(obj, &buf, PyBUF_SIMPLE) +*/ + goto __pyx_L3; + } + + /* "clickhouse_driver/_cityhash/cityhash.pyx":63 + * result = c_CityHash128(buf.buf, buf.len) + * Py_DECREF(obj) + * elif PyBytes_Check(data): # <<<<<<<<<<<<<< + * result = c_CityHash128(PyBytes_AS_STRING(data), + * PyBytes_GET_SIZE(data)) +*/ + __pyx_t_1 = PyBytes_Check(__pyx_v_data); + if (__pyx_t_1) { + + /* "clickhouse_driver/_cityhash/cityhash.pyx":64 + * Py_DECREF(obj) + * elif PyBytes_Check(data): + * result = c_CityHash128(PyBytes_AS_STRING(data), # <<<<<<<<<<<<<< + * PyBytes_GET_SIZE(data)) + * elif PyObject_CheckBuffer(data): +*/ + __pyx_v_result = CityHash128(((char const *)PyBytes_AS_STRING(__pyx_v_data)), PyBytes_GET_SIZE(__pyx_v_data)); + + /* "clickhouse_driver/_cityhash/cityhash.pyx":63 + * result = c_CityHash128(buf.buf, buf.len) + * Py_DECREF(obj) + * elif PyBytes_Check(data): # <<<<<<<<<<<<<< + * result = c_CityHash128(PyBytes_AS_STRING(data), + * PyBytes_GET_SIZE(data)) +*/ + goto __pyx_L3; + } + + /* "clickhouse_driver/_cityhash/cityhash.pyx":66 + * result = c_CityHash128(PyBytes_AS_STRING(data), + * PyBytes_GET_SIZE(data)) + * elif PyObject_CheckBuffer(data): # <<<<<<<<<<<<<< + * PyObject_GetBuffer(data, &buf, PyBUF_SIMPLE) + * result = c_CityHash128(buf.buf, buf.len) +*/ + __pyx_t_1 = PyObject_CheckBuffer(__pyx_v_data); + if (likely(__pyx_t_1)) { + + /* "clickhouse_driver/_cityhash/cityhash.pyx":67 + * PyBytes_GET_SIZE(data)) + * elif PyObject_CheckBuffer(data): + * PyObject_GetBuffer(data, &buf, PyBUF_SIMPLE) # <<<<<<<<<<<<<< + * result = c_CityHash128(buf.buf, buf.len) + * else: +*/ + __pyx_t_3 = PyObject_GetBuffer(__pyx_v_data, (&__pyx_v_buf), PyBUF_SIMPLE); if (unlikely(__pyx_t_3 == ((int)-1))) __PYX_ERR(0, 67, __pyx_L1_error) + + /* "clickhouse_driver/_cityhash/cityhash.pyx":68 + * elif PyObject_CheckBuffer(data): + * PyObject_GetBuffer(data, &buf, PyBUF_SIMPLE) + * result = c_CityHash128(buf.buf, buf.len) # <<<<<<<<<<<<<< + * else: + * raise _type_error("data", ["bytes", "str", "buffer"], data) +*/ + __pyx_v_result = CityHash128(((char const *)__pyx_v_buf.buf), __pyx_v_buf.len); + + /* "clickhouse_driver/_cityhash/cityhash.pyx":66 + * result = c_CityHash128(PyBytes_AS_STRING(data), + * PyBytes_GET_SIZE(data)) + * elif PyObject_CheckBuffer(data): # <<<<<<<<<<<<<< + * PyObject_GetBuffer(data, &buf, PyBUF_SIMPLE) + * result = c_CityHash128(buf.buf, buf.len) +*/ + goto __pyx_L3; + } + + /* "clickhouse_driver/_cityhash/cityhash.pyx":70 + * result = c_CityHash128(buf.buf, buf.len) + * else: + * raise _type_error("data", ["bytes", "str", "buffer"], data) # <<<<<<<<<<<<<< + * return 0x10000000000000000 * int(result.first) + int(result.second) +*/ + /*else*/ { + __pyx_t_2 = PyList_New(3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 70, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_mstate_global->__pyx_n_u_bytes); + __Pyx_GIVEREF(__pyx_mstate_global->__pyx_n_u_bytes); + if (__Pyx_PyList_SET_ITEM(__pyx_t_2, 0, __pyx_mstate_global->__pyx_n_u_bytes) != (0)) __PYX_ERR(0, 70, __pyx_L1_error); + __Pyx_INCREF(__pyx_mstate_global->__pyx_n_u_str); + __Pyx_GIVEREF(__pyx_mstate_global->__pyx_n_u_str); + if (__Pyx_PyList_SET_ITEM(__pyx_t_2, 1, __pyx_mstate_global->__pyx_n_u_str) != (0)) __PYX_ERR(0, 70, __pyx_L1_error); + __Pyx_INCREF(__pyx_mstate_global->__pyx_n_u_buffer); + __Pyx_GIVEREF(__pyx_mstate_global->__pyx_n_u_buffer); + if (__Pyx_PyList_SET_ITEM(__pyx_t_2, 2, __pyx_mstate_global->__pyx_n_u_buffer) != (0)) __PYX_ERR(0, 70, __pyx_L1_error); + __pyx_t_4 = __pyx_f_17clickhouse_driver_9_cityhash_8cityhash__type_error(__pyx_mstate_global->__pyx_n_u_data, __pyx_t_2, __pyx_v_data); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 70, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_Raise(__pyx_t_4, 0, 0, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __PYX_ERR(0, 70, __pyx_L1_error) + } + __pyx_L3:; + + /* "clickhouse_driver/_cityhash/cityhash.pyx":71 + * else: + * raise _type_error("data", ["bytes", "str", "buffer"], data) + * return 0x10000000000000000 * int(result.first) + int(result.second) # <<<<<<<<<<<<<< +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_2 = NULL; + __pyx_t_5 = __Pyx_PyLong_From_uint64_t(__pyx_v_result.first); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 71, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_6 = 1; + { + PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_5}; + __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)(&PyLong_Type), __pyx_callargs+__pyx_t_6, (2-__pyx_t_6) | (__pyx_t_6*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 71, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + } + __pyx_t_5 = PyNumber_Multiply(__pyx_mstate_global->__pyx_int_0x10000000000000000, __pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 71, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_2 = NULL; + __pyx_t_7 = __Pyx_PyLong_From_uint64_t(__pyx_v_result.second); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 71, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_6 = 1; + { + PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_7}; + __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)(&PyLong_Type), __pyx_callargs+__pyx_t_6, (2-__pyx_t_6) | (__pyx_t_6*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 71, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + } + __pyx_t_7 = PyNumber_Add(__pyx_t_5, __pyx_t_4); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 71, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_r = __pyx_t_7; + __pyx_t_7 = 0; + goto __pyx_L0; + + /* "clickhouse_driver/_cityhash/cityhash.pyx":53 + * + * + * cpdef CityHash128(data): # <<<<<<<<<<<<<< + * """128-bit hash function for a bytes, str or buffer type.""" + * cdef Py_buffer buf +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_AddTraceback("clickhouse_driver._cityhash.cityhash.CityHash128", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_obj); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* Python wrapper */ +static PyObject *__pyx_pw_17clickhouse_driver_9_cityhash_8cityhash_1CityHash128(PyObject *__pyx_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +); /*proto*/ +PyDoc_STRVAR(__pyx_doc_17clickhouse_driver_9_cityhash_8cityhash_CityHash128, "128-bit hash function for a bytes, str or buffer type."); +static PyMethodDef __pyx_mdef_17clickhouse_driver_9_cityhash_8cityhash_1CityHash128 = {"CityHash128", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_17clickhouse_driver_9_cityhash_8cityhash_1CityHash128, __Pyx_METH_FASTCALL|METH_KEYWORDS, __pyx_doc_17clickhouse_driver_9_cityhash_8cityhash_CityHash128}; +static PyObject *__pyx_pw_17clickhouse_driver_9_cityhash_8cityhash_1CityHash128(PyObject *__pyx_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +) { + PyObject *__pyx_v_data = 0; + #if !CYTHON_METH_FASTCALL + CYTHON_UNUSED Py_ssize_t __pyx_nargs; + #endif + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject* values[1] = {0}; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("CityHash128 (wrapper)", 0); + #if !CYTHON_METH_FASTCALL + #if CYTHON_ASSUME_SAFE_SIZE + __pyx_nargs = PyTuple_GET_SIZE(__pyx_args); + #else + __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL; + #endif + #endif + __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs); + { + PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_data,0}; + const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0; + if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 53, __pyx_L3_error) + if (__pyx_kwds_len > 0) { + switch (__pyx_nargs) { + case 1: + values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 53, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + const Py_ssize_t kwd_pos_args = __pyx_nargs; + if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "CityHash128", 0) < (0)) __PYX_ERR(0, 53, __pyx_L3_error) + for (Py_ssize_t i = __pyx_nargs; i < 1; i++) { + if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("CityHash128", 1, 1, 1, i); __PYX_ERR(0, 53, __pyx_L3_error) } + } + } else if (unlikely(__pyx_nargs != 1)) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 53, __pyx_L3_error) + } + __pyx_v_data = values[0]; + } + goto __pyx_L6_skip; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("CityHash128", 1, 1, 1, __pyx_nargs); __PYX_ERR(0, 53, __pyx_L3_error) + __pyx_L6_skip:; + goto __pyx_L4_argument_unpacking_done; + __pyx_L3_error:; + for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { + Py_XDECREF(values[__pyx_temp]); + } + __Pyx_AddTraceback("clickhouse_driver._cityhash.cityhash.CityHash128", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_17clickhouse_driver_9_cityhash_8cityhash_CityHash128(__pyx_self, __pyx_v_data); + + /* function exit code */ + for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { + Py_XDECREF(values[__pyx_temp]); + } + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_17clickhouse_driver_9_cityhash_8cityhash_CityHash128(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_data) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("CityHash128", 0); + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __pyx_f_17clickhouse_driver_9_cityhash_8cityhash_CityHash128(__pyx_v_data, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 53, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("clickhouse_driver._cityhash.cityhash.CityHash128", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} +/* #### Code section: module_exttypes ### */ + +static PyMethodDef __pyx_methods[] = { + {0, 0, 0, 0} +}; +/* #### Code section: initfunc_declarations ### */ +static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(__pyx_mstatetype *__pyx_mstate); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(__pyx_mstatetype *__pyx_mstate); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_InitConstants(__pyx_mstatetype *__pyx_mstate); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_global_init_code(__pyx_mstatetype *__pyx_mstate); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_variable_export_code(__pyx_mstatetype *__pyx_mstate); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_function_export_code(__pyx_mstatetype *__pyx_mstate); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_type_init_code(__pyx_mstatetype *__pyx_mstate); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_type_import_code(__pyx_mstatetype *__pyx_mstate); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_variable_import_code(__pyx_mstatetype *__pyx_mstate); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_function_import_code(__pyx_mstatetype *__pyx_mstate); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_CreateCodeObjects(__pyx_mstatetype *__pyx_mstate); /*proto*/ +/* #### Code section: init_module ### */ + +static int __Pyx_modinit_global_init_code(__pyx_mstatetype *__pyx_mstate) { + __Pyx_RefNannyDeclarations + CYTHON_UNUSED_VAR(__pyx_mstate); + __Pyx_RefNannySetupContext("__Pyx_modinit_global_init_code", 0); + /*--- Global init code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_variable_export_code(__pyx_mstatetype *__pyx_mstate) { + __Pyx_RefNannyDeclarations + CYTHON_UNUSED_VAR(__pyx_mstate); + __Pyx_RefNannySetupContext("__Pyx_modinit_variable_export_code", 0); + /*--- Variable export code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_function_export_code(__pyx_mstatetype *__pyx_mstate) { + __Pyx_RefNannyDeclarations + CYTHON_UNUSED_VAR(__pyx_mstate); + __Pyx_RefNannySetupContext("__Pyx_modinit_function_export_code", 0); + /*--- Function export code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_type_init_code(__pyx_mstatetype *__pyx_mstate) { + __Pyx_RefNannyDeclarations + CYTHON_UNUSED_VAR(__pyx_mstate); + __Pyx_RefNannySetupContext("__Pyx_modinit_type_init_code", 0); + /*--- Type init code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_type_import_code(__pyx_mstatetype *__pyx_mstate) { + __Pyx_RefNannyDeclarations + CYTHON_UNUSED_VAR(__pyx_mstate); + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__Pyx_modinit_type_import_code", 0); + /*--- Type import code ---*/ + __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_mstate->__pyx_ptype_7cpython_4type_type = __Pyx_ImportType_3_2_0(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "type", + #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 + sizeof(PyTypeObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_0(PyTypeObject), + #elif CYTHON_COMPILING_IN_LIMITED_API + 0, 0, + #else + sizeof(PyHeapTypeObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_0(PyHeapTypeObject), + #endif + __Pyx_ImportType_CheckSize_Warn_3_2_0); if (!__pyx_mstate->__pyx_ptype_7cpython_4type_type) __PYX_ERR(2, 9, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(3, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_mstate->__pyx_ptype_7cpython_4bool_bool = __Pyx_ImportType_3_2_0(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "bool", + #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 + sizeof(PyLongObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_0(PyLongObject), + #elif CYTHON_COMPILING_IN_LIMITED_API + 0, 0, + #else + sizeof(PyLongObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_0(PyLongObject), + #endif + __Pyx_ImportType_CheckSize_Warn_3_2_0); if (!__pyx_mstate->__pyx_ptype_7cpython_4bool_bool) __PYX_ERR(3, 8, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(4, 16, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_mstate->__pyx_ptype_7cpython_7complex_complex = __Pyx_ImportType_3_2_0(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "complex", + #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 + sizeof(PyComplexObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_0(PyComplexObject), + #elif CYTHON_COMPILING_IN_LIMITED_API + 0, 0, + #else + sizeof(PyComplexObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_0(PyComplexObject), + #endif + __Pyx_ImportType_CheckSize_Warn_3_2_0); if (!__pyx_mstate->__pyx_ptype_7cpython_7complex_complex) __PYX_ERR(4, 16, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_RefNannyFinishContext(); + return 0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_RefNannyFinishContext(); + return -1; +} + +static int __Pyx_modinit_variable_import_code(__pyx_mstatetype *__pyx_mstate) { + __Pyx_RefNannyDeclarations + CYTHON_UNUSED_VAR(__pyx_mstate); + __Pyx_RefNannySetupContext("__Pyx_modinit_variable_import_code", 0); + /*--- Variable import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_function_import_code(__pyx_mstatetype *__pyx_mstate) { + __Pyx_RefNannyDeclarations + CYTHON_UNUSED_VAR(__pyx_mstate); + __Pyx_RefNannySetupContext("__Pyx_modinit_function_import_code", 0); + /*--- Function import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +#if CYTHON_PEP489_MULTI_PHASE_INIT +static PyObject* __pyx_pymod_create(PyObject *spec, PyModuleDef *def); /*proto*/ +static int __pyx_pymod_exec_cityhash(PyObject* module); /*proto*/ +static PyModuleDef_Slot __pyx_moduledef_slots[] = { + {Py_mod_create, (void*)__pyx_pymod_create}, + {Py_mod_exec, (void*)__pyx_pymod_exec_cityhash}, + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + {Py_mod_gil, Py_MOD_GIL_USED}, + #endif + #if PY_VERSION_HEX >= 0x030C0000 && CYTHON_USE_MODULE_STATE + {Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED}, + #endif + {0, NULL} +}; +#endif + +#ifdef __cplusplus +namespace { + struct PyModuleDef __pyx_moduledef = + #else + static struct PyModuleDef __pyx_moduledef = + #endif + { + PyModuleDef_HEAD_INIT, + "cityhash", + __pyx_k_A_minimal_Python_wrapper_around, /* m_doc */ + #if CYTHON_USE_MODULE_STATE + sizeof(__pyx_mstatetype), /* m_size */ + #else + (CYTHON_PEP489_MULTI_PHASE_INIT) ? 0 : -1, /* m_size */ + #endif + __pyx_methods /* m_methods */, + #if CYTHON_PEP489_MULTI_PHASE_INIT + __pyx_moduledef_slots, /* m_slots */ + #else + NULL, /* m_reload */ + #endif + #if CYTHON_USE_MODULE_STATE + __pyx_m_traverse, /* m_traverse */ + __pyx_m_clear, /* m_clear */ + NULL /* m_free */ + #else + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL /* m_free */ + #endif + }; + #ifdef __cplusplus +} /* anonymous namespace */ +#endif + +/* PyModInitFuncType */ +#ifndef CYTHON_NO_PYINIT_EXPORT + #define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC +#else + #ifdef __cplusplus + #define __Pyx_PyMODINIT_FUNC extern "C" PyObject * + #else + #define __Pyx_PyMODINIT_FUNC PyObject * + #endif +#endif + +__Pyx_PyMODINIT_FUNC PyInit_cityhash(void) CYTHON_SMALL_CODE; /*proto*/ +__Pyx_PyMODINIT_FUNC PyInit_cityhash(void) +#if CYTHON_PEP489_MULTI_PHASE_INIT +{ + return PyModuleDef_Init(&__pyx_moduledef); +} +/* ModuleCreationPEP489 */ +#if CYTHON_COMPILING_IN_LIMITED_API && (__PYX_LIMITED_VERSION_HEX < 0x03090000\ + || ((defined(_WIN32) || defined(WIN32) || defined(MS_WINDOWS)) && __PYX_LIMITED_VERSION_HEX < 0x030A0000)) +static PY_INT64_T __Pyx_GetCurrentInterpreterId(void) { + { + PyObject *module = PyImport_ImportModule("_interpreters"); // 3.13+ I think + if (!module) { + PyErr_Clear(); // just try the 3.8-3.12 version + module = PyImport_ImportModule("_xxsubinterpreters"); + if (!module) goto bad; + } + PyObject *current = PyObject_CallMethod(module, "get_current", NULL); + Py_DECREF(module); + if (!current) goto bad; + if (PyTuple_Check(current)) { + PyObject *new_current = PySequence_GetItem(current, 0); + Py_DECREF(current); + current = new_current; + if (!new_current) goto bad; + } + long long as_c_int = PyLong_AsLongLong(current); + Py_DECREF(current); + return as_c_int; + } + bad: + PySys_WriteStderr("__Pyx_GetCurrentInterpreterId failed. Try setting the C define CYTHON_PEP489_MULTI_PHASE_INIT=0\n"); + return -1; +} +#endif +#if !CYTHON_USE_MODULE_STATE +static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) { + static PY_INT64_T main_interpreter_id = -1; +#if CYTHON_COMPILING_IN_GRAAL && defined(GRAALPY_VERSION_NUM) && GRAALPY_VERSION_NUM > 0x19000000 + PY_INT64_T current_id = GraalPyInterpreterState_GetIDFromThreadState(PyThreadState_Get()); +#elif CYTHON_COMPILING_IN_GRAAL + PY_INT64_T current_id = PyInterpreterState_GetIDFromThreadState(PyThreadState_Get()); +#elif CYTHON_COMPILING_IN_LIMITED_API && (__PYX_LIMITED_VERSION_HEX < 0x03090000\ + || ((defined(_WIN32) || defined(WIN32) || defined(MS_WINDOWS)) && __PYX_LIMITED_VERSION_HEX < 0x030A0000)) + PY_INT64_T current_id = __Pyx_GetCurrentInterpreterId(); +#elif CYTHON_COMPILING_IN_LIMITED_API + PY_INT64_T current_id = PyInterpreterState_GetID(PyInterpreterState_Get()); +#else + PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()->interp); +#endif + if (unlikely(current_id == -1)) { + return -1; + } + if (main_interpreter_id == -1) { + main_interpreter_id = current_id; + return 0; + } else if (unlikely(main_interpreter_id != current_id)) { + PyErr_SetString( + PyExc_ImportError, + "Interpreter change detected - this module can only be loaded into one interpreter per process."); + return -1; + } + return 0; +} +#endif +static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name, int allow_none) +{ + PyObject *value = PyObject_GetAttrString(spec, from_name); + int result = 0; + if (likely(value)) { + if (allow_none || value != Py_None) { + result = PyDict_SetItemString(moddict, to_name, value); + } + Py_DECREF(value); + } else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + } else { + result = -1; + } + return result; +} +static CYTHON_SMALL_CODE PyObject* __pyx_pymod_create(PyObject *spec, PyModuleDef *def) { + PyObject *module = NULL, *moddict, *modname; + CYTHON_UNUSED_VAR(def); + #if !CYTHON_USE_MODULE_STATE + if (__Pyx_check_single_interpreter()) + return NULL; + #endif + if (__pyx_m) + return __Pyx_NewRef(__pyx_m); + modname = PyObject_GetAttrString(spec, "name"); + if (unlikely(!modname)) goto bad; + module = PyModule_NewObject(modname); + Py_DECREF(modname); + if (unlikely(!module)) goto bad; + moddict = PyModule_GetDict(module); + if (unlikely(!moddict)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "loader", "__loader__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "origin", "__file__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "parent", "__package__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "submodule_search_locations", "__path__", 0) < 0)) goto bad; + return module; +bad: + Py_XDECREF(module); + return NULL; +} + + +static CYTHON_SMALL_CODE int __pyx_pymod_exec_cityhash(PyObject *__pyx_pyinit_module) +#endif +{ + int stringtab_initialized = 0; + #if CYTHON_USE_MODULE_STATE + int pystate_addmodule_run = 0; + #endif + __pyx_mstatetype *__pyx_mstate = NULL; + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannyDeclarations + #if CYTHON_PEP489_MULTI_PHASE_INIT + if (__pyx_m) { + if (__pyx_m == __pyx_pyinit_module) return 0; + PyErr_SetString(PyExc_RuntimeError, "Module 'cityhash' has already been imported. Re-initialisation is not supported."); + return -1; + } + #else + if (__pyx_m) return __Pyx_NewRef(__pyx_m); + #endif + /*--- Module creation code ---*/ + #if CYTHON_PEP489_MULTI_PHASE_INIT + __pyx_t_1 = __pyx_pyinit_module; + Py_INCREF(__pyx_t_1); + #else + __pyx_t_1 = PyModule_Create(&__pyx_moduledef); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #if CYTHON_USE_MODULE_STATE + { + int add_module_result = __Pyx_State_AddModule(__pyx_t_1, &__pyx_moduledef); + __pyx_t_1 = 0; /* transfer ownership from __pyx_t_1 to "cityhash" pseudovariable */ + if (unlikely((add_module_result < 0))) __PYX_ERR(0, 1, __pyx_L1_error) + pystate_addmodule_run = 1; + } + #else + __pyx_m = __pyx_t_1; + #endif + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + PyUnstable_Module_SetGIL(__pyx_m, Py_MOD_GIL_USED); + #endif + __pyx_mstate = __pyx_mstate_global; + CYTHON_UNUSED_VAR(__pyx_t_1); + __pyx_mstate->__pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_mstate->__pyx_d)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_mstate->__pyx_d); + __pyx_mstate->__pyx_b = __Pyx_PyImport_AddModuleRef(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_mstate->__pyx_b)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_mstate->__pyx_cython_runtime = __Pyx_PyImport_AddModuleRef("cython_runtime"); if (unlikely(!__pyx_mstate->__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error) + if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_mstate->__pyx_b) < 0) __PYX_ERR(0, 1, __pyx_L1_error) + /* ImportRefnannyAPI */ + #if CYTHON_REFNANNY + __Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); + if (!__Pyx_RefNanny) { + PyErr_Clear(); + __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); + if (!__Pyx_RefNanny) + Py_FatalError("failed to import 'refnanny' module"); + } + #endif + +__Pyx_RefNannySetupContext("PyInit_cityhash", 0); + __Pyx_init_runtime_version(); + if (__Pyx_check_binary_version(__PYX_LIMITED_VERSION_HEX, __Pyx_get_runtime_version(), CYTHON_COMPILING_IN_LIMITED_API) < (0)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_mstate->__pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_mstate->__pyx_empty_tuple)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_mstate->__pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_mstate->__pyx_empty_bytes)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_mstate->__pyx_empty_unicode = PyUnicode_FromStringAndSize("", 0); if (unlikely(!__pyx_mstate->__pyx_empty_unicode)) __PYX_ERR(0, 1, __pyx_L1_error) + /*--- Library function declarations ---*/ + /*--- Initialize various global constants etc. ---*/ + if (__Pyx_InitConstants(__pyx_mstate) < (0)) __PYX_ERR(0, 1, __pyx_L1_error) + stringtab_initialized = 1; + if (__Pyx_InitGlobals() < (0)) __PYX_ERR(0, 1, __pyx_L1_error) + if (__pyx_module_is_main_clickhouse_driver___cityhash__cityhash) { + if (PyObject_SetAttr(__pyx_m, __pyx_mstate_global->__pyx_n_u_name, __pyx_mstate_global->__pyx_n_u_main) < (0)) __PYX_ERR(0, 1, __pyx_L1_error) + } + { + PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) __PYX_ERR(0, 1, __pyx_L1_error) + if (!PyDict_GetItemString(modules, "clickhouse_driver._cityhash.cityhash")) { + if (unlikely((PyDict_SetItemString(modules, "clickhouse_driver._cityhash.cityhash", __pyx_m) < 0))) __PYX_ERR(0, 1, __pyx_L1_error) + } + } + /*--- Builtin init code ---*/ + if (__Pyx_InitCachedBuiltins(__pyx_mstate) < (0)) __PYX_ERR(0, 1, __pyx_L1_error) + /*--- Constants init code ---*/ + if (__Pyx_InitCachedConstants(__pyx_mstate) < (0)) __PYX_ERR(0, 1, __pyx_L1_error) + if (__Pyx_CreateCodeObjects(__pyx_mstate) < (0)) __PYX_ERR(0, 1, __pyx_L1_error) + /*--- Global type/function init code ---*/ + (void)__Pyx_modinit_global_init_code(__pyx_mstate); + (void)__Pyx_modinit_variable_export_code(__pyx_mstate); + (void)__Pyx_modinit_function_export_code(__pyx_mstate); + (void)__Pyx_modinit_type_init_code(__pyx_mstate); + if (unlikely((__Pyx_modinit_type_import_code(__pyx_mstate) < 0))) __PYX_ERR(0, 1, __pyx_L1_error) + (void)__Pyx_modinit_variable_import_code(__pyx_mstate); + (void)__Pyx_modinit_function_import_code(__pyx_mstate); + /*--- Execution code ---*/ + + /* "clickhouse_driver/_cityhash/cityhash.pyx":10 + * """ + * + * __all__ = ["CityHash128"] # <<<<<<<<<<<<<< + * + * cdef extern from * nogil: +*/ + __pyx_t_2 = __Pyx_PyList_Pack(1, __pyx_mstate_global->__pyx_n_u_CityHash128); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 10, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_all, __pyx_t_2) < (0)) __PYX_ERR(0, 10, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "clickhouse_driver/_cityhash/cityhash.pyx":53 + * + * + * cpdef CityHash128(data): # <<<<<<<<<<<<<< + * """128-bit hash function for a bytes, str or buffer type.""" + * cdef Py_buffer buf +*/ + __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_9_cityhash_8cityhash_1CityHash128, 0, __pyx_mstate_global->__pyx_n_u_CityHash128, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver__cityhash_city, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[0])); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 53, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000 + PyUnstable_Object_EnableDeferredRefcount(__pyx_t_2); + #endif + if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_CityHash128, __pyx_t_2) < (0)) __PYX_ERR(0, 53, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "clickhouse_driver/_cityhash/cityhash.pyx":1 + * # cython: infer_types=True # <<<<<<<<<<<<<< + * + * """ +*/ + __pyx_t_2 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_test, __pyx_t_2) < (0)) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /*--- Wrapped vars code ---*/ + + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + if (__pyx_m) { + if (__pyx_mstate->__pyx_d && stringtab_initialized) { + __Pyx_AddTraceback("init clickhouse_driver._cityhash.cityhash", __pyx_clineno, __pyx_lineno, __pyx_filename); + } + #if !CYTHON_USE_MODULE_STATE + Py_CLEAR(__pyx_m); + #else + Py_DECREF(__pyx_m); + if (pystate_addmodule_run) { + PyObject *tp, *value, *tb; + PyErr_Fetch(&tp, &value, &tb); + PyState_RemoveModule(&__pyx_moduledef); + PyErr_Restore(tp, value, tb); + } + #endif + } else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_ImportError, "init clickhouse_driver._cityhash.cityhash"); + } + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + #if CYTHON_PEP489_MULTI_PHASE_INIT + return (__pyx_m != NULL) ? 0 : -1; + #else + return __pyx_m; + #endif +} +/* #### Code section: pystring_table ### */ +/* #### Code section: cached_builtins ### */ + +static int __Pyx_InitCachedBuiltins(__pyx_mstatetype *__pyx_mstate) { + CYTHON_UNUSED_VAR(__pyx_mstate); + + /* Cached unbound methods */ + __pyx_mstate->__pyx_umethod_PyDict_Type_items.type = (PyObject*)&PyDict_Type; + __pyx_mstate->__pyx_umethod_PyDict_Type_items.method_name = &__pyx_mstate->__pyx_n_u_items; + __pyx_mstate->__pyx_umethod_PyDict_Type_pop.type = (PyObject*)&PyDict_Type; + __pyx_mstate->__pyx_umethod_PyDict_Type_pop.method_name = &__pyx_mstate->__pyx_n_u_pop; + __pyx_mstate->__pyx_umethod_PyDict_Type_values.type = (PyObject*)&PyDict_Type; + __pyx_mstate->__pyx_umethod_PyDict_Type_values.method_name = &__pyx_mstate->__pyx_n_u_values; + return 0; +} +/* #### Code section: cached_constants ### */ + +static int __Pyx_InitCachedConstants(__pyx_mstatetype *__pyx_mstate) { + __Pyx_RefNannyDeclarations + CYTHON_UNUSED_VAR(__pyx_mstate); + __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); + __Pyx_RefNannyFinishContext(); + return 0; +} +/* #### Code section: init_constants ### */ + +static int __Pyx_InitConstants(__pyx_mstatetype *__pyx_mstate) { + CYTHON_UNUSED_VAR(__pyx_mstate); + { + const struct { const unsigned int length: 8; } index[] = {{1},{10},{4},{1},{40},{6},{31},{11},{20},{7},{18},{6},{5},{36},{18},{4},{8},{13},{5},{8},{10},{8},{3},{12},{12},{10},{3},{8},{6},{172}}; + #if (CYTHON_COMPRESS_STRINGS) == 2 /* compression: bz2 (440 bytes) */ +const char* const cstring = "BZh91AY&SY\023\236\364#\033\226\364\233\023\274#|i3\232\331\212\367`\267`\220\222\255)@1\t<\277\006\334\360\341\332;\242\226\014\031s \340\250\210\030@\030\022\243\263\252\372\366\202M\000l\236\252\315A\2565\206qG\024\022\223\366\212D}\005y\304\224\256\272\210}\314\221S\024\3269\010v\210\323[\\\351um\014B\005\017\214\376\366B\236\216\233\013\000\357\000r\013CSV\244l\tQ\016\247@0\002O\310~\241\027\002\213\301!s\254\220B\2073&H\221\003\036\"X'\311\200\310,\275W\315O/\0054\224bpO\374]\020\271}\222\333X\230Oa.\004@gZ\354\322\026\343\311'_\267^\000\243\241$/uV\344\222\306\354\326@R\206\330\210F4JB3]\367\256\027\253\376=\331\010;\352Q\313\224'0\314\006\237H\t\215\343\374\353R\231\237\020cjp\246\217!\213%_~\301\305#\235\271}\273\321\335\212\024 (\347A\220\377\027rE8P\220__pyx_string_tab; + Py_ssize_t pos = 0; + for (int i = 0; i < 29; i++) { + Py_ssize_t bytes_length = index[i].length; + PyObject *string = PyUnicode_DecodeUTF8(bytes + pos, bytes_length, NULL); + if (likely(string) && i >= 7) PyUnicode_InternInPlace(&string); + if (unlikely(!string)) { + Py_XDECREF(data); + __PYX_ERR(0, 1, __pyx_L1_error) + } + stringtab[i] = string; + pos += bytes_length; + } + for (int i = 29; i < 30; i++) { + Py_ssize_t bytes_length = index[i].length; + PyObject *string = PyBytes_FromStringAndSize(bytes + pos, bytes_length); + stringtab[i] = string; + pos += bytes_length; + if (unlikely(!string)) { + Py_XDECREF(data); + __PYX_ERR(0, 1, __pyx_L1_error) + } + } + Py_XDECREF(data); + for (Py_ssize_t i = 0; i < 30; i++) { + if (unlikely(PyObject_Hash(stringtab[i]) == -1)) { + __PYX_ERR(0, 1, __pyx_L1_error) + } + } + #if CYTHON_IMMORTAL_CONSTANTS + { + PyObject **table = stringtab + 29; + for (Py_ssize_t i=0; i<1; ++i) { + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + Py_SET_REFCNT(table[i], _Py_IMMORTAL_REFCNT_LOCAL); + #else + Py_SET_REFCNT(table[i], _Py_IMMORTAL_INITIAL_REFCNT); + #endif + } + } + #endif + } + { + PyObject **numbertab = __pyx_mstate->__pyx_number_tab + 0; + const char* c_constant = "g000000000000"; + for (int i = 0; i < 1; i++) { + char *end_pos; + numbertab[i] = PyLong_FromString(c_constant, &end_pos, 32); + if (unlikely(!numbertab[i])) __PYX_ERR(0, 1, __pyx_L1_error) + c_constant = end_pos + 1; + } + } + #if CYTHON_IMMORTAL_CONSTANTS + { + PyObject **table = __pyx_mstate->__pyx_number_tab; + for (Py_ssize_t i=0; i<1; ++i) { + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + Py_SET_REFCNT(table[i], _Py_IMMORTAL_REFCNT_LOCAL); + #else + Py_SET_REFCNT(table[i], _Py_IMMORTAL_INITIAL_REFCNT); + #endif + } + } + #endif + return 0; + __pyx_L1_error:; + return -1; +} +/* #### Code section: init_codeobjects ### */ +typedef struct { + unsigned int argcount : 1; + unsigned int num_posonly_args : 1; + unsigned int num_kwonly_args : 1; + unsigned int nlocals : 1; + unsigned int flags : 10; + unsigned int first_line : 6; +} __Pyx_PyCode_New_function_description; +/* NewCodeObj.proto */ +static PyObject* __Pyx_PyCode_New( + const __Pyx_PyCode_New_function_description descr, + PyObject * const *varnames, + PyObject *filename, + PyObject *funcname, + PyObject *line_table, + PyObject *tuple_dedup_map +); + + +static int __Pyx_CreateCodeObjects(__pyx_mstatetype *__pyx_mstate) { + PyObject* tuple_dedup_map = PyDict_New(); + if (unlikely(!tuple_dedup_map)) return -1; + { + const __Pyx_PyCode_New_function_description descr = {1, 0, 0, 1, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 53}; + PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_data}; + __pyx_mstate_global->__pyx_codeobj_tab[0] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_clickhouse_driver__cityhash_city_2, __pyx_mstate->__pyx_n_u_CityHash128, __pyx_mstate->__pyx_kp_b_iso88591_aq_AQ_5_a_a_CvS_aq_a_Qa_q_Qa_6, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[0])) goto bad; + } + Py_DECREF(tuple_dedup_map); + return 0; + bad: + Py_DECREF(tuple_dedup_map); + return -1; +} +/* #### Code section: init_globals ### */ + +static int __Pyx_InitGlobals(void) { + /* PythonCompatibility.init */ + if (likely(__Pyx_init_co_variables() == 0)); else + + if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1, __pyx_L1_error) + + /* CommonTypesMetaclass.init */ + if (likely(__pyx_CommonTypesMetaclass_init(__pyx_m) == 0)); else + + if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1, __pyx_L1_error) + + /* CachedMethodType.init */ + #if CYTHON_COMPILING_IN_LIMITED_API + { + PyObject *typesModule=NULL; + typesModule = PyImport_ImportModule("types"); + if (typesModule) { + __pyx_mstate_global->__Pyx_CachedMethodType = PyObject_GetAttrString(typesModule, "MethodType"); + Py_DECREF(typesModule); + } + } // error handling follows + #endif + + if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1, __pyx_L1_error) + + /* CythonFunctionShared.init */ + if (likely(__pyx_CyFunction_init(__pyx_m) == 0)); else + + if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1, __pyx_L1_error) + + return 0; + __pyx_L1_error:; + return -1; +} +/* #### Code section: cleanup_globals ### */ +/* #### Code section: cleanup_module ### */ +/* #### Code section: main_method ### */ +/* #### Code section: utility_code_pragmas ### */ +#ifdef _MSC_VER +#pragma warning( push ) +/* Warning 4127: conditional expression is constant + * Cython uses constant conditional expressions to allow in inline functions to be optimized at + * compile-time, so this warning is not useful + */ +#pragma warning( disable : 4127 ) +#endif + + + +/* #### Code section: utility_code_def ### */ + +/* --- Runtime support code --- */ +/* Refnanny */ +#if CYTHON_REFNANNY +static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { + PyObject *m = NULL, *p = NULL; + void *r = NULL; + m = PyImport_ImportModule(modname); + if (!m) goto end; + p = PyObject_GetAttrString(m, "RefNannyAPI"); + if (!p) goto end; + r = PyLong_AsVoidPtr(p); +end: + Py_XDECREF(p); + Py_XDECREF(m); + return (__Pyx_RefNannyAPIStruct *)r; +} +#endif + +/* PyUnicode_Unicode */ +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_Unicode(PyObject *obj) { + if (unlikely(obj == Py_None)) + obj = __pyx_mstate_global->__pyx_kp_u_None; + return __Pyx_NewRef(obj); +} + +/* PyObjectFormatAndDecref */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_FormatSimpleAndDecref(PyObject* s, PyObject* f) { + if (unlikely(!s)) return NULL; + if (likely(PyUnicode_CheckExact(s))) return s; + return __Pyx_PyObject_FormatAndDecref(s, f); +} +static CYTHON_INLINE PyObject* __Pyx_PyObject_FormatAndDecref(PyObject* s, PyObject* f) { + PyObject *result; + if (unlikely(!s)) return NULL; + result = PyObject_Format(s, f); + Py_DECREF(s); + return result; +} + +/* JoinPyUnicode */ +static PyObject* __Pyx_PyUnicode_Join(PyObject** values, Py_ssize_t value_count, Py_ssize_t result_ulength, + Py_UCS4 max_char) { +#if CYTHON_USE_UNICODE_INTERNALS && CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + PyObject *result_uval; + int result_ukind, kind_shift; + Py_ssize_t i, char_pos; + void *result_udata; + if (max_char > 1114111) max_char = 1114111; + result_uval = PyUnicode_New(result_ulength, max_char); + if (unlikely(!result_uval)) return NULL; + result_ukind = (max_char <= 255) ? PyUnicode_1BYTE_KIND : (max_char <= 65535) ? PyUnicode_2BYTE_KIND : PyUnicode_4BYTE_KIND; + kind_shift = (result_ukind == PyUnicode_4BYTE_KIND) ? 2 : result_ukind - 1; + result_udata = PyUnicode_DATA(result_uval); + assert(kind_shift == 2 || kind_shift == 1 || kind_shift == 0); + if (unlikely((PY_SSIZE_T_MAX >> kind_shift) - result_ulength < 0)) + goto overflow; + char_pos = 0; + for (i=0; i < value_count; i++) { + int ukind; + Py_ssize_t ulength; + void *udata; + PyObject *uval = values[i]; + #if !CYTHON_COMPILING_IN_LIMITED_API + if (__Pyx_PyUnicode_READY(uval) == (-1)) + goto bad; + #endif + ulength = __Pyx_PyUnicode_GET_LENGTH(uval); + #if !CYTHON_ASSUME_SAFE_SIZE + if (unlikely(ulength < 0)) goto bad; + #endif + if (unlikely(!ulength)) + continue; + if (unlikely((PY_SSIZE_T_MAX >> kind_shift) - ulength < char_pos)) + goto overflow; + ukind = __Pyx_PyUnicode_KIND(uval); + udata = __Pyx_PyUnicode_DATA(uval); + if (ukind == result_ukind) { + memcpy((char *)result_udata + (char_pos << kind_shift), udata, (size_t) (ulength << kind_shift)); + } else { + #if PY_VERSION_HEX >= 0x030d0000 + if (unlikely(PyUnicode_CopyCharacters(result_uval, char_pos, uval, 0, ulength) < 0)) goto bad; + #elif CYTHON_COMPILING_IN_CPYTHON || defined(_PyUnicode_FastCopyCharacters) + _PyUnicode_FastCopyCharacters(result_uval, char_pos, uval, 0, ulength); + #else + Py_ssize_t j; + for (j=0; j < ulength; j++) { + Py_UCS4 uchar = __Pyx_PyUnicode_READ(ukind, udata, j); + __Pyx_PyUnicode_WRITE(result_ukind, result_udata, char_pos+j, uchar); + } + #endif + } + char_pos += ulength; + } + return result_uval; +overflow: + PyErr_SetString(PyExc_OverflowError, "join() result is too long for a Python string"); +bad: + Py_DECREF(result_uval); + return NULL; +#else + Py_ssize_t i; + PyObject *result = NULL; + PyObject *value_tuple = PyTuple_New(value_count); + if (unlikely(!value_tuple)) return NULL; + CYTHON_UNUSED_VAR(max_char); + CYTHON_UNUSED_VAR(result_ulength); + for (i=0; i__pyx_empty_unicode, value_tuple); +bad: + Py_DECREF(value_tuple); + return result; +#endif +} + +/* PyObjectCall */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { + PyObject *result; + ternaryfunc call = Py_TYPE(func)->tp_call; + if (unlikely(!call)) + return PyObject_Call(func, arg, kw); + if (unlikely(Py_EnterRecursiveCall(" while calling a Python object"))) + return NULL; + result = (*call)(func, arg, kw); + Py_LeaveRecursiveCall(); + if (unlikely(!result) && unlikely(!PyErr_Occurred())) { + PyErr_SetString( + PyExc_SystemError, + "NULL result without error in PyObject_Call"); + } + return result; +} +#endif + +/* PyObjectCallMethO */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg) { + PyObject *self, *result; + PyCFunction cfunc; + cfunc = __Pyx_CyOrPyCFunction_GET_FUNCTION(func); + self = __Pyx_CyOrPyCFunction_GET_SELF(func); + if (unlikely(Py_EnterRecursiveCall(" while calling a Python object"))) + return NULL; + result = cfunc(self, arg); + Py_LeaveRecursiveCall(); + if (unlikely(!result) && unlikely(!PyErr_Occurred())) { + PyErr_SetString( + PyExc_SystemError, + "NULL result without error in PyObject_Call"); + } + return result; +} +#endif + +/* PyObjectFastCall */ +#if PY_VERSION_HEX < 0x03090000 || CYTHON_COMPILING_IN_LIMITED_API +static PyObject* __Pyx_PyObject_FastCall_fallback(PyObject *func, PyObject * const*args, size_t nargs, PyObject *kwargs) { + PyObject *argstuple; + PyObject *result = 0; + size_t i; + argstuple = PyTuple_New((Py_ssize_t)nargs); + if (unlikely(!argstuple)) return NULL; + for (i = 0; i < nargs; i++) { + Py_INCREF(args[i]); + if (__Pyx_PyTuple_SET_ITEM(argstuple, (Py_ssize_t)i, args[i]) != (0)) goto bad; + } + result = __Pyx_PyObject_Call(func, argstuple, kwargs); + bad: + Py_DECREF(argstuple); + return result; +} +#endif +#if CYTHON_VECTORCALL && !CYTHON_COMPILING_IN_LIMITED_API + #if PY_VERSION_HEX < 0x03090000 + #define __Pyx_PyVectorcall_Function(callable) _PyVectorcall_Function(callable) + #elif CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE vectorcallfunc __Pyx_PyVectorcall_Function(PyObject *callable) { + PyTypeObject *tp = Py_TYPE(callable); + #if defined(__Pyx_CyFunction_USED) + if (__Pyx_CyFunction_CheckExact(callable)) { + return __Pyx_CyFunction_func_vectorcall(callable); + } + #endif + if (!PyType_HasFeature(tp, Py_TPFLAGS_HAVE_VECTORCALL)) { + return NULL; + } + assert(PyCallable_Check(callable)); + Py_ssize_t offset = tp->tp_vectorcall_offset; + assert(offset > 0); + vectorcallfunc ptr; + memcpy(&ptr, (char *) callable + offset, sizeof(ptr)); + return ptr; +} + #else + #define __Pyx_PyVectorcall_Function(callable) PyVectorcall_Function(callable) + #endif +#endif +static CYTHON_INLINE PyObject* __Pyx_PyObject_FastCallDict(PyObject *func, PyObject *const *args, size_t _nargs, PyObject *kwargs) { + Py_ssize_t nargs = __Pyx_PyVectorcall_NARGS(_nargs); +#if CYTHON_COMPILING_IN_CPYTHON + if (nargs == 0 && kwargs == NULL) { + if (__Pyx_CyOrPyCFunction_Check(func) && likely( __Pyx_CyOrPyCFunction_GET_FLAGS(func) & METH_NOARGS)) + return __Pyx_PyObject_CallMethO(func, NULL); + } + else if (nargs == 1 && kwargs == NULL) { + if (__Pyx_CyOrPyCFunction_Check(func) && likely( __Pyx_CyOrPyCFunction_GET_FLAGS(func) & METH_O)) + return __Pyx_PyObject_CallMethO(func, args[0]); + } +#endif + if (kwargs == NULL) { + #if CYTHON_VECTORCALL + #if CYTHON_COMPILING_IN_LIMITED_API + return PyObject_Vectorcall(func, args, _nargs, NULL); + #else + vectorcallfunc f = __Pyx_PyVectorcall_Function(func); + if (f) { + return f(func, args, _nargs, NULL); + } + #endif + #endif + } + if (nargs == 0) { + return __Pyx_PyObject_Call(func, __pyx_mstate_global->__pyx_empty_tuple, kwargs); + } + #if PY_VERSION_HEX >= 0x03090000 && !CYTHON_COMPILING_IN_LIMITED_API + return PyObject_VectorcallDict(func, args, (size_t)nargs, kwargs); + #else + return __Pyx_PyObject_FastCall_fallback(func, args, (size_t)nargs, kwargs); + #endif +} + +/* PyErrFetchRestore */ +#if CYTHON_FAST_THREAD_STATE +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { +#if PY_VERSION_HEX >= 0x030C00A6 + PyObject *tmp_value; + assert(type == NULL || (value != NULL && type == (PyObject*) Py_TYPE(value))); + if (value) { + #if CYTHON_COMPILING_IN_CPYTHON + if (unlikely(((PyBaseExceptionObject*) value)->traceback != tb)) + #endif + PyException_SetTraceback(value, tb); + } + tmp_value = tstate->current_exception; + tstate->current_exception = value; + Py_XDECREF(tmp_value); + Py_XDECREF(type); + Py_XDECREF(tb); +#else + PyObject *tmp_type, *tmp_value, *tmp_tb; + tmp_type = tstate->curexc_type; + tmp_value = tstate->curexc_value; + tmp_tb = tstate->curexc_traceback; + tstate->curexc_type = type; + tstate->curexc_value = value; + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +#endif +} +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { +#if PY_VERSION_HEX >= 0x030C00A6 + PyObject* exc_value; + exc_value = tstate->current_exception; + tstate->current_exception = 0; + *value = exc_value; + *type = NULL; + *tb = NULL; + if (exc_value) { + *type = (PyObject*) Py_TYPE(exc_value); + Py_INCREF(*type); + #if CYTHON_COMPILING_IN_CPYTHON + *tb = ((PyBaseExceptionObject*) exc_value)->traceback; + Py_XINCREF(*tb); + #else + *tb = PyException_GetTraceback(exc_value); + #endif + } +#else + *type = tstate->curexc_type; + *value = tstate->curexc_value; + *tb = tstate->curexc_traceback; + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; +#endif +} +#endif + +/* RaiseException */ +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { + PyObject* owned_instance = NULL; + if (tb == Py_None) { + tb = 0; + } else if (tb && !PyTraceBack_Check(tb)) { + PyErr_SetString(PyExc_TypeError, + "raise: arg 3 must be a traceback or None"); + goto bad; + } + if (value == Py_None) + value = 0; + if (PyExceptionInstance_Check(type)) { + if (value) { + PyErr_SetString(PyExc_TypeError, + "instance exception may not have a separate value"); + goto bad; + } + value = type; + type = (PyObject*) Py_TYPE(value); + } else if (PyExceptionClass_Check(type)) { + PyObject *instance_class = NULL; + if (value && PyExceptionInstance_Check(value)) { + instance_class = (PyObject*) Py_TYPE(value); + if (instance_class != type) { + int is_subclass = PyObject_IsSubclass(instance_class, type); + if (!is_subclass) { + instance_class = NULL; + } else if (unlikely(is_subclass == -1)) { + goto bad; + } else { + type = instance_class; + } + } + } + if (!instance_class) { + PyObject *args; + if (!value) + args = PyTuple_New(0); + else if (PyTuple_Check(value)) { + Py_INCREF(value); + args = value; + } else + args = PyTuple_Pack(1, value); + if (!args) + goto bad; + owned_instance = PyObject_Call(type, args, NULL); + Py_DECREF(args); + if (!owned_instance) + goto bad; + value = owned_instance; + if (!PyExceptionInstance_Check(value)) { + PyErr_Format(PyExc_TypeError, + "calling %R should have returned an instance of " + "BaseException, not %R", + type, Py_TYPE(value)); + goto bad; + } + } + } else { + PyErr_SetString(PyExc_TypeError, + "raise: exception class must be a subclass of BaseException"); + goto bad; + } + if (cause) { + PyObject *fixed_cause; + if (cause == Py_None) { + fixed_cause = NULL; + } else if (PyExceptionClass_Check(cause)) { + fixed_cause = PyObject_CallObject(cause, NULL); + if (fixed_cause == NULL) + goto bad; + } else if (PyExceptionInstance_Check(cause)) { + fixed_cause = cause; + Py_INCREF(fixed_cause); + } else { + PyErr_SetString(PyExc_TypeError, + "exception causes must derive from " + "BaseException"); + goto bad; + } + PyException_SetCause(value, fixed_cause); + } + PyErr_SetObject(type, value); + if (tb) { +#if PY_VERSION_HEX >= 0x030C00A6 + PyException_SetTraceback(value, tb); +#elif CYTHON_FAST_THREAD_STATE + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject* tmp_tb = tstate->curexc_traceback; + if (tb != tmp_tb) { + Py_INCREF(tb); + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_tb); + } +#else + PyObject *tmp_type, *tmp_value, *tmp_tb; + PyErr_Fetch(&tmp_type, &tmp_value, &tmp_tb); + Py_INCREF(tb); + PyErr_Restore(tmp_type, tmp_value, tb); + Py_XDECREF(tmp_tb); +#endif + } +bad: + Py_XDECREF(owned_instance); + return; +} + +/* TupleAndListFromArray */ +#if !CYTHON_COMPILING_IN_CPYTHON && CYTHON_METH_FASTCALL +static CYTHON_INLINE PyObject * +__Pyx_PyTuple_FromArray(PyObject *const *src, Py_ssize_t n) +{ + PyObject *res; + Py_ssize_t i; + if (n <= 0) { + return __Pyx_NewRef(__pyx_mstate_global->__pyx_empty_tuple); + } + res = PyTuple_New(n); + if (unlikely(res == NULL)) return NULL; + for (i = 0; i < n; i++) { + if (unlikely(__Pyx_PyTuple_SET_ITEM(res, i, src[i]) < (0))) { + Py_DECREF(res); + return NULL; + } + Py_INCREF(src[i]); + } + return res; +} +#elif CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE void __Pyx_copy_object_array(PyObject *const *CYTHON_RESTRICT src, PyObject** CYTHON_RESTRICT dest, Py_ssize_t length) { + PyObject *v; + Py_ssize_t i; + for (i = 0; i < length; i++) { + v = dest[i] = src[i]; + Py_INCREF(v); + } +} +static CYTHON_INLINE PyObject * +__Pyx_PyTuple_FromArray(PyObject *const *src, Py_ssize_t n) +{ + PyObject *res; + if (n <= 0) { + return __Pyx_NewRef(__pyx_mstate_global->__pyx_empty_tuple); + } + res = PyTuple_New(n); + if (unlikely(res == NULL)) return NULL; + __Pyx_copy_object_array(src, ((PyTupleObject*)res)->ob_item, n); + return res; +} +static CYTHON_INLINE PyObject * +__Pyx_PyList_FromArray(PyObject *const *src, Py_ssize_t n) +{ + PyObject *res; + if (n <= 0) { + return PyList_New(0); + } + res = PyList_New(n); + if (unlikely(res == NULL)) return NULL; + __Pyx_copy_object_array(src, ((PyListObject*)res)->ob_item, n); + return res; +} +#endif + +/* BytesEquals */ +static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int equals) { +#if CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_LIMITED_API || CYTHON_COMPILING_IN_GRAAL ||\ + !(CYTHON_ASSUME_SAFE_SIZE && CYTHON_ASSUME_SAFE_MACROS) + return PyObject_RichCompareBool(s1, s2, equals); +#else + if (s1 == s2) { + return (equals == Py_EQ); + } else if (PyBytes_CheckExact(s1) & PyBytes_CheckExact(s2)) { + const char *ps1, *ps2; + Py_ssize_t length = PyBytes_GET_SIZE(s1); + if (length != PyBytes_GET_SIZE(s2)) + return (equals == Py_NE); + ps1 = PyBytes_AS_STRING(s1); + ps2 = PyBytes_AS_STRING(s2); + if (ps1[0] != ps2[0]) { + return (equals == Py_NE); + } else if (length == 1) { + return (equals == Py_EQ); + } else { + int result; +#if CYTHON_USE_UNICODE_INTERNALS && (PY_VERSION_HEX < 0x030B0000) + Py_hash_t hash1, hash2; + hash1 = ((PyBytesObject*)s1)->ob_shash; + hash2 = ((PyBytesObject*)s2)->ob_shash; + if (hash1 != hash2 && hash1 != -1 && hash2 != -1) { + return (equals == Py_NE); + } +#endif + result = memcmp(ps1, ps2, (size_t)length); + return (equals == Py_EQ) ? (result == 0) : (result != 0); + } + } else if ((s1 == Py_None) & PyBytes_CheckExact(s2)) { + return (equals == Py_NE); + } else if ((s2 == Py_None) & PyBytes_CheckExact(s1)) { + return (equals == Py_NE); + } else { + int result; + PyObject* py_result = PyObject_RichCompare(s1, s2, equals); + if (!py_result) + return -1; + result = __Pyx_PyObject_IsTrue(py_result); + Py_DECREF(py_result); + return result; + } +#endif +} + +/* UnicodeEquals */ +static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int equals) { +#if CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_LIMITED_API || CYTHON_COMPILING_IN_GRAAL + return PyObject_RichCompareBool(s1, s2, equals); +#else + int s1_is_unicode, s2_is_unicode; + if (s1 == s2) { + goto return_eq; + } + s1_is_unicode = PyUnicode_CheckExact(s1); + s2_is_unicode = PyUnicode_CheckExact(s2); + if (s1_is_unicode & s2_is_unicode) { + Py_ssize_t length, length2; + int kind; + void *data1, *data2; + #if !CYTHON_COMPILING_IN_LIMITED_API + if (unlikely(__Pyx_PyUnicode_READY(s1) < 0) || unlikely(__Pyx_PyUnicode_READY(s2) < 0)) + return -1; + #endif + length = __Pyx_PyUnicode_GET_LENGTH(s1); + #if !CYTHON_ASSUME_SAFE_SIZE + if (unlikely(length < 0)) return -1; + #endif + length2 = __Pyx_PyUnicode_GET_LENGTH(s2); + #if !CYTHON_ASSUME_SAFE_SIZE + if (unlikely(length2 < 0)) return -1; + #endif + if (length != length2) { + goto return_ne; + } +#if CYTHON_USE_UNICODE_INTERNALS + { + Py_hash_t hash1, hash2; + hash1 = ((PyASCIIObject*)s1)->hash; + hash2 = ((PyASCIIObject*)s2)->hash; + if (hash1 != hash2 && hash1 != -1 && hash2 != -1) { + goto return_ne; + } + } +#endif + kind = __Pyx_PyUnicode_KIND(s1); + if (kind != __Pyx_PyUnicode_KIND(s2)) { + goto return_ne; + } + data1 = __Pyx_PyUnicode_DATA(s1); + data2 = __Pyx_PyUnicode_DATA(s2); + if (__Pyx_PyUnicode_READ(kind, data1, 0) != __Pyx_PyUnicode_READ(kind, data2, 0)) { + goto return_ne; + } else if (length == 1) { + goto return_eq; + } else { + int result = memcmp(data1, data2, (size_t)(length * kind)); + return (equals == Py_EQ) ? (result == 0) : (result != 0); + } + } else if ((s1 == Py_None) & s2_is_unicode) { + goto return_ne; + } else if ((s2 == Py_None) & s1_is_unicode) { + goto return_ne; + } else { + int result; + PyObject* py_result = PyObject_RichCompare(s1, s2, equals); + if (!py_result) + return -1; + result = __Pyx_PyObject_IsTrue(py_result); + Py_DECREF(py_result); + return result; + } +return_eq: + return (equals == Py_EQ); +return_ne: + return (equals == Py_NE); +#endif +} + +/* fastcall */ +#if CYTHON_METH_FASTCALL +static CYTHON_INLINE PyObject * __Pyx_GetKwValue_FASTCALL(PyObject *kwnames, PyObject *const *kwvalues, PyObject *s) +{ + Py_ssize_t i, n = __Pyx_PyTuple_GET_SIZE(kwnames); + #if !CYTHON_ASSUME_SAFE_SIZE + if (unlikely(n == -1)) return NULL; + #endif + for (i = 0; i < n; i++) + { + PyObject *namei = __Pyx_PyTuple_GET_ITEM(kwnames, i); + #if !CYTHON_ASSUME_SAFE_MACROS + if (unlikely(!namei)) return NULL; + #endif + if (s == namei) return kwvalues[i]; + } + for (i = 0; i < n; i++) + { + PyObject *namei = __Pyx_PyTuple_GET_ITEM(kwnames, i); + #if !CYTHON_ASSUME_SAFE_MACROS + if (unlikely(!namei)) return NULL; + #endif + int eq = __Pyx_PyUnicode_Equals(s, namei, Py_EQ); + if (unlikely(eq != 0)) { + if (unlikely(eq < 0)) return NULL; + return kwvalues[i]; + } + } + return NULL; +} +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030d0000 || CYTHON_COMPILING_IN_LIMITED_API +CYTHON_UNUSED static PyObject *__Pyx_KwargsAsDict_FASTCALL(PyObject *kwnames, PyObject *const *kwvalues) { + Py_ssize_t i, nkwargs; + PyObject *dict; +#if !CYTHON_ASSUME_SAFE_SIZE + nkwargs = PyTuple_Size(kwnames); + if (unlikely(nkwargs < 0)) return NULL; +#else + nkwargs = PyTuple_GET_SIZE(kwnames); +#endif + dict = PyDict_New(); + if (unlikely(!dict)) + return NULL; + for (i=0; itp_getattro)) + return tp->tp_getattro(obj, attr_name); + return PyObject_GetAttr(obj, attr_name); +} +#endif + +/* UnpackUnboundCMethod */ +#if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030C0000 +static PyObject *__Pyx_SelflessCall(PyObject *method, PyObject *args, PyObject *kwargs) { + PyObject *result; + PyObject *selfless_args = PyTuple_GetSlice(args, 1, PyTuple_Size(args)); + if (unlikely(!selfless_args)) return NULL; + result = PyObject_Call(method, selfless_args, kwargs); + Py_DECREF(selfless_args); + return result; +} +#elif CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x03090000 +static PyObject *__Pyx_SelflessCall(PyObject *method, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) { + return _PyObject_Vectorcall + (method, args ? args+1 : NULL, nargs ? nargs-1 : 0, kwnames); +} +#else +static PyObject *__Pyx_SelflessCall(PyObject *method, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { + return +#if PY_VERSION_HEX < 0x03090000 + _PyObject_Vectorcall +#else + PyObject_Vectorcall +#endif + (method, args ? args+1 : NULL, nargs ? (size_t) nargs-1 : 0, kwnames); +} +#endif +static PyMethodDef __Pyx_UnboundCMethod_Def = { + "CythonUnboundCMethod", + __PYX_REINTERPRET_FUNCION(PyCFunction, __Pyx_SelflessCall), +#if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030C0000 + METH_VARARGS | METH_KEYWORDS, +#else + METH_FASTCALL | METH_KEYWORDS, +#endif + NULL +}; +static int __Pyx_TryUnpackUnboundCMethod(__Pyx_CachedCFunction* target) { + PyObject *method, *result=NULL; + method = __Pyx_PyObject_GetAttrStr(target->type, *target->method_name); + if (unlikely(!method)) + return -1; + result = method; +#if CYTHON_COMPILING_IN_CPYTHON + if (likely(__Pyx_TypeCheck(method, &PyMethodDescr_Type))) + { + PyMethodDescrObject *descr = (PyMethodDescrObject*) method; + target->func = descr->d_method->ml_meth; + target->flag = descr->d_method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_STACKLESS); + } else +#endif +#if CYTHON_COMPILING_IN_PYPY +#else + if (PyCFunction_Check(method)) +#endif + { + PyObject *self; + int self_found; +#if CYTHON_COMPILING_IN_LIMITED_API || CYTHON_COMPILING_IN_PYPY + self = PyObject_GetAttrString(method, "__self__"); + if (!self) { + PyErr_Clear(); + } +#else + self = PyCFunction_GET_SELF(method); +#endif + self_found = (self && self != Py_None); +#if CYTHON_COMPILING_IN_LIMITED_API || CYTHON_COMPILING_IN_PYPY + Py_XDECREF(self); +#endif + if (self_found) { + PyObject *unbound_method = PyCFunction_New(&__Pyx_UnboundCMethod_Def, method); + if (unlikely(!unbound_method)) return -1; + Py_DECREF(method); + result = unbound_method; + } + } +#if !CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + if (unlikely(target->method)) { + Py_DECREF(result); + } else +#endif + target->method = result; + return 0; +} + +/* CallUnboundCMethod0 */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_CallUnboundCMethod0(__Pyx_CachedCFunction* cfunc, PyObject* self) { + int was_initialized = __Pyx_CachedCFunction_GetAndSetInitializing(cfunc); + if (likely(was_initialized == 2 && cfunc->func)) { + if (likely(cfunc->flag == METH_NOARGS)) + return __Pyx_CallCFunction(cfunc, self, NULL); + if (likely(cfunc->flag == METH_FASTCALL)) + return __Pyx_CallCFunctionFast(cfunc, self, NULL, 0); + if (cfunc->flag == (METH_FASTCALL | METH_KEYWORDS)) + return __Pyx_CallCFunctionFastWithKeywords(cfunc, self, NULL, 0, NULL); + if (likely(cfunc->flag == (METH_VARARGS | METH_KEYWORDS))) + return __Pyx_CallCFunctionWithKeywords(cfunc, self, __pyx_mstate_global->__pyx_empty_tuple, NULL); + if (cfunc->flag == METH_VARARGS) + return __Pyx_CallCFunction(cfunc, self, __pyx_mstate_global->__pyx_empty_tuple); + return __Pyx__CallUnboundCMethod0(cfunc, self); + } +#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + else if (unlikely(was_initialized == 1)) { + __Pyx_CachedCFunction tmp_cfunc = { +#ifndef __cplusplus + 0 +#endif + }; + tmp_cfunc.type = cfunc->type; + tmp_cfunc.method_name = cfunc->method_name; + return __Pyx__CallUnboundCMethod0(&tmp_cfunc, self); + } +#endif + PyObject *result = __Pyx__CallUnboundCMethod0(cfunc, self); + __Pyx_CachedCFunction_SetFinishedInitializing(cfunc); + return result; +} +#endif +static PyObject* __Pyx__CallUnboundCMethod0(__Pyx_CachedCFunction* cfunc, PyObject* self) { + PyObject *result; + if (unlikely(!cfunc->method) && unlikely(__Pyx_TryUnpackUnboundCMethod(cfunc) < 0)) return NULL; + result = __Pyx_PyObject_CallOneArg(cfunc->method, self); + return result; +} + +/* py_dict_items */ +static CYTHON_INLINE PyObject* __Pyx_PyDict_Items(PyObject* d) { + return __Pyx_CallUnboundCMethod0(&__pyx_mstate_global->__pyx_umethod_PyDict_Type_items, d); +} + +/* py_dict_values */ +static CYTHON_INLINE PyObject* __Pyx_PyDict_Values(PyObject* d) { + return __Pyx_CallUnboundCMethod0(&__pyx_mstate_global->__pyx_umethod_PyDict_Type_values, d); +} + +/* OwnedDictNext */ +#if CYTHON_AVOID_BORROWED_REFS +static int __Pyx_PyDict_NextRef(PyObject *p, PyObject **ppos, PyObject **pkey, PyObject **pvalue) { + PyObject *next = NULL; + if (!*ppos) { + if (pvalue) { + PyObject *dictview = pkey ? __Pyx_PyDict_Items(p) : __Pyx_PyDict_Values(p); + if (unlikely(!dictview)) goto bad; + *ppos = PyObject_GetIter(dictview); + Py_DECREF(dictview); + } else { + *ppos = PyObject_GetIter(p); + } + if (unlikely(!*ppos)) goto bad; + } + next = PyIter_Next(*ppos); + if (!next) { + if (PyErr_Occurred()) goto bad; + return 0; + } + if (pkey && pvalue) { + *pkey = __Pyx_PySequence_ITEM(next, 0); + if (unlikely(*pkey)) goto bad; + *pvalue = __Pyx_PySequence_ITEM(next, 1); + if (unlikely(*pvalue)) goto bad; + Py_DECREF(next); + } else if (pkey) { + *pkey = next; + } else { + assert(pvalue); + *pvalue = next; + } + return 1; + bad: + Py_XDECREF(next); +#if !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x030d0000 + PyErr_FormatUnraisable("Exception ignored in __Pyx_PyDict_NextRef"); +#else + PyErr_WriteUnraisable(__pyx_mstate_global->__pyx_n_u_Pyx_PyDict_NextRef); +#endif + if (pkey) *pkey = NULL; + if (pvalue) *pvalue = NULL; + return 0; +} +#else // !CYTHON_AVOID_BORROWED_REFS +static int __Pyx_PyDict_NextRef(PyObject *p, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue) { + int result = PyDict_Next(p, ppos, pkey, pvalue); + if (likely(result == 1)) { + if (pkey) Py_INCREF(*pkey); + if (pvalue) Py_INCREF(*pvalue); + } + return result; +} +#endif + +/* RaiseDoubleKeywords */ +static void __Pyx_RaiseDoubleKeywordsError( + const char* func_name, + PyObject* kw_name) +{ + PyErr_Format(PyExc_TypeError, + "%s() got multiple values for keyword argument '%U'", func_name, kw_name); +} + +/* CallUnboundCMethod2 */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject *__Pyx_CallUnboundCMethod2(__Pyx_CachedCFunction *cfunc, PyObject *self, PyObject *arg1, PyObject *arg2) { + int was_initialized = __Pyx_CachedCFunction_GetAndSetInitializing(cfunc); + if (likely(was_initialized == 2 && cfunc->func)) { + PyObject *args[2] = {arg1, arg2}; + if (cfunc->flag == METH_FASTCALL) { + return __Pyx_CallCFunctionFast(cfunc, self, args, 2); + } + if (cfunc->flag == (METH_FASTCALL | METH_KEYWORDS)) + return __Pyx_CallCFunctionFastWithKeywords(cfunc, self, args, 2, NULL); + } +#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + else if (unlikely(was_initialized == 1)) { + __Pyx_CachedCFunction tmp_cfunc = { +#ifndef __cplusplus + 0 +#endif + }; + tmp_cfunc.type = cfunc->type; + tmp_cfunc.method_name = cfunc->method_name; + return __Pyx__CallUnboundCMethod2(&tmp_cfunc, self, arg1, arg2); + } +#endif + PyObject *result = __Pyx__CallUnboundCMethod2(cfunc, self, arg1, arg2); + __Pyx_CachedCFunction_SetFinishedInitializing(cfunc); + return result; +} +#endif +static PyObject* __Pyx__CallUnboundCMethod2(__Pyx_CachedCFunction* cfunc, PyObject* self, PyObject* arg1, PyObject* arg2){ + if (unlikely(!cfunc->func && !cfunc->method) && unlikely(__Pyx_TryUnpackUnboundCMethod(cfunc) < 0)) return NULL; +#if CYTHON_COMPILING_IN_CPYTHON + if (cfunc->func && (cfunc->flag & METH_VARARGS)) { + PyObject *result = NULL; + PyObject *args = PyTuple_New(2); + if (unlikely(!args)) return NULL; + Py_INCREF(arg1); + PyTuple_SET_ITEM(args, 0, arg1); + Py_INCREF(arg2); + PyTuple_SET_ITEM(args, 1, arg2); + if (cfunc->flag & METH_KEYWORDS) + result = __Pyx_CallCFunctionWithKeywords(cfunc, self, args, NULL); + else + result = __Pyx_CallCFunction(cfunc, self, args); + Py_DECREF(args); + return result; + } +#endif + { + PyObject *args[4] = {NULL, self, arg1, arg2}; + return __Pyx_PyObject_FastCall(cfunc->method, args+1, 3 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET); + } +} + +/* ParseKeywordsImpl */ +static int __Pyx_ValidateDuplicatePosArgs( + PyObject *kwds, + PyObject ** const argnames[], + PyObject ** const *first_kw_arg, + const char* function_name) +{ + PyObject ** const *name = argnames; + while (name != first_kw_arg) { + PyObject *key = **name; + int found = PyDict_Contains(kwds, key); + if (unlikely(found)) { + if (found == 1) __Pyx_RaiseDoubleKeywordsError(function_name, key); + goto bad; + } + name++; + } + return 0; +bad: + return -1; +} +#if CYTHON_USE_UNICODE_INTERNALS +static CYTHON_INLINE int __Pyx_UnicodeKeywordsEqual(PyObject *s1, PyObject *s2) { + int kind; + Py_ssize_t len = PyUnicode_GET_LENGTH(s1); + if (len != PyUnicode_GET_LENGTH(s2)) return 0; + kind = PyUnicode_KIND(s1); + if (kind != PyUnicode_KIND(s2)) return 0; + const void *data1 = PyUnicode_DATA(s1); + const void *data2 = PyUnicode_DATA(s2); + return (memcmp(data1, data2, (size_t) len * (size_t) kind) == 0); +} +#endif +static int __Pyx_MatchKeywordArg_str( + PyObject *key, + PyObject ** const argnames[], + PyObject ** const *first_kw_arg, + size_t *index_found, + const char *function_name) +{ + PyObject ** const *name; + #if CYTHON_USE_UNICODE_INTERNALS + Py_hash_t key_hash = ((PyASCIIObject*)key)->hash; + if (unlikely(key_hash == -1)) { + key_hash = PyObject_Hash(key); + if (unlikely(key_hash == -1)) + goto bad; + } + #endif + name = first_kw_arg; + while (*name) { + PyObject *name_str = **name; + #if CYTHON_USE_UNICODE_INTERNALS + if (key_hash == ((PyASCIIObject*)name_str)->hash && __Pyx_UnicodeKeywordsEqual(name_str, key)) { + *index_found = (size_t) (name - argnames); + return 1; + } + #else + #if CYTHON_ASSUME_SAFE_SIZE + if (PyUnicode_GET_LENGTH(name_str) == PyUnicode_GET_LENGTH(key)) + #endif + { + int cmp = PyUnicode_Compare(name_str, key); + if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; + if (cmp == 0) { + *index_found = (size_t) (name - argnames); + return 1; + } + } + #endif + name++; + } + name = argnames; + while (name != first_kw_arg) { + PyObject *name_str = **name; + #if CYTHON_USE_UNICODE_INTERNALS + if (unlikely(key_hash == ((PyASCIIObject*)name_str)->hash)) { + if (__Pyx_UnicodeKeywordsEqual(name_str, key)) + goto arg_passed_twice; + } + #else + #if CYTHON_ASSUME_SAFE_SIZE + if (PyUnicode_GET_LENGTH(name_str) == PyUnicode_GET_LENGTH(key)) + #endif + { + if (unlikely(name_str == key)) goto arg_passed_twice; + int cmp = PyUnicode_Compare(name_str, key); + if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; + if (cmp == 0) goto arg_passed_twice; + } + #endif + name++; + } + return 0; +arg_passed_twice: + __Pyx_RaiseDoubleKeywordsError(function_name, key); + goto bad; +bad: + return -1; +} +static int __Pyx_MatchKeywordArg_nostr( + PyObject *key, + PyObject ** const argnames[], + PyObject ** const *first_kw_arg, + size_t *index_found, + const char *function_name) +{ + PyObject ** const *name; + if (unlikely(!PyUnicode_Check(key))) goto invalid_keyword_type; + name = first_kw_arg; + while (*name) { + int cmp = PyObject_RichCompareBool(**name, key, Py_EQ); + if (cmp == 1) { + *index_found = (size_t) (name - argnames); + return 1; + } + if (unlikely(cmp == -1)) goto bad; + name++; + } + name = argnames; + while (name != first_kw_arg) { + int cmp = PyObject_RichCompareBool(**name, key, Py_EQ); + if (unlikely(cmp != 0)) { + if (cmp == 1) goto arg_passed_twice; + else goto bad; + } + name++; + } + return 0; +arg_passed_twice: + __Pyx_RaiseDoubleKeywordsError(function_name, key); + goto bad; +invalid_keyword_type: + PyErr_Format(PyExc_TypeError, + "%.200s() keywords must be strings", function_name); + goto bad; +bad: + return -1; +} +static CYTHON_INLINE int __Pyx_MatchKeywordArg( + PyObject *key, + PyObject ** const argnames[], + PyObject ** const *first_kw_arg, + size_t *index_found, + const char *function_name) +{ + return likely(PyUnicode_CheckExact(key)) ? + __Pyx_MatchKeywordArg_str(key, argnames, first_kw_arg, index_found, function_name) : + __Pyx_MatchKeywordArg_nostr(key, argnames, first_kw_arg, index_found, function_name); +} +static void __Pyx_RejectUnknownKeyword( + PyObject *kwds, + PyObject ** const argnames[], + PyObject ** const *first_kw_arg, + const char *function_name) +{ + #if CYTHON_AVOID_BORROWED_REFS + PyObject *pos = NULL; + #else + Py_ssize_t pos = 0; + #endif + PyObject *key = NULL; + __Pyx_BEGIN_CRITICAL_SECTION(kwds); + while ( + #if CYTHON_AVOID_BORROWED_REFS + __Pyx_PyDict_NextRef(kwds, &pos, &key, NULL) + #else + PyDict_Next(kwds, &pos, &key, NULL) + #endif + ) { + PyObject** const *name = first_kw_arg; + while (*name && (**name != key)) name++; + if (!*name) { + size_t index_found = 0; + int cmp = __Pyx_MatchKeywordArg(key, argnames, first_kw_arg, &index_found, function_name); + if (cmp != 1) { + if (cmp == 0) { + PyErr_Format(PyExc_TypeError, + "%s() got an unexpected keyword argument '%U'", + function_name, key); + } + #if CYTHON_AVOID_BORROWED_REFS + Py_DECREF(key); + #endif + break; + } + } + #if CYTHON_AVOID_BORROWED_REFS + Py_DECREF(key); + #endif + } + __Pyx_END_CRITICAL_SECTION(); + #if CYTHON_AVOID_BORROWED_REFS + Py_XDECREF(pos); + #endif + assert(PyErr_Occurred()); +} +static int __Pyx_ParseKeywordDict( + PyObject *kwds, + PyObject ** const argnames[], + PyObject *values[], + Py_ssize_t num_pos_args, + Py_ssize_t num_kwargs, + const char* function_name, + int ignore_unknown_kwargs) +{ + PyObject** const *name; + PyObject** const *first_kw_arg = argnames + num_pos_args; + Py_ssize_t extracted = 0; +#if !CYTHON_COMPILING_IN_PYPY || defined(PyArg_ValidateKeywordArguments) + if (unlikely(!PyArg_ValidateKeywordArguments(kwds))) return -1; +#endif + name = first_kw_arg; + while (*name && num_kwargs > extracted) { + PyObject * key = **name; + PyObject *value; + int found = 0; + #if __PYX_LIMITED_VERSION_HEX >= 0x030d0000 + found = PyDict_GetItemRef(kwds, key, &value); + #else + value = PyDict_GetItemWithError(kwds, key); + if (value) { + Py_INCREF(value); + found = 1; + } else { + if (unlikely(PyErr_Occurred())) goto bad; + } + #endif + if (found) { + if (unlikely(found < 0)) goto bad; + values[name-argnames] = value; + extracted++; + } + name++; + } + if (num_kwargs > extracted) { + if (ignore_unknown_kwargs) { + if (unlikely(__Pyx_ValidateDuplicatePosArgs(kwds, argnames, first_kw_arg, function_name) == -1)) + goto bad; + } else { + __Pyx_RejectUnknownKeyword(kwds, argnames, first_kw_arg, function_name); + goto bad; + } + } + return 0; +bad: + return -1; +} +static int __Pyx_ParseKeywordDictToDict( + PyObject *kwds, + PyObject ** const argnames[], + PyObject *kwds2, + PyObject *values[], + Py_ssize_t num_pos_args, + const char* function_name) +{ + PyObject** const *name; + PyObject** const *first_kw_arg = argnames + num_pos_args; + Py_ssize_t len; +#if !CYTHON_COMPILING_IN_PYPY || defined(PyArg_ValidateKeywordArguments) + if (unlikely(!PyArg_ValidateKeywordArguments(kwds))) return -1; +#endif + if (PyDict_Update(kwds2, kwds) < 0) goto bad; + name = first_kw_arg; + while (*name) { + PyObject *key = **name; + PyObject *value; +#if !CYTHON_COMPILING_IN_LIMITED_API && (PY_VERSION_HEX >= 0x030d00A2 || defined(PyDict_Pop)) + int found = PyDict_Pop(kwds2, key, &value); + if (found) { + if (unlikely(found < 0)) goto bad; + values[name-argnames] = value; + } +#elif __PYX_LIMITED_VERSION_HEX >= 0x030d0000 + int found = PyDict_GetItemRef(kwds2, key, &value); + if (found) { + if (unlikely(found < 0)) goto bad; + values[name-argnames] = value; + if (unlikely(PyDict_DelItem(kwds2, key) < 0)) goto bad; + } +#else + #if CYTHON_COMPILING_IN_CPYTHON + value = _PyDict_Pop(kwds2, key, kwds2); + #else + value = __Pyx_CallUnboundCMethod2(&__pyx_mstate_global->__pyx_umethod_PyDict_Type_pop, kwds2, key, kwds2); + #endif + if (value == kwds2) { + Py_DECREF(value); + } else { + if (unlikely(!value)) goto bad; + values[name-argnames] = value; + } +#endif + name++; + } + len = PyDict_Size(kwds2); + if (len > 0) { + return __Pyx_ValidateDuplicatePosArgs(kwds, argnames, first_kw_arg, function_name); + } else if (unlikely(len == -1)) { + goto bad; + } + return 0; +bad: + return -1; +} +static int __Pyx_ParseKeywordsTuple( + PyObject *kwds, + PyObject * const *kwvalues, + PyObject ** const argnames[], + PyObject *kwds2, + PyObject *values[], + Py_ssize_t num_pos_args, + Py_ssize_t num_kwargs, + const char* function_name, + int ignore_unknown_kwargs) +{ + PyObject *key = NULL; + PyObject** const * name; + PyObject** const *first_kw_arg = argnames + num_pos_args; + for (Py_ssize_t pos = 0; pos < num_kwargs; pos++) { +#if CYTHON_AVOID_BORROWED_REFS + key = __Pyx_PySequence_ITEM(kwds, pos); +#else + key = __Pyx_PyTuple_GET_ITEM(kwds, pos); +#endif +#if !CYTHON_ASSUME_SAFE_MACROS + if (unlikely(!key)) goto bad; +#endif + name = first_kw_arg; + while (*name && (**name != key)) name++; + if (*name) { + PyObject *value = kwvalues[pos]; + values[name-argnames] = __Pyx_NewRef(value); + } else { + size_t index_found = 0; + int cmp = __Pyx_MatchKeywordArg(key, argnames, first_kw_arg, &index_found, function_name); + if (cmp == 1) { + PyObject *value = kwvalues[pos]; + values[index_found] = __Pyx_NewRef(value); + } else { + if (unlikely(cmp == -1)) goto bad; + if (kwds2) { + PyObject *value = kwvalues[pos]; + if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; + } else if (!ignore_unknown_kwargs) { + goto invalid_keyword; + } + } + } + #if CYTHON_AVOID_BORROWED_REFS + Py_DECREF(key); + key = NULL; + #endif + } + return 0; +invalid_keyword: + PyErr_Format(PyExc_TypeError, + "%s() got an unexpected keyword argument '%U'", + function_name, key); + goto bad; +bad: + #if CYTHON_AVOID_BORROWED_REFS + Py_XDECREF(key); + #endif + return -1; +} + +/* ParseKeywords */ +static int __Pyx_ParseKeywords( + PyObject *kwds, + PyObject * const *kwvalues, + PyObject ** const argnames[], + PyObject *kwds2, + PyObject *values[], + Py_ssize_t num_pos_args, + Py_ssize_t num_kwargs, + const char* function_name, + int ignore_unknown_kwargs) +{ + if (CYTHON_METH_FASTCALL && likely(PyTuple_Check(kwds))) + return __Pyx_ParseKeywordsTuple(kwds, kwvalues, argnames, kwds2, values, num_pos_args, num_kwargs, function_name, ignore_unknown_kwargs); + else if (kwds2) + return __Pyx_ParseKeywordDictToDict(kwds, argnames, kwds2, values, num_pos_args, function_name); + else + return __Pyx_ParseKeywordDict(kwds, argnames, values, num_pos_args, num_kwargs, function_name, ignore_unknown_kwargs); +} + +/* RaiseArgTupleInvalid */ +static void __Pyx_RaiseArgtupleInvalid( + const char* func_name, + int exact, + Py_ssize_t num_min, + Py_ssize_t num_max, + Py_ssize_t num_found) +{ + Py_ssize_t num_expected; + const char *more_or_less; + if (num_found < num_min) { + num_expected = num_min; + more_or_less = "at least"; + } else { + num_expected = num_max; + more_or_less = "at most"; + } + if (exact) { + more_or_less = "exactly"; + } + PyErr_Format(PyExc_TypeError, + "%.200s() takes %.8s %" CYTHON_FORMAT_SSIZE_T "d positional argument%.1s (%" CYTHON_FORMAT_SSIZE_T "d given)", + func_name, more_or_less, num_expected, + (num_expected == 1) ? "" : "s", num_found); +} + +/* TypeImport */ +#ifndef __PYX_HAVE_RT_ImportType_3_2_0 +#define __PYX_HAVE_RT_ImportType_3_2_0 +static PyTypeObject *__Pyx_ImportType_3_2_0(PyObject *module, const char *module_name, const char *class_name, + size_t size, size_t alignment, enum __Pyx_ImportType_CheckSize_3_2_0 check_size) +{ + PyObject *result = 0; + Py_ssize_t basicsize; + Py_ssize_t itemsize; +#if defined(Py_LIMITED_API) || (defined(CYTHON_COMPILING_IN_LIMITED_API) && CYTHON_COMPILING_IN_LIMITED_API) + PyObject *py_basicsize; + PyObject *py_itemsize; +#endif + result = PyObject_GetAttrString(module, class_name); + if (!result) + goto bad; + if (!PyType_Check(result)) { + PyErr_Format(PyExc_TypeError, + "%.200s.%.200s is not a type object", + module_name, class_name); + goto bad; + } +#if !( defined(Py_LIMITED_API) || (defined(CYTHON_COMPILING_IN_LIMITED_API) && CYTHON_COMPILING_IN_LIMITED_API) ) + basicsize = ((PyTypeObject *)result)->tp_basicsize; + itemsize = ((PyTypeObject *)result)->tp_itemsize; +#else + if (size == 0) { + return (PyTypeObject *)result; + } + py_basicsize = PyObject_GetAttrString(result, "__basicsize__"); + if (!py_basicsize) + goto bad; + basicsize = PyLong_AsSsize_t(py_basicsize); + Py_DECREF(py_basicsize); + py_basicsize = 0; + if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred()) + goto bad; + py_itemsize = PyObject_GetAttrString(result, "__itemsize__"); + if (!py_itemsize) + goto bad; + itemsize = PyLong_AsSsize_t(py_itemsize); + Py_DECREF(py_itemsize); + py_itemsize = 0; + if (itemsize == (Py_ssize_t)-1 && PyErr_Occurred()) + goto bad; +#endif + if (itemsize) { + if (size % alignment) { + alignment = size % alignment; + } + if (itemsize < (Py_ssize_t)alignment) + itemsize = (Py_ssize_t)alignment; + } + if ((size_t)(basicsize + itemsize) < size) { + PyErr_Format(PyExc_ValueError, + "%.200s.%.200s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize+itemsize); + goto bad; + } + if (check_size == __Pyx_ImportType_CheckSize_Error_3_2_0 && + ((size_t)basicsize > size || (size_t)(basicsize + itemsize) < size)) { + PyErr_Format(PyExc_ValueError, + "%.200s.%.200s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd-%zd from PyObject", + module_name, class_name, size, basicsize, basicsize+itemsize); + goto bad; + } + else if (check_size == __Pyx_ImportType_CheckSize_Warn_3_2_0 && (size_t)basicsize > size) { + if (PyErr_WarnFormat(NULL, 0, + "%.200s.%.200s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize) < 0) { + goto bad; + } + } + return (PyTypeObject *)result; +bad: + Py_XDECREF(result); + return NULL; +} +#endif + +/* ListPack */ +static PyObject *__Pyx_PyList_Pack(Py_ssize_t n, ...) { + va_list va; + PyObject *l = PyList_New(n); + va_start(va, n); + if (unlikely(!l)) goto end; + for (Py_ssize_t i=0; i= 0x030C0000 + PyObject *args[] = {d, key, default_value}; + value = PyObject_VectorcallMethod(__pyx_mstate_global->__pyx_n_u_setdefault, args, 3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); +#elif CYTHON_COMPILING_IN_LIMITED_API + value = PyObject_CallMethodObjArgs(d, __pyx_mstate_global->__pyx_n_u_setdefault, key, default_value, NULL); +#elif PY_VERSION_HEX >= 0x030d0000 + PyDict_SetDefaultRef(d, key, default_value, &value); +#else + value = PyDict_SetDefault(d, key, default_value); + if (unlikely(!value)) return NULL; + Py_INCREF(value); +#endif + return value; +} + +/* LimitedApiGetTypeDict */ +#if CYTHON_COMPILING_IN_LIMITED_API +static Py_ssize_t __Pyx_GetTypeDictOffset(void) { + PyObject *tp_dictoffset_o; + Py_ssize_t tp_dictoffset; + tp_dictoffset_o = PyObject_GetAttrString((PyObject*)(&PyType_Type), "__dictoffset__"); + if (unlikely(!tp_dictoffset_o)) return -1; + tp_dictoffset = PyLong_AsSsize_t(tp_dictoffset_o); + Py_DECREF(tp_dictoffset_o); + if (unlikely(tp_dictoffset == 0)) { + PyErr_SetString( + PyExc_TypeError, + "'type' doesn't have a dictoffset"); + return -1; + } else if (unlikely(tp_dictoffset < 0)) { + PyErr_SetString( + PyExc_TypeError, + "'type' has an unexpected negative dictoffset. " + "Please report this as Cython bug"); + return -1; + } + return tp_dictoffset; +} +static PyObject *__Pyx_GetTypeDict(PyTypeObject *tp) { + static Py_ssize_t tp_dictoffset = 0; + if (unlikely(tp_dictoffset == 0)) { + tp_dictoffset = __Pyx_GetTypeDictOffset(); + if (unlikely(tp_dictoffset == -1 && PyErr_Occurred())) { + tp_dictoffset = 0; // try again next time? + return NULL; + } + } + return *(PyObject**)((char*)tp + tp_dictoffset); +} +#endif + +/* SetItemOnTypeDict */ +static int __Pyx__SetItemOnTypeDict(PyTypeObject *tp, PyObject *k, PyObject *v) { + int result; + PyObject *tp_dict; +#if CYTHON_COMPILING_IN_LIMITED_API + tp_dict = __Pyx_GetTypeDict(tp); + if (unlikely(!tp_dict)) return -1; +#else + tp_dict = tp->tp_dict; +#endif + result = PyDict_SetItem(tp_dict, k, v); + if (likely(!result)) { + PyType_Modified(tp); + if (unlikely(PyObject_HasAttr(v, __pyx_mstate_global->__pyx_n_u_set_name))) { + PyObject *setNameResult = PyObject_CallMethodObjArgs(v, __pyx_mstate_global->__pyx_n_u_set_name, (PyObject *) tp, k, NULL); + if (!setNameResult) return -1; + Py_DECREF(setNameResult); + } + } + return result; +} + +/* FixUpExtensionType */ +static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject *type) { +#if __PYX_LIMITED_VERSION_HEX > 0x030900B1 + CYTHON_UNUSED_VAR(spec); + CYTHON_UNUSED_VAR(type); + CYTHON_UNUSED_VAR(__Pyx__SetItemOnTypeDict); +#else + const PyType_Slot *slot = spec->slots; + int changed = 0; +#if !CYTHON_COMPILING_IN_LIMITED_API + while (slot && slot->slot && slot->slot != Py_tp_members) + slot++; + if (slot && slot->slot == Py_tp_members) { +#if !CYTHON_COMPILING_IN_CPYTHON + const +#endif // !CYTHON_COMPILING_IN_CPYTHON) + PyMemberDef *memb = (PyMemberDef*) slot->pfunc; + while (memb && memb->name) { + if (memb->name[0] == '_' && memb->name[1] == '_') { + if (strcmp(memb->name, "__weaklistoffset__") == 0) { + assert(memb->type == T_PYSSIZET); + assert(memb->flags == READONLY); + type->tp_weaklistoffset = memb->offset; + changed = 1; + } + else if (strcmp(memb->name, "__dictoffset__") == 0) { + assert(memb->type == T_PYSSIZET); + assert(memb->flags == READONLY); + type->tp_dictoffset = memb->offset; + changed = 1; + } +#if CYTHON_METH_FASTCALL + else if (strcmp(memb->name, "__vectorcalloffset__") == 0) { + assert(memb->type == T_PYSSIZET); + assert(memb->flags == READONLY); + type->tp_vectorcall_offset = memb->offset; + changed = 1; + } +#endif // CYTHON_METH_FASTCALL +#if !CYTHON_COMPILING_IN_PYPY + else if (strcmp(memb->name, "__module__") == 0) { + PyObject *descr; + assert(memb->type == T_OBJECT); + assert(memb->flags == 0 || memb->flags == READONLY); + descr = PyDescr_NewMember(type, memb); + if (unlikely(!descr)) + return -1; + int set_item_result = PyDict_SetItem(type->tp_dict, PyDescr_NAME(descr), descr); + Py_DECREF(descr); + if (unlikely(set_item_result < 0)) { + return -1; + } + changed = 1; + } +#endif // !CYTHON_COMPILING_IN_PYPY + } + memb++; + } + } +#endif // !CYTHON_COMPILING_IN_LIMITED_API +#if !CYTHON_COMPILING_IN_PYPY + slot = spec->slots; + while (slot && slot->slot && slot->slot != Py_tp_getset) + slot++; + if (slot && slot->slot == Py_tp_getset) { + PyGetSetDef *getset = (PyGetSetDef*) slot->pfunc; + while (getset && getset->name) { + if (getset->name[0] == '_' && getset->name[1] == '_' && strcmp(getset->name, "__module__") == 0) { + PyObject *descr = PyDescr_NewGetSet(type, getset); + if (unlikely(!descr)) + return -1; + #if CYTHON_COMPILING_IN_LIMITED_API + PyObject *pyname = PyUnicode_FromString(getset->name); + if (unlikely(!pyname)) { + Py_DECREF(descr); + return -1; + } + int set_item_result = __Pyx_SetItemOnTypeDict(type, pyname, descr); + Py_DECREF(pyname); + #else + CYTHON_UNUSED_VAR(__Pyx__SetItemOnTypeDict); + int set_item_result = PyDict_SetItem(type->tp_dict, PyDescr_NAME(descr), descr); + #endif + Py_DECREF(descr); + if (unlikely(set_item_result < 0)) { + return -1; + } + changed = 1; + } + ++getset; + } + } +#else + CYTHON_UNUSED_VAR(__Pyx__SetItemOnTypeDict); +#endif // !CYTHON_COMPILING_IN_PYPY + if (changed) + PyType_Modified(type); +#endif // PY_VERSION_HEX > 0x030900B1 + return 0; +} + +/* AddModuleRef */ +#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + static PyObject *__Pyx_PyImport_AddModuleObjectRef(PyObject *name) { + PyObject *module_dict = PyImport_GetModuleDict(); + PyObject *m; + if (PyMapping_GetOptionalItem(module_dict, name, &m) < 0) { + return NULL; + } + if (m != NULL && PyModule_Check(m)) { + return m; + } + Py_XDECREF(m); + m = PyModule_NewObject(name); + if (m == NULL) + return NULL; + if (PyDict_CheckExact(module_dict)) { + PyObject *new_m; + (void)PyDict_SetDefaultRef(module_dict, name, m, &new_m); + Py_DECREF(m); + return new_m; + } else { + if (PyObject_SetItem(module_dict, name, m) != 0) { + Py_DECREF(m); + return NULL; + } + return m; + } + } + static PyObject *__Pyx_PyImport_AddModuleRef(const char *name) { + PyObject *py_name = PyUnicode_FromString(name); + if (!py_name) return NULL; + PyObject *module = __Pyx_PyImport_AddModuleObjectRef(py_name); + Py_DECREF(py_name); + return module; + } +#elif __PYX_LIMITED_VERSION_HEX >= 0x030d0000 + #define __Pyx_PyImport_AddModuleRef(name) PyImport_AddModuleRef(name) +#else + static PyObject *__Pyx_PyImport_AddModuleRef(const char *name) { + PyObject *module = PyImport_AddModule(name); + Py_XINCREF(module); + return module; + } +#endif + +/* FetchSharedCythonModule */ +static PyObject *__Pyx_FetchSharedCythonABIModule(void) { + return __Pyx_PyImport_AddModuleRef(__PYX_ABI_MODULE_NAME); +} + +/* FetchCommonType */ +#if __PYX_LIMITED_VERSION_HEX < 0x030C0000 +static PyObject* __Pyx_PyType_FromMetaclass(PyTypeObject *metaclass, PyObject *module, PyType_Spec *spec, PyObject *bases) { + PyObject *result = __Pyx_PyType_FromModuleAndSpec(module, spec, bases); + if (result && metaclass) { + PyObject *old_tp = (PyObject*)Py_TYPE(result); + Py_INCREF((PyObject*)metaclass); +#if __PYX_LIMITED_VERSION_HEX >= 0x03090000 + Py_SET_TYPE(result, metaclass); +#else + result->ob_type = metaclass; +#endif + Py_DECREF(old_tp); + } + return result; +} +#else +#define __Pyx_PyType_FromMetaclass(me, mo, s, b) PyType_FromMetaclass(me, mo, s, b) +#endif +static int __Pyx_VerifyCachedType(PyObject *cached_type, + const char *name, + Py_ssize_t expected_basicsize) { + Py_ssize_t basicsize; + if (!PyType_Check(cached_type)) { + PyErr_Format(PyExc_TypeError, + "Shared Cython type %.200s is not a type object", name); + return -1; + } + if (expected_basicsize == 0) { + return 0; // size is inherited, nothing useful to check + } +#if CYTHON_COMPILING_IN_LIMITED_API + PyObject *py_basicsize; + py_basicsize = PyObject_GetAttrString(cached_type, "__basicsize__"); + if (unlikely(!py_basicsize)) return -1; + basicsize = PyLong_AsSsize_t(py_basicsize); + Py_DECREF(py_basicsize); + py_basicsize = NULL; + if (unlikely(basicsize == (Py_ssize_t)-1) && PyErr_Occurred()) return -1; +#else + basicsize = ((PyTypeObject*) cached_type)->tp_basicsize; +#endif + if (basicsize != expected_basicsize) { + PyErr_Format(PyExc_TypeError, + "Shared Cython type %.200s has the wrong size, try recompiling", + name); + return -1; + } + return 0; +} +static PyTypeObject *__Pyx_FetchCommonTypeFromSpec(PyTypeObject *metaclass, PyObject *module, PyType_Spec *spec, PyObject *bases) { + PyObject *abi_module = NULL, *cached_type = NULL, *abi_module_dict, *new_cached_type, *py_object_name; + int get_item_ref_result; + const char* object_name = strrchr(spec->name, '.'); + object_name = object_name ? object_name+1 : spec->name; + py_object_name = PyUnicode_FromString(object_name); + if (!py_object_name) return NULL; + abi_module = __Pyx_FetchSharedCythonABIModule(); + if (!abi_module) goto done; + abi_module_dict = PyModule_GetDict(abi_module); + if (!abi_module_dict) goto done; + get_item_ref_result = __Pyx_PyDict_GetItemRef(abi_module_dict, py_object_name, &cached_type); + if (get_item_ref_result == 1) { + if (__Pyx_VerifyCachedType( + cached_type, + object_name, + spec->basicsize) < 0) { + goto bad; + } + goto done; + } else if (unlikely(get_item_ref_result == -1)) { + goto bad; + } + cached_type = __Pyx_PyType_FromMetaclass( + metaclass, + CYTHON_USE_MODULE_STATE ? module : abi_module, + spec, bases); + if (unlikely(!cached_type)) goto bad; + if (unlikely(__Pyx_fix_up_extension_type_from_spec(spec, (PyTypeObject *) cached_type) < 0)) goto bad; + new_cached_type = __Pyx_PyDict_SetDefault(abi_module_dict, py_object_name, cached_type); + if (unlikely(new_cached_type != cached_type)) { + if (unlikely(!new_cached_type)) goto bad; + Py_DECREF(cached_type); + cached_type = new_cached_type; + if (__Pyx_VerifyCachedType( + cached_type, + object_name, + spec->basicsize) < 0) { + goto bad; + } + goto done; + } else { + Py_DECREF(new_cached_type); + } +done: + Py_XDECREF(abi_module); + Py_DECREF(py_object_name); + assert(cached_type == NULL || PyType_Check(cached_type)); + return (PyTypeObject *) cached_type; +bad: + Py_XDECREF(cached_type); + cached_type = NULL; + goto done; +} + +/* CommonTypesMetaclass */ +static PyObject* __pyx_CommonTypesMetaclass_get_module(CYTHON_UNUSED PyObject *self, CYTHON_UNUSED void* context) { + return PyUnicode_FromString(__PYX_ABI_MODULE_NAME); +} +#if __PYX_LIMITED_VERSION_HEX < 0x030A0000 +static PyObject* __pyx_CommonTypesMetaclass_call(CYTHON_UNUSED PyObject *self, CYTHON_UNUSED PyObject *args, CYTHON_UNUSED PyObject *kwds) { + PyErr_SetString(PyExc_TypeError, "Cannot instantiate Cython internal types"); + return NULL; +} +static int __pyx_CommonTypesMetaclass_setattr(CYTHON_UNUSED PyObject *self, CYTHON_UNUSED PyObject *attr, CYTHON_UNUSED PyObject *value) { + PyErr_SetString(PyExc_TypeError, "Cython internal types are immutable"); + return -1; +} +#endif +static PyGetSetDef __pyx_CommonTypesMetaclass_getset[] = { + {"__module__", __pyx_CommonTypesMetaclass_get_module, NULL, NULL, NULL}, + {0, 0, 0, 0, 0} +}; +static PyType_Slot __pyx_CommonTypesMetaclass_slots[] = { + {Py_tp_getset, (void *)__pyx_CommonTypesMetaclass_getset}, + #if __PYX_LIMITED_VERSION_HEX < 0x030A0000 + {Py_tp_call, (void*)__pyx_CommonTypesMetaclass_call}, + {Py_tp_new, (void*)__pyx_CommonTypesMetaclass_call}, + {Py_tp_setattro, (void*)__pyx_CommonTypesMetaclass_setattr}, + #endif + {0, 0} +}; +static PyType_Spec __pyx_CommonTypesMetaclass_spec = { + __PYX_TYPE_MODULE_PREFIX "_common_types_metatype", + 0, + 0, + Py_TPFLAGS_IMMUTABLETYPE | + Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_DEFAULT, + __pyx_CommonTypesMetaclass_slots +}; +static int __pyx_CommonTypesMetaclass_init(PyObject *module) { + __pyx_mstatetype *mstate = __Pyx_PyModule_GetState(module); + PyObject *bases = PyTuple_Pack(1, &PyType_Type); + if (unlikely(!bases)) { + return -1; + } + mstate->__pyx_CommonTypesMetaclassType = __Pyx_FetchCommonTypeFromSpec(NULL, module, &__pyx_CommonTypesMetaclass_spec, bases); + Py_DECREF(bases); + if (unlikely(mstate->__pyx_CommonTypesMetaclassType == NULL)) { + return -1; + } + return 0; +} + +/* CallTypeTraverse */ +#if !CYTHON_USE_TYPE_SPECS || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX < 0x03090000) +#else +static int __Pyx_call_type_traverse(PyObject *o, int always_call, visitproc visit, void *arg) { + #if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x03090000 + if (__Pyx_get_runtime_version() < 0x03090000) return 0; + #endif + if (!always_call) { + PyTypeObject *base = __Pyx_PyObject_GetSlot(o, tp_base, PyTypeObject*); + unsigned long flags = PyType_GetFlags(base); + if (flags & Py_TPFLAGS_HEAPTYPE) { + return 0; + } + } + Py_VISIT((PyObject*)Py_TYPE(o)); + return 0; +} +#endif + +/* PyMethodNew */ +#if CYTHON_COMPILING_IN_LIMITED_API +static PyObject *__Pyx_PyMethod_New(PyObject *func, PyObject *self, PyObject *typ) { + PyObject *result; + CYTHON_UNUSED_VAR(typ); + if (!self) + return __Pyx_NewRef(func); + #if __PYX_LIMITED_VERSION_HEX >= 0x030C0000 + { + PyObject *args[] = {func, self}; + result = PyObject_Vectorcall(__pyx_mstate_global->__Pyx_CachedMethodType, args, 2, NULL); + } + #else + result = PyObject_CallFunctionObjArgs(__pyx_mstate_global->__Pyx_CachedMethodType, func, self, NULL); + #endif + return result; +} +#else +static PyObject *__Pyx_PyMethod_New(PyObject *func, PyObject *self, PyObject *typ) { + CYTHON_UNUSED_VAR(typ); + if (!self) + return __Pyx_NewRef(func); + return PyMethod_New(func, self); +} +#endif + +/* PyVectorcallFastCallDict */ +#if CYTHON_METH_FASTCALL && CYTHON_VECTORCALL +static PyObject *__Pyx_PyVectorcall_FastCallDict_kw(PyObject *func, __pyx_vectorcallfunc vc, PyObject *const *args, size_t nargs, PyObject *kw) +{ + PyObject *res = NULL; + PyObject *kwnames; + PyObject **newargs; + PyObject **kwvalues; + Py_ssize_t i; + #if CYTHON_AVOID_BORROWED_REFS + PyObject *pos; + #else + Py_ssize_t pos; + #endif + size_t j; + PyObject *key, *value; + unsigned long keys_are_strings; + #if !CYTHON_ASSUME_SAFE_SIZE + Py_ssize_t nkw = PyDict_Size(kw); + if (unlikely(nkw == -1)) return NULL; + #else + Py_ssize_t nkw = PyDict_GET_SIZE(kw); + #endif + newargs = (PyObject **)PyMem_Malloc((nargs + (size_t)nkw) * sizeof(args[0])); + if (unlikely(newargs == NULL)) { + PyErr_NoMemory(); + return NULL; + } + for (j = 0; j < nargs; j++) newargs[j] = args[j]; + kwnames = PyTuple_New(nkw); + if (unlikely(kwnames == NULL)) { + PyMem_Free(newargs); + return NULL; + } + kwvalues = newargs + nargs; + pos = 0; + i = 0; + keys_are_strings = Py_TPFLAGS_UNICODE_SUBCLASS; + while (__Pyx_PyDict_NextRef(kw, &pos, &key, &value)) { + keys_are_strings &= + #if CYTHON_COMPILING_IN_LIMITED_API + PyType_GetFlags(Py_TYPE(key)); + #else + Py_TYPE(key)->tp_flags; + #endif + #if !CYTHON_ASSUME_SAFE_MACROS + if (unlikely(PyTuple_SetItem(kwnames, i, key) < 0)) goto cleanup; + #else + PyTuple_SET_ITEM(kwnames, i, key); + #endif + kwvalues[i] = value; + i++; + } + if (unlikely(!keys_are_strings)) { + PyErr_SetString(PyExc_TypeError, "keywords must be strings"); + goto cleanup; + } + res = vc(func, newargs, nargs, kwnames); +cleanup: + #if CYTHON_AVOID_BORROWED_REFS + Py_DECREF(pos); + #endif + Py_DECREF(kwnames); + for (i = 0; i < nkw; i++) + Py_DECREF(kwvalues[i]); + PyMem_Free(newargs); + return res; +} +static CYTHON_INLINE PyObject *__Pyx_PyVectorcall_FastCallDict(PyObject *func, __pyx_vectorcallfunc vc, PyObject *const *args, size_t nargs, PyObject *kw) +{ + Py_ssize_t kw_size = + likely(kw == NULL) ? + 0 : +#if !CYTHON_ASSUME_SAFE_SIZE + PyDict_Size(kw); +#else + PyDict_GET_SIZE(kw); +#endif + if (kw_size == 0) { + return vc(func, args, nargs, NULL); + } +#if !CYTHON_ASSUME_SAFE_SIZE + else if (unlikely(kw_size == -1)) { + return NULL; + } +#endif + return __Pyx_PyVectorcall_FastCallDict_kw(func, vc, args, nargs, kw); +} +#endif + +/* CythonFunctionShared */ +#if CYTHON_COMPILING_IN_LIMITED_API +static CYTHON_INLINE int __Pyx__IsSameCyOrCFunctionNoMethod(PyObject *func, void (*cfunc)(void)) { + if (__Pyx_CyFunction_Check(func)) { + return PyCFunction_GetFunction(((__pyx_CyFunctionObject*)func)->func) == (PyCFunction) cfunc; + } else if (PyCFunction_Check(func)) { + return PyCFunction_GetFunction(func) == (PyCFunction) cfunc; + } + return 0; +} +static CYTHON_INLINE int __Pyx__IsSameCyOrCFunction(PyObject *func, void (*cfunc)(void)) { + if ((PyObject*)Py_TYPE(func) == __pyx_mstate_global->__Pyx_CachedMethodType) { + int result; + PyObject *newFunc = PyObject_GetAttr(func, __pyx_mstate_global->__pyx_n_u_func); + if (unlikely(!newFunc)) { + PyErr_Clear(); // It's only an optimization, so don't throw an error + return 0; + } + result = __Pyx__IsSameCyOrCFunctionNoMethod(newFunc, cfunc); + Py_DECREF(newFunc); + return result; + } + return __Pyx__IsSameCyOrCFunctionNoMethod(func, cfunc); +} +#else +static CYTHON_INLINE int __Pyx__IsSameCyOrCFunction(PyObject *func, void (*cfunc)(void)) { + if (PyMethod_Check(func)) { + func = PyMethod_GET_FUNCTION(func); + } + return __Pyx_CyOrPyCFunction_Check(func) && __Pyx_CyOrPyCFunction_GET_FUNCTION(func) == (PyCFunction) cfunc; +} +#endif +static CYTHON_INLINE void __Pyx__CyFunction_SetClassObj(__pyx_CyFunctionObject* f, PyObject* classobj) { +#if PY_VERSION_HEX < 0x030900B1 || CYTHON_COMPILING_IN_LIMITED_API + __Pyx_Py_XDECREF_SET( + __Pyx_CyFunction_GetClassObj(f), + ((classobj) ? __Pyx_NewRef(classobj) : NULL)); +#else + __Pyx_Py_XDECREF_SET( + ((PyCMethodObject *) (f))->mm_class, + (PyTypeObject*)((classobj) ? __Pyx_NewRef(classobj) : NULL)); +#endif +} +static PyObject * +__Pyx_CyFunction_get_doc_locked(__pyx_CyFunctionObject *op) +{ + if (unlikely(op->func_doc == NULL)) { +#if CYTHON_COMPILING_IN_LIMITED_API + op->func_doc = PyObject_GetAttrString(op->func, "__doc__"); + if (unlikely(!op->func_doc)) return NULL; +#else + if (((PyCFunctionObject*)op)->m_ml->ml_doc) { + op->func_doc = PyUnicode_FromString(((PyCFunctionObject*)op)->m_ml->ml_doc); + if (unlikely(op->func_doc == NULL)) + return NULL; + } else { + Py_INCREF(Py_None); + return Py_None; + } +#endif + } + Py_INCREF(op->func_doc); + return op->func_doc; +} +static PyObject * +__Pyx_CyFunction_get_doc(__pyx_CyFunctionObject *op, void *closure) { + PyObject *result; + CYTHON_UNUSED_VAR(closure); + __Pyx_BEGIN_CRITICAL_SECTION(op); + result = __Pyx_CyFunction_get_doc_locked(op); + __Pyx_END_CRITICAL_SECTION(); + return result; +} +static int +__Pyx_CyFunction_set_doc(__pyx_CyFunctionObject *op, PyObject *value, void *context) +{ + CYTHON_UNUSED_VAR(context); + if (value == NULL) { + value = Py_None; + } + Py_INCREF(value); + __Pyx_BEGIN_CRITICAL_SECTION(op); + __Pyx_Py_XDECREF_SET(op->func_doc, value); + __Pyx_END_CRITICAL_SECTION(); + return 0; +} +static PyObject * +__Pyx_CyFunction_get_name_locked(__pyx_CyFunctionObject *op) +{ + if (unlikely(op->func_name == NULL)) { +#if CYTHON_COMPILING_IN_LIMITED_API + op->func_name = PyObject_GetAttrString(op->func, "__name__"); +#else + op->func_name = PyUnicode_InternFromString(((PyCFunctionObject*)op)->m_ml->ml_name); +#endif + if (unlikely(op->func_name == NULL)) + return NULL; + } + Py_INCREF(op->func_name); + return op->func_name; +} +static PyObject * +__Pyx_CyFunction_get_name(__pyx_CyFunctionObject *op, void *context) +{ + PyObject *result = NULL; + CYTHON_UNUSED_VAR(context); + __Pyx_BEGIN_CRITICAL_SECTION(op); + result = __Pyx_CyFunction_get_name_locked(op); + __Pyx_END_CRITICAL_SECTION(); + return result; +} +static int +__Pyx_CyFunction_set_name(__pyx_CyFunctionObject *op, PyObject *value, void *context) +{ + CYTHON_UNUSED_VAR(context); + if (unlikely(value == NULL || !PyUnicode_Check(value))) { + PyErr_SetString(PyExc_TypeError, + "__name__ must be set to a string object"); + return -1; + } + Py_INCREF(value); + __Pyx_BEGIN_CRITICAL_SECTION(op); + __Pyx_Py_XDECREF_SET(op->func_name, value); + __Pyx_END_CRITICAL_SECTION(); + return 0; +} +static PyObject * +__Pyx_CyFunction_get_qualname(__pyx_CyFunctionObject *op, void *context) +{ + CYTHON_UNUSED_VAR(context); + PyObject *result; + __Pyx_BEGIN_CRITICAL_SECTION(op); + Py_INCREF(op->func_qualname); + result = op->func_qualname; + __Pyx_END_CRITICAL_SECTION(); + return result; +} +static int +__Pyx_CyFunction_set_qualname(__pyx_CyFunctionObject *op, PyObject *value, void *context) +{ + CYTHON_UNUSED_VAR(context); + if (unlikely(value == NULL || !PyUnicode_Check(value))) { + PyErr_SetString(PyExc_TypeError, + "__qualname__ must be set to a string object"); + return -1; + } + Py_INCREF(value); + __Pyx_BEGIN_CRITICAL_SECTION(op); + __Pyx_Py_XDECREF_SET(op->func_qualname, value); + __Pyx_END_CRITICAL_SECTION(); + return 0; +} +#if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030A0000 +static PyObject * +__Pyx_CyFunction_get_dict(__pyx_CyFunctionObject *op, void *context) +{ + CYTHON_UNUSED_VAR(context); + if (unlikely(op->func_dict == NULL)) { + op->func_dict = PyDict_New(); + if (unlikely(op->func_dict == NULL)) + return NULL; + } + Py_INCREF(op->func_dict); + return op->func_dict; +} +#endif +static PyObject * +__Pyx_CyFunction_get_globals(__pyx_CyFunctionObject *op, void *context) +{ + CYTHON_UNUSED_VAR(context); + Py_INCREF(op->func_globals); + return op->func_globals; +} +static PyObject * +__Pyx_CyFunction_get_closure(__pyx_CyFunctionObject *op, void *context) +{ + CYTHON_UNUSED_VAR(op); + CYTHON_UNUSED_VAR(context); + Py_INCREF(Py_None); + return Py_None; +} +static PyObject * +__Pyx_CyFunction_get_code(__pyx_CyFunctionObject *op, void *context) +{ + PyObject* result = (op->func_code) ? op->func_code : Py_None; + CYTHON_UNUSED_VAR(context); + Py_INCREF(result); + return result; +} +static int +__Pyx_CyFunction_init_defaults(__pyx_CyFunctionObject *op) { + int result = 0; + PyObject *res = op->defaults_getter((PyObject *) op); + if (unlikely(!res)) + return -1; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + op->defaults_tuple = PyTuple_GET_ITEM(res, 0); + Py_INCREF(op->defaults_tuple); + op->defaults_kwdict = PyTuple_GET_ITEM(res, 1); + Py_INCREF(op->defaults_kwdict); + #else + op->defaults_tuple = __Pyx_PySequence_ITEM(res, 0); + if (unlikely(!op->defaults_tuple)) result = -1; + else { + op->defaults_kwdict = __Pyx_PySequence_ITEM(res, 1); + if (unlikely(!op->defaults_kwdict)) result = -1; + } + #endif + Py_DECREF(res); + return result; +} +static int +__Pyx_CyFunction_set_defaults(__pyx_CyFunctionObject *op, PyObject* value, void *context) { + CYTHON_UNUSED_VAR(context); + if (!value) { + value = Py_None; + } else if (unlikely(value != Py_None && !PyTuple_Check(value))) { + PyErr_SetString(PyExc_TypeError, + "__defaults__ must be set to a tuple object"); + return -1; + } + PyErr_WarnEx(PyExc_RuntimeWarning, "changes to cyfunction.__defaults__ will not " + "currently affect the values used in function calls", 1); + Py_INCREF(value); + __Pyx_BEGIN_CRITICAL_SECTION(op); + __Pyx_Py_XDECREF_SET(op->defaults_tuple, value); + __Pyx_END_CRITICAL_SECTION(); + return 0; +} +static PyObject * +__Pyx_CyFunction_get_defaults_locked(__pyx_CyFunctionObject *op) { + PyObject* result = op->defaults_tuple; + if (unlikely(!result)) { + if (op->defaults_getter) { + if (unlikely(__Pyx_CyFunction_init_defaults(op) < 0)) return NULL; + result = op->defaults_tuple; + } else { + result = Py_None; + } + } + Py_INCREF(result); + return result; +} +static PyObject * +__Pyx_CyFunction_get_defaults(__pyx_CyFunctionObject *op, void *context) { + PyObject* result = NULL; + CYTHON_UNUSED_VAR(context); + __Pyx_BEGIN_CRITICAL_SECTION(op); + result = __Pyx_CyFunction_get_defaults_locked(op); + __Pyx_END_CRITICAL_SECTION(); + return result; +} +static int +__Pyx_CyFunction_set_kwdefaults(__pyx_CyFunctionObject *op, PyObject* value, void *context) { + CYTHON_UNUSED_VAR(context); + if (!value) { + value = Py_None; + } else if (unlikely(value != Py_None && !PyDict_Check(value))) { + PyErr_SetString(PyExc_TypeError, + "__kwdefaults__ must be set to a dict object"); + return -1; + } + PyErr_WarnEx(PyExc_RuntimeWarning, "changes to cyfunction.__kwdefaults__ will not " + "currently affect the values used in function calls", 1); + Py_INCREF(value); + __Pyx_BEGIN_CRITICAL_SECTION(op); + __Pyx_Py_XDECREF_SET(op->defaults_kwdict, value); + __Pyx_END_CRITICAL_SECTION(); + return 0; +} +static PyObject * +__Pyx_CyFunction_get_kwdefaults_locked(__pyx_CyFunctionObject *op) { + PyObject* result = op->defaults_kwdict; + if (unlikely(!result)) { + if (op->defaults_getter) { + if (unlikely(__Pyx_CyFunction_init_defaults(op) < 0)) return NULL; + result = op->defaults_kwdict; + } else { + result = Py_None; + } + } + Py_INCREF(result); + return result; +} +static PyObject * +__Pyx_CyFunction_get_kwdefaults(__pyx_CyFunctionObject *op, void *context) { + PyObject* result; + CYTHON_UNUSED_VAR(context); + __Pyx_BEGIN_CRITICAL_SECTION(op); + result = __Pyx_CyFunction_get_kwdefaults_locked(op); + __Pyx_END_CRITICAL_SECTION(); + return result; +} +static int +__Pyx_CyFunction_set_annotations(__pyx_CyFunctionObject *op, PyObject* value, void *context) { + CYTHON_UNUSED_VAR(context); + if (!value || value == Py_None) { + value = NULL; + } else if (unlikely(!PyDict_Check(value))) { + PyErr_SetString(PyExc_TypeError, + "__annotations__ must be set to a dict object"); + return -1; + } + Py_XINCREF(value); + __Pyx_BEGIN_CRITICAL_SECTION(op); + __Pyx_Py_XDECREF_SET(op->func_annotations, value); + __Pyx_END_CRITICAL_SECTION(); + return 0; +} +static PyObject * +__Pyx_CyFunction_get_annotations_locked(__pyx_CyFunctionObject *op) { + PyObject* result = op->func_annotations; + if (unlikely(!result)) { + result = PyDict_New(); + if (unlikely(!result)) return NULL; + op->func_annotations = result; + } + Py_INCREF(result); + return result; +} +static PyObject * +__Pyx_CyFunction_get_annotations(__pyx_CyFunctionObject *op, void *context) { + PyObject *result; + CYTHON_UNUSED_VAR(context); + __Pyx_BEGIN_CRITICAL_SECTION(op); + result = __Pyx_CyFunction_get_annotations_locked(op); + __Pyx_END_CRITICAL_SECTION(); + return result; +} +static PyObject * +__Pyx_CyFunction_get_is_coroutine_value(__pyx_CyFunctionObject *op) { + int is_coroutine = op->flags & __Pyx_CYFUNCTION_COROUTINE; + if (is_coroutine) { + PyObject *is_coroutine_value, *module, *fromlist, *marker = __pyx_mstate_global->__pyx_n_u_is_coroutine; + fromlist = PyList_New(1); + if (unlikely(!fromlist)) return NULL; + Py_INCREF(marker); +#if CYTHON_ASSUME_SAFE_MACROS + PyList_SET_ITEM(fromlist, 0, marker); +#else + if (unlikely(PyList_SetItem(fromlist, 0, marker) < 0)) { + Py_DECREF(marker); + Py_DECREF(fromlist); + return NULL; + } +#endif + module = PyImport_ImportModuleLevelObject(__pyx_mstate_global->__pyx_n_u_asyncio_coroutines, NULL, NULL, fromlist, 0); + Py_DECREF(fromlist); + if (unlikely(!module)) goto ignore; + is_coroutine_value = __Pyx_PyObject_GetAttrStr(module, marker); + Py_DECREF(module); + if (likely(is_coroutine_value)) { + return is_coroutine_value; + } +ignore: + PyErr_Clear(); + } + return __Pyx_PyBool_FromLong(is_coroutine); +} +static PyObject * +__Pyx_CyFunction_get_is_coroutine(__pyx_CyFunctionObject *op, void *context) { + PyObject *result; + CYTHON_UNUSED_VAR(context); + if (op->func_is_coroutine) { + return __Pyx_NewRef(op->func_is_coroutine); + } + result = __Pyx_CyFunction_get_is_coroutine_value(op); + if (unlikely(!result)) + return NULL; + __Pyx_BEGIN_CRITICAL_SECTION(op); + if (op->func_is_coroutine) { + Py_DECREF(result); + result = __Pyx_NewRef(op->func_is_coroutine); + } else { + op->func_is_coroutine = __Pyx_NewRef(result); + } + __Pyx_END_CRITICAL_SECTION(); + return result; +} +static void __Pyx_CyFunction_raise_argument_count_error(__pyx_CyFunctionObject *func, const char* message, Py_ssize_t size) { +#if CYTHON_COMPILING_IN_LIMITED_API + PyObject *py_name = __Pyx_CyFunction_get_name(func, NULL); + if (!py_name) return; + PyErr_Format(PyExc_TypeError, + "%.200S() %s (%" CYTHON_FORMAT_SSIZE_T "d given)", + py_name, message, size); + Py_DECREF(py_name); +#else + const char* name = ((PyCFunctionObject*)func)->m_ml->ml_name; + PyErr_Format(PyExc_TypeError, + "%.200s() %s (%" CYTHON_FORMAT_SSIZE_T "d given)", + name, message, size); +#endif +} +static void __Pyx_CyFunction_raise_type_error(__pyx_CyFunctionObject *func, const char* message) { +#if CYTHON_COMPILING_IN_LIMITED_API + PyObject *py_name = __Pyx_CyFunction_get_name(func, NULL); + if (!py_name) return; + PyErr_Format(PyExc_TypeError, + "%.200S() %s", + py_name, message); + Py_DECREF(py_name); +#else + const char* name = ((PyCFunctionObject*)func)->m_ml->ml_name; + PyErr_Format(PyExc_TypeError, + "%.200s() %s", + name, message); +#endif +} +#if CYTHON_COMPILING_IN_LIMITED_API +static PyObject * +__Pyx_CyFunction_get_module(__pyx_CyFunctionObject *op, void *context) { + CYTHON_UNUSED_VAR(context); + return PyObject_GetAttrString(op->func, "__module__"); +} +static int +__Pyx_CyFunction_set_module(__pyx_CyFunctionObject *op, PyObject* value, void *context) { + CYTHON_UNUSED_VAR(context); + return PyObject_SetAttrString(op->func, "__module__", value); +} +#endif +static PyGetSetDef __pyx_CyFunction_getsets[] = { + {"func_doc", (getter)__Pyx_CyFunction_get_doc, (setter)__Pyx_CyFunction_set_doc, 0, 0}, + {"__doc__", (getter)__Pyx_CyFunction_get_doc, (setter)__Pyx_CyFunction_set_doc, 0, 0}, + {"func_name", (getter)__Pyx_CyFunction_get_name, (setter)__Pyx_CyFunction_set_name, 0, 0}, + {"__name__", (getter)__Pyx_CyFunction_get_name, (setter)__Pyx_CyFunction_set_name, 0, 0}, + {"__qualname__", (getter)__Pyx_CyFunction_get_qualname, (setter)__Pyx_CyFunction_set_qualname, 0, 0}, +#if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030A0000 + {"func_dict", (getter)__Pyx_CyFunction_get_dict, (setter)PyObject_GenericSetDict, 0, 0}, + {"__dict__", (getter)__Pyx_CyFunction_get_dict, (setter)PyObject_GenericSetDict, 0, 0}, +#else + {"func_dict", (getter)PyObject_GenericGetDict, (setter)PyObject_GenericSetDict, 0, 0}, + {"__dict__", (getter)PyObject_GenericGetDict, (setter)PyObject_GenericSetDict, 0, 0}, +#endif + {"func_globals", (getter)__Pyx_CyFunction_get_globals, 0, 0, 0}, + {"__globals__", (getter)__Pyx_CyFunction_get_globals, 0, 0, 0}, + {"func_closure", (getter)__Pyx_CyFunction_get_closure, 0, 0, 0}, + {"__closure__", (getter)__Pyx_CyFunction_get_closure, 0, 0, 0}, + {"func_code", (getter)__Pyx_CyFunction_get_code, 0, 0, 0}, + {"__code__", (getter)__Pyx_CyFunction_get_code, 0, 0, 0}, + {"func_defaults", (getter)__Pyx_CyFunction_get_defaults, (setter)__Pyx_CyFunction_set_defaults, 0, 0}, + {"__defaults__", (getter)__Pyx_CyFunction_get_defaults, (setter)__Pyx_CyFunction_set_defaults, 0, 0}, + {"__kwdefaults__", (getter)__Pyx_CyFunction_get_kwdefaults, (setter)__Pyx_CyFunction_set_kwdefaults, 0, 0}, + {"__annotations__", (getter)__Pyx_CyFunction_get_annotations, (setter)__Pyx_CyFunction_set_annotations, 0, 0}, + {"_is_coroutine", (getter)__Pyx_CyFunction_get_is_coroutine, 0, 0, 0}, +#if CYTHON_COMPILING_IN_LIMITED_API + {"__module__", (getter)__Pyx_CyFunction_get_module, (setter)__Pyx_CyFunction_set_module, 0, 0}, +#endif + {0, 0, 0, 0, 0} +}; +static PyMemberDef __pyx_CyFunction_members[] = { +#if !CYTHON_COMPILING_IN_LIMITED_API + {"__module__", T_OBJECT, offsetof(PyCFunctionObject, m_module), 0, 0}, +#endif +#if PY_VERSION_HEX < 0x030C0000 || CYTHON_COMPILING_IN_LIMITED_API + {"__dictoffset__", T_PYSSIZET, offsetof(__pyx_CyFunctionObject, func_dict), READONLY, 0}, +#endif +#if CYTHON_METH_FASTCALL +#if CYTHON_COMPILING_IN_LIMITED_API + {"__vectorcalloffset__", T_PYSSIZET, offsetof(__pyx_CyFunctionObject, func_vectorcall), READONLY, 0}, +#else + {"__vectorcalloffset__", T_PYSSIZET, offsetof(PyCFunctionObject, vectorcall), READONLY, 0}, +#endif +#if CYTHON_COMPILING_IN_LIMITED_API + {"__weaklistoffset__", T_PYSSIZET, offsetof(__pyx_CyFunctionObject, func_weakreflist), READONLY, 0}, +#else + {"__weaklistoffset__", T_PYSSIZET, offsetof(PyCFunctionObject, m_weakreflist), READONLY, 0}, +#endif +#endif + {0, 0, 0, 0, 0} +}; +static PyObject * +__Pyx_CyFunction_reduce(__pyx_CyFunctionObject *m, PyObject *args) +{ + PyObject *result = NULL; + CYTHON_UNUSED_VAR(args); + __Pyx_BEGIN_CRITICAL_SECTION(m); + Py_INCREF(m->func_qualname); + result = m->func_qualname; + __Pyx_END_CRITICAL_SECTION(); + return result; +} +static PyMethodDef __pyx_CyFunction_methods[] = { + {"__reduce__", (PyCFunction)__Pyx_CyFunction_reduce, METH_VARARGS, 0}, + {0, 0, 0, 0} +}; +#if CYTHON_COMPILING_IN_LIMITED_API +#define __Pyx_CyFunction_weakreflist(cyfunc) ((cyfunc)->func_weakreflist) +#else +#define __Pyx_CyFunction_weakreflist(cyfunc) (((PyCFunctionObject*)cyfunc)->m_weakreflist) +#endif +static PyObject *__Pyx_CyFunction_Init(__pyx_CyFunctionObject *op, PyMethodDef *ml, int flags, PyObject* qualname, + PyObject *closure, PyObject *module, PyObject* globals, PyObject* code) { +#if !CYTHON_COMPILING_IN_LIMITED_API + PyCFunctionObject *cf = (PyCFunctionObject*) op; +#endif + if (unlikely(op == NULL)) + return NULL; +#if CYTHON_COMPILING_IN_LIMITED_API + op->func = PyCFunction_NewEx(ml, (PyObject*)op, module); + if (unlikely(!op->func)) return NULL; +#endif + op->flags = flags; + __Pyx_CyFunction_weakreflist(op) = NULL; +#if !CYTHON_COMPILING_IN_LIMITED_API + cf->m_ml = ml; + cf->m_self = (PyObject *) op; +#endif + Py_XINCREF(closure); + op->func_closure = closure; +#if !CYTHON_COMPILING_IN_LIMITED_API + Py_XINCREF(module); + cf->m_module = module; +#endif +#if PY_VERSION_HEX < 0x030C0000 || CYTHON_COMPILING_IN_LIMITED_API + op->func_dict = NULL; +#endif + op->func_name = NULL; + Py_INCREF(qualname); + op->func_qualname = qualname; + op->func_doc = NULL; +#if PY_VERSION_HEX < 0x030900B1 || CYTHON_COMPILING_IN_LIMITED_API + op->func_classobj = NULL; +#else + ((PyCMethodObject*)op)->mm_class = NULL; +#endif + op->func_globals = globals; + Py_INCREF(op->func_globals); + Py_XINCREF(code); + op->func_code = code; + op->defaults = NULL; + op->defaults_tuple = NULL; + op->defaults_kwdict = NULL; + op->defaults_getter = NULL; + op->func_annotations = NULL; + op->func_is_coroutine = NULL; +#if CYTHON_METH_FASTCALL + switch (ml->ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O | METH_KEYWORDS | METH_METHOD)) { + case METH_NOARGS: + __Pyx_CyFunction_func_vectorcall(op) = __Pyx_CyFunction_Vectorcall_NOARGS; + break; + case METH_O: + __Pyx_CyFunction_func_vectorcall(op) = __Pyx_CyFunction_Vectorcall_O; + break; + case METH_METHOD | METH_FASTCALL | METH_KEYWORDS: + __Pyx_CyFunction_func_vectorcall(op) = __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS_METHOD; + break; + case METH_FASTCALL | METH_KEYWORDS: + __Pyx_CyFunction_func_vectorcall(op) = __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS; + break; + case METH_VARARGS | METH_KEYWORDS: + __Pyx_CyFunction_func_vectorcall(op) = NULL; + break; + default: + PyErr_SetString(PyExc_SystemError, "Bad call flags for CyFunction"); + Py_DECREF(op); + return NULL; + } +#endif + return (PyObject *) op; +} +static int +__Pyx_CyFunction_clear(__pyx_CyFunctionObject *m) +{ + Py_CLEAR(m->func_closure); +#if CYTHON_COMPILING_IN_LIMITED_API + Py_CLEAR(m->func); +#else + Py_CLEAR(((PyCFunctionObject*)m)->m_module); +#endif +#if PY_VERSION_HEX < 0x030C0000 || CYTHON_COMPILING_IN_LIMITED_API + Py_CLEAR(m->func_dict); +#elif PY_VERSION_HEX < 0x030d0000 + _PyObject_ClearManagedDict((PyObject*)m); +#else + PyObject_ClearManagedDict((PyObject*)m); +#endif + Py_CLEAR(m->func_name); + Py_CLEAR(m->func_qualname); + Py_CLEAR(m->func_doc); + Py_CLEAR(m->func_globals); + Py_CLEAR(m->func_code); +#if !CYTHON_COMPILING_IN_LIMITED_API +#if PY_VERSION_HEX < 0x030900B1 + Py_CLEAR(__Pyx_CyFunction_GetClassObj(m)); +#else + { + PyObject *cls = (PyObject*) ((PyCMethodObject *) (m))->mm_class; + ((PyCMethodObject *) (m))->mm_class = NULL; + Py_XDECREF(cls); + } +#endif +#endif + Py_CLEAR(m->defaults_tuple); + Py_CLEAR(m->defaults_kwdict); + Py_CLEAR(m->func_annotations); + Py_CLEAR(m->func_is_coroutine); + Py_CLEAR(m->defaults); + return 0; +} +static void __Pyx__CyFunction_dealloc(__pyx_CyFunctionObject *m) +{ + if (__Pyx_CyFunction_weakreflist(m) != NULL) + PyObject_ClearWeakRefs((PyObject *) m); + __Pyx_CyFunction_clear(m); + __Pyx_PyHeapTypeObject_GC_Del(m); +} +static void __Pyx_CyFunction_dealloc(__pyx_CyFunctionObject *m) +{ + PyObject_GC_UnTrack(m); + __Pyx__CyFunction_dealloc(m); +} +static int __Pyx_CyFunction_traverse(__pyx_CyFunctionObject *m, visitproc visit, void *arg) +{ + { + int e = __Pyx_call_type_traverse((PyObject*)m, 1, visit, arg); + if (e) return e; + } + Py_VISIT(m->func_closure); +#if CYTHON_COMPILING_IN_LIMITED_API + Py_VISIT(m->func); +#else + Py_VISIT(((PyCFunctionObject*)m)->m_module); +#endif +#if PY_VERSION_HEX < 0x030C0000 || CYTHON_COMPILING_IN_LIMITED_API + Py_VISIT(m->func_dict); +#else + { + int e = +#if PY_VERSION_HEX < 0x030d0000 + _PyObject_VisitManagedDict +#else + PyObject_VisitManagedDict +#endif + ((PyObject*)m, visit, arg); + if (e != 0) return e; + } +#endif + __Pyx_VISIT_CONST(m->func_name); + __Pyx_VISIT_CONST(m->func_qualname); + Py_VISIT(m->func_doc); + Py_VISIT(m->func_globals); + __Pyx_VISIT_CONST(m->func_code); +#if !CYTHON_COMPILING_IN_LIMITED_API + Py_VISIT(__Pyx_CyFunction_GetClassObj(m)); +#endif + Py_VISIT(m->defaults_tuple); + Py_VISIT(m->defaults_kwdict); + Py_VISIT(m->func_is_coroutine); + Py_VISIT(m->defaults); + return 0; +} +static PyObject* +__Pyx_CyFunction_repr(__pyx_CyFunctionObject *op) +{ + PyObject *repr; + __Pyx_BEGIN_CRITICAL_SECTION(op); + repr = PyUnicode_FromFormat("", + op->func_qualname, (void *)op); + __Pyx_END_CRITICAL_SECTION(); + return repr; +} +static PyObject * __Pyx_CyFunction_CallMethod(PyObject *func, PyObject *self, PyObject *arg, PyObject *kw) { +#if CYTHON_COMPILING_IN_LIMITED_API + PyObject *f = ((__pyx_CyFunctionObject*)func)->func; + PyCFunction meth; + int flags; + meth = PyCFunction_GetFunction(f); + if (unlikely(!meth)) return NULL; + flags = PyCFunction_GetFlags(f); + if (unlikely(flags < 0)) return NULL; +#else + PyCFunctionObject* f = (PyCFunctionObject*)func; + PyCFunction meth = f->m_ml->ml_meth; + int flags = f->m_ml->ml_flags; +#endif + Py_ssize_t size; + switch (flags & (METH_VARARGS | METH_KEYWORDS | METH_NOARGS | METH_O)) { + case METH_VARARGS: + if (likely(kw == NULL || PyDict_Size(kw) == 0)) + return (*meth)(self, arg); + break; + case METH_VARARGS | METH_KEYWORDS: + return (*(PyCFunctionWithKeywords)(void(*)(void))meth)(self, arg, kw); + case METH_NOARGS: + if (likely(kw == NULL || PyDict_Size(kw) == 0)) { +#if CYTHON_ASSUME_SAFE_SIZE + size = PyTuple_GET_SIZE(arg); +#else + size = PyTuple_Size(arg); + if (unlikely(size < 0)) return NULL; +#endif + if (likely(size == 0)) + return (*meth)(self, NULL); + __Pyx_CyFunction_raise_argument_count_error( + (__pyx_CyFunctionObject*)func, + "takes no arguments", size); + return NULL; + } + break; + case METH_O: + if (likely(kw == NULL || PyDict_Size(kw) == 0)) { +#if CYTHON_ASSUME_SAFE_SIZE + size = PyTuple_GET_SIZE(arg); +#else + size = PyTuple_Size(arg); + if (unlikely(size < 0)) return NULL; +#endif + if (likely(size == 1)) { + PyObject *result, *arg0; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + arg0 = PyTuple_GET_ITEM(arg, 0); + #else + arg0 = __Pyx_PySequence_ITEM(arg, 0); if (unlikely(!arg0)) return NULL; + #endif + result = (*meth)(self, arg0); + #if !(CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS) + Py_DECREF(arg0); + #endif + return result; + } + __Pyx_CyFunction_raise_argument_count_error( + (__pyx_CyFunctionObject*)func, + "takes exactly one argument", size); + return NULL; + } + break; + default: + PyErr_SetString(PyExc_SystemError, "Bad call flags for CyFunction"); + return NULL; + } + __Pyx_CyFunction_raise_type_error( + (__pyx_CyFunctionObject*)func, "takes no keyword arguments"); + return NULL; +} +static CYTHON_INLINE PyObject *__Pyx_CyFunction_Call(PyObject *func, PyObject *arg, PyObject *kw) { + PyObject *self, *result; +#if CYTHON_COMPILING_IN_LIMITED_API + self = PyCFunction_GetSelf(((__pyx_CyFunctionObject*)func)->func); + if (unlikely(!self) && PyErr_Occurred()) return NULL; +#else + self = ((PyCFunctionObject*)func)->m_self; +#endif + result = __Pyx_CyFunction_CallMethod(func, self, arg, kw); + return result; +} +static PyObject *__Pyx_CyFunction_CallAsMethod(PyObject *func, PyObject *args, PyObject *kw) { + PyObject *result; + __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *) func; +#if CYTHON_METH_FASTCALL && CYTHON_VECTORCALL + __pyx_vectorcallfunc vc = __Pyx_CyFunction_func_vectorcall(cyfunc); + if (vc) { +#if CYTHON_ASSUME_SAFE_MACROS && CYTHON_ASSUME_SAFE_SIZE + return __Pyx_PyVectorcall_FastCallDict(func, vc, &PyTuple_GET_ITEM(args, 0), (size_t)PyTuple_GET_SIZE(args), kw); +#else + (void) &__Pyx_PyVectorcall_FastCallDict; + return PyVectorcall_Call(func, args, kw); +#endif + } +#endif + if ((cyfunc->flags & __Pyx_CYFUNCTION_CCLASS) && !(cyfunc->flags & __Pyx_CYFUNCTION_STATICMETHOD)) { + Py_ssize_t argc; + PyObject *new_args; + PyObject *self; +#if CYTHON_ASSUME_SAFE_SIZE + argc = PyTuple_GET_SIZE(args); +#else + argc = PyTuple_Size(args); + if (unlikely(argc < 0)) return NULL; +#endif + new_args = PyTuple_GetSlice(args, 1, argc); + if (unlikely(!new_args)) + return NULL; + self = PyTuple_GetItem(args, 0); + if (unlikely(!self)) { + Py_DECREF(new_args); + PyErr_Format(PyExc_TypeError, + "unbound method %.200S() needs an argument", + cyfunc->func_qualname); + return NULL; + } + result = __Pyx_CyFunction_CallMethod(func, self, new_args, kw); + Py_DECREF(new_args); + } else { + result = __Pyx_CyFunction_Call(func, args, kw); + } + return result; +} +#if CYTHON_METH_FASTCALL && CYTHON_VECTORCALL +static CYTHON_INLINE int __Pyx_CyFunction_Vectorcall_CheckArgs(__pyx_CyFunctionObject *cyfunc, Py_ssize_t nargs, PyObject *kwnames) +{ + int ret = 0; + if ((cyfunc->flags & __Pyx_CYFUNCTION_CCLASS) && !(cyfunc->flags & __Pyx_CYFUNCTION_STATICMETHOD)) { + if (unlikely(nargs < 1)) { + __Pyx_CyFunction_raise_type_error( + cyfunc, "needs an argument"); + return -1; + } + ret = 1; + } + if (unlikely(kwnames) && unlikely(__Pyx_PyTuple_GET_SIZE(kwnames))) { + __Pyx_CyFunction_raise_type_error( + cyfunc, "takes no keyword arguments"); + return -1; + } + return ret; +} +static PyObject * __Pyx_CyFunction_Vectorcall_NOARGS(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) +{ + __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *)func; + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + PyObject *self; +#if CYTHON_COMPILING_IN_LIMITED_API + PyCFunction meth = PyCFunction_GetFunction(cyfunc->func); + if (unlikely(!meth)) return NULL; +#else + PyCFunction meth = ((PyCFunctionObject*)cyfunc)->m_ml->ml_meth; +#endif + switch (__Pyx_CyFunction_Vectorcall_CheckArgs(cyfunc, nargs, kwnames)) { + case 1: + self = args[0]; + args += 1; + nargs -= 1; + break; + case 0: +#if CYTHON_COMPILING_IN_LIMITED_API + self = PyCFunction_GetSelf(((__pyx_CyFunctionObject*)cyfunc)->func); + if (unlikely(!self) && PyErr_Occurred()) return NULL; +#else + self = ((PyCFunctionObject*)cyfunc)->m_self; +#endif + break; + default: + return NULL; + } + if (unlikely(nargs != 0)) { + __Pyx_CyFunction_raise_argument_count_error( + cyfunc, "takes no arguments", nargs); + return NULL; + } + return meth(self, NULL); +} +static PyObject * __Pyx_CyFunction_Vectorcall_O(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) +{ + __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *)func; + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + PyObject *self; +#if CYTHON_COMPILING_IN_LIMITED_API + PyCFunction meth = PyCFunction_GetFunction(cyfunc->func); + if (unlikely(!meth)) return NULL; +#else + PyCFunction meth = ((PyCFunctionObject*)cyfunc)->m_ml->ml_meth; +#endif + switch (__Pyx_CyFunction_Vectorcall_CheckArgs(cyfunc, nargs, kwnames)) { + case 1: + self = args[0]; + args += 1; + nargs -= 1; + break; + case 0: +#if CYTHON_COMPILING_IN_LIMITED_API + self = PyCFunction_GetSelf(((__pyx_CyFunctionObject*)cyfunc)->func); + if (unlikely(!self) && PyErr_Occurred()) return NULL; +#else + self = ((PyCFunctionObject*)cyfunc)->m_self; +#endif + break; + default: + return NULL; + } + if (unlikely(nargs != 1)) { + __Pyx_CyFunction_raise_argument_count_error( + cyfunc, "takes exactly one argument", nargs); + return NULL; + } + return meth(self, args[0]); +} +static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) +{ + __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *)func; + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + PyObject *self; +#if CYTHON_COMPILING_IN_LIMITED_API + PyCFunction meth = PyCFunction_GetFunction(cyfunc->func); + if (unlikely(!meth)) return NULL; +#else + PyCFunction meth = ((PyCFunctionObject*)cyfunc)->m_ml->ml_meth; +#endif + switch (__Pyx_CyFunction_Vectorcall_CheckArgs(cyfunc, nargs, NULL)) { + case 1: + self = args[0]; + args += 1; + nargs -= 1; + break; + case 0: +#if CYTHON_COMPILING_IN_LIMITED_API + self = PyCFunction_GetSelf(((__pyx_CyFunctionObject*)cyfunc)->func); + if (unlikely(!self) && PyErr_Occurred()) return NULL; +#else + self = ((PyCFunctionObject*)cyfunc)->m_self; +#endif + break; + default: + return NULL; + } + return ((__Pyx_PyCFunctionFastWithKeywords)(void(*)(void))meth)(self, args, nargs, kwnames); +} +static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS_METHOD(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) +{ + __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *)func; + PyTypeObject *cls = (PyTypeObject *) __Pyx_CyFunction_GetClassObj(cyfunc); + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + PyObject *self; +#if CYTHON_COMPILING_IN_LIMITED_API + PyCFunction meth = PyCFunction_GetFunction(cyfunc->func); + if (unlikely(!meth)) return NULL; +#else + PyCFunction meth = ((PyCFunctionObject*)cyfunc)->m_ml->ml_meth; +#endif + switch (__Pyx_CyFunction_Vectorcall_CheckArgs(cyfunc, nargs, NULL)) { + case 1: + self = args[0]; + args += 1; + nargs -= 1; + break; + case 0: +#if CYTHON_COMPILING_IN_LIMITED_API + self = PyCFunction_GetSelf(((__pyx_CyFunctionObject*)cyfunc)->func); + if (unlikely(!self) && PyErr_Occurred()) return NULL; +#else + self = ((PyCFunctionObject*)cyfunc)->m_self; +#endif + break; + default: + return NULL; + } + #if PY_VERSION_HEX < 0x030e00A6 + size_t nargs_value = (size_t) nargs; + #else + Py_ssize_t nargs_value = nargs; + #endif + return ((__Pyx_PyCMethod)(void(*)(void))meth)(self, cls, args, nargs_value, kwnames); +} +#endif +static PyType_Slot __pyx_CyFunctionType_slots[] = { + {Py_tp_dealloc, (void *)__Pyx_CyFunction_dealloc}, + {Py_tp_repr, (void *)__Pyx_CyFunction_repr}, + {Py_tp_call, (void *)__Pyx_CyFunction_CallAsMethod}, + {Py_tp_traverse, (void *)__Pyx_CyFunction_traverse}, + {Py_tp_clear, (void *)__Pyx_CyFunction_clear}, + {Py_tp_methods, (void *)__pyx_CyFunction_methods}, + {Py_tp_members, (void *)__pyx_CyFunction_members}, + {Py_tp_getset, (void *)__pyx_CyFunction_getsets}, + {Py_tp_descr_get, (void *)__Pyx_PyMethod_New}, + {0, 0}, +}; +static PyType_Spec __pyx_CyFunctionType_spec = { + __PYX_TYPE_MODULE_PREFIX "cython_function_or_method", + sizeof(__pyx_CyFunctionObject), + 0, +#ifdef Py_TPFLAGS_METHOD_DESCRIPTOR + Py_TPFLAGS_METHOD_DESCRIPTOR | +#endif +#if CYTHON_METH_FASTCALL +#if defined(Py_TPFLAGS_HAVE_VECTORCALL) + Py_TPFLAGS_HAVE_VECTORCALL | +#elif defined(_Py_TPFLAGS_HAVE_VECTORCALL) + _Py_TPFLAGS_HAVE_VECTORCALL | +#endif +#endif // CYTHON_METH_FASTCALL +#if PY_VERSION_HEX >= 0x030C0000 && !CYTHON_COMPILING_IN_LIMITED_API + Py_TPFLAGS_MANAGED_DICT | +#endif + Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + __pyx_CyFunctionType_slots +}; +static int __pyx_CyFunction_init(PyObject *module) { + __pyx_mstatetype *mstate = __Pyx_PyModule_GetState(module); + mstate->__pyx_CyFunctionType = __Pyx_FetchCommonTypeFromSpec( + mstate->__pyx_CommonTypesMetaclassType, module, &__pyx_CyFunctionType_spec, NULL); + if (unlikely(mstate->__pyx_CyFunctionType == NULL)) { + return -1; + } + return 0; +} +static CYTHON_INLINE PyObject *__Pyx_CyFunction_InitDefaults(PyObject *func, PyTypeObject *defaults_type) { + __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func; + m->defaults = PyObject_CallObject((PyObject*)defaults_type, NULL); // _PyObject_New(defaults_type); + if (unlikely(!m->defaults)) + return NULL; + return m->defaults; +} +static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsTuple(PyObject *func, PyObject *tuple) { + __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func; + m->defaults_tuple = tuple; + Py_INCREF(tuple); +} +static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsKwDict(PyObject *func, PyObject *dict) { + __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func; + m->defaults_kwdict = dict; + Py_INCREF(dict); +} +static CYTHON_INLINE void __Pyx_CyFunction_SetAnnotationsDict(PyObject *func, PyObject *dict) { + __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func; + m->func_annotations = dict; + Py_INCREF(dict); +} + +/* CythonFunction */ +static PyObject *__Pyx_CyFunction_New(PyMethodDef *ml, int flags, PyObject* qualname, + PyObject *closure, PyObject *module, PyObject* globals, PyObject* code) { + PyObject *op = __Pyx_CyFunction_Init( + PyObject_GC_New(__pyx_CyFunctionObject, __pyx_mstate_global->__pyx_CyFunctionType), + ml, flags, qualname, closure, module, globals, code + ); + if (likely(op)) { + PyObject_GC_Track(op); + } + return op; +} + +/* PyDictVersioning */ +#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) { + PyObject *dict = Py_TYPE(obj)->tp_dict; + return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0; +} +static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) { + PyObject **dictptr = NULL; + Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset; + if (offset) { +#if CYTHON_COMPILING_IN_CPYTHON + dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj); +#else + dictptr = _PyObject_GetDictPtr(obj); +#endif + } + return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0; +} +static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) { + PyObject *dict = Py_TYPE(obj)->tp_dict; + if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict))) + return 0; + return obj_dict_version == __Pyx_get_object_dict_version(obj); +} +#endif + +/* PyErrExceptionMatches */ +#if CYTHON_FAST_THREAD_STATE +static int __Pyx_PyErr_ExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { + Py_ssize_t i, n; + n = PyTuple_GET_SIZE(tuple); + for (i=0; i= 0x030C00A6 + PyObject *current_exception = tstate->current_exception; + if (unlikely(!current_exception)) return 0; + exc_type = (PyObject*) Py_TYPE(current_exception); + if (exc_type == err) return 1; +#else + exc_type = tstate->curexc_type; + if (exc_type == err) return 1; + if (unlikely(!exc_type)) return 0; +#endif + #if CYTHON_AVOID_BORROWED_REFS + Py_INCREF(exc_type); + #endif + if (unlikely(PyTuple_Check(err))) { + result = __Pyx_PyErr_ExceptionMatchesTuple(exc_type, err); + } else { + result = __Pyx_PyErr_GivenExceptionMatches(exc_type, err); + } + #if CYTHON_AVOID_BORROWED_REFS + Py_DECREF(exc_type); + #endif + return result; +} +#endif + +/* PyObjectGetAttrStrNoError */ +#if __PYX_LIMITED_VERSION_HEX < 0x030d0000 +static void __Pyx_PyObject_GetAttrStr_ClearAttributeError(void) { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + if (likely(__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError))) + __Pyx_PyErr_Clear(); +} +#endif +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name) { + PyObject *result; +#if __PYX_LIMITED_VERSION_HEX >= 0x030d0000 + (void) PyObject_GetOptionalAttr(obj, attr_name, &result); + return result; +#else +#if CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_TYPE_SLOTS + PyTypeObject* tp = Py_TYPE(obj); + if (likely(tp->tp_getattro == PyObject_GenericGetAttr)) { + return _PyObject_GenericGetAttrWithDict(obj, attr_name, NULL, 1); + } +#endif + result = __Pyx_PyObject_GetAttrStr(obj, attr_name); + if (unlikely(!result)) { + __Pyx_PyObject_GetAttrStr_ClearAttributeError(); + } + return result; +#endif +} + +/* CLineInTraceback */ +#if CYTHON_CLINE_IN_TRACEBACK && CYTHON_CLINE_IN_TRACEBACK_RUNTIME +#if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030A0000 +#define __Pyx_PyProbablyModule_GetDict(o) __Pyx_XNewRef(PyModule_GetDict(o)) +#elif !CYTHON_COMPILING_IN_CPYTHON || CYTHON_COMPILING_IN_CPYTHON_FREETHREADING +#define __Pyx_PyProbablyModule_GetDict(o) PyObject_GenericGetDict(o, NULL); +#else +PyObject* __Pyx_PyProbablyModule_GetDict(PyObject *o) { + PyObject **dict_ptr = _PyObject_GetDictPtr(o); + return dict_ptr ? __Pyx_XNewRef(*dict_ptr) : NULL; +} +#endif +static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line) { + PyObject *use_cline = NULL; + PyObject *ptype, *pvalue, *ptraceback; + PyObject *cython_runtime_dict; + CYTHON_MAYBE_UNUSED_VAR(tstate); + if (unlikely(!__pyx_mstate_global->__pyx_cython_runtime)) { + return c_line; + } + __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); + cython_runtime_dict = __Pyx_PyProbablyModule_GetDict(__pyx_mstate_global->__pyx_cython_runtime); + if (likely(cython_runtime_dict)) { + __PYX_PY_DICT_LOOKUP_IF_MODIFIED( + use_cline, cython_runtime_dict, + __Pyx_PyDict_SetDefault(cython_runtime_dict, __pyx_mstate_global->__pyx_n_u_cline_in_traceback, Py_False)) + } + if (use_cline == NULL || use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { + c_line = 0; + } + Py_XDECREF(use_cline); + Py_XDECREF(cython_runtime_dict); + __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); + return c_line; +} +#endif + +/* CodeObjectCache */ +static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) { + int start = 0, mid = 0, end = count - 1; + if (end >= 0 && code_line > entries[end].code_line) { + return count; + } + while (start < end) { + mid = start + (end - start) / 2; + if (code_line < entries[mid].code_line) { + end = mid; + } else if (code_line > entries[mid].code_line) { + start = mid + 1; + } else { + return mid; + } + } + if (code_line <= entries[mid].code_line) { + return mid; + } else { + return mid + 1; + } +} +static __Pyx_CachedCodeObjectType *__pyx__find_code_object(struct __Pyx_CodeObjectCache *code_cache, int code_line) { + __Pyx_CachedCodeObjectType* code_object; + int pos; + if (unlikely(!code_line) || unlikely(!code_cache->entries)) { + return NULL; + } + pos = __pyx_bisect_code_objects(code_cache->entries, code_cache->count, code_line); + if (unlikely(pos >= code_cache->count) || unlikely(code_cache->entries[pos].code_line != code_line)) { + return NULL; + } + code_object = code_cache->entries[pos].code_object; + Py_INCREF(code_object); + return code_object; +} +static __Pyx_CachedCodeObjectType *__pyx_find_code_object(int code_line) { +#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING && !CYTHON_ATOMICS + (void)__pyx__find_code_object; + return NULL; // Most implementation should have atomics. But otherwise, don't make it thread-safe, just miss. +#else + struct __Pyx_CodeObjectCache *code_cache = &__pyx_mstate_global->__pyx_code_cache; +#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + __pyx_nonatomic_int_type old_count = __pyx_atomic_incr_acq_rel(&code_cache->accessor_count); + if (old_count < 0) { + __pyx_atomic_decr_acq_rel(&code_cache->accessor_count); + return NULL; + } +#endif + __Pyx_CachedCodeObjectType *result = __pyx__find_code_object(code_cache, code_line); +#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + __pyx_atomic_decr_acq_rel(&code_cache->accessor_count); +#endif + return result; +#endif +} +static void __pyx__insert_code_object(struct __Pyx_CodeObjectCache *code_cache, int code_line, __Pyx_CachedCodeObjectType* code_object) +{ + int pos, i; + __Pyx_CodeObjectCacheEntry* entries = code_cache->entries; + if (unlikely(!code_line)) { + return; + } + if (unlikely(!entries)) { + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry)); + if (likely(entries)) { + code_cache->entries = entries; + code_cache->max_count = 64; + code_cache->count = 1; + entries[0].code_line = code_line; + entries[0].code_object = code_object; + Py_INCREF(code_object); + } + return; + } + pos = __pyx_bisect_code_objects(code_cache->entries, code_cache->count, code_line); + if ((pos < code_cache->count) && unlikely(code_cache->entries[pos].code_line == code_line)) { + __Pyx_CachedCodeObjectType* tmp = entries[pos].code_object; + entries[pos].code_object = code_object; + Py_INCREF(code_object); + Py_DECREF(tmp); + return; + } + if (code_cache->count == code_cache->max_count) { + int new_max = code_cache->max_count + 64; + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc( + code_cache->entries, ((size_t)new_max) * sizeof(__Pyx_CodeObjectCacheEntry)); + if (unlikely(!entries)) { + return; + } + code_cache->entries = entries; + code_cache->max_count = new_max; + } + for (i=code_cache->count; i>pos; i--) { + entries[i] = entries[i-1]; + } + entries[pos].code_line = code_line; + entries[pos].code_object = code_object; + code_cache->count++; + Py_INCREF(code_object); +} +static void __pyx_insert_code_object(int code_line, __Pyx_CachedCodeObjectType* code_object) { +#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING && !CYTHON_ATOMICS + (void)__pyx__insert_code_object; + return; // Most implementation should have atomics. But otherwise, don't make it thread-safe, just fail. +#else + struct __Pyx_CodeObjectCache *code_cache = &__pyx_mstate_global->__pyx_code_cache; +#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + __pyx_nonatomic_int_type expected = 0; + if (!__pyx_atomic_int_cmp_exchange(&code_cache->accessor_count, &expected, INT_MIN)) { + return; + } +#endif + __pyx__insert_code_object(code_cache, code_line, code_object); +#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + __pyx_atomic_sub(&code_cache->accessor_count, INT_MIN); +#endif +#endif +} + +/* AddTraceback */ +#include "compile.h" +#include "frameobject.h" +#include "traceback.h" +#if PY_VERSION_HEX >= 0x030b00a6 && !CYTHON_COMPILING_IN_LIMITED_API && !defined(PYPY_VERSION) + #ifndef Py_BUILD_CORE + #define Py_BUILD_CORE 1 + #endif + #include "internal/pycore_frame.h" +#endif +#if CYTHON_COMPILING_IN_LIMITED_API +static PyObject *__Pyx_PyCode_Replace_For_AddTraceback(PyObject *code, PyObject *scratch_dict, + PyObject *firstlineno, PyObject *name) { + PyObject *replace = NULL; + if (unlikely(PyDict_SetItemString(scratch_dict, "co_firstlineno", firstlineno))) return NULL; + if (unlikely(PyDict_SetItemString(scratch_dict, "co_name", name))) return NULL; + replace = PyObject_GetAttrString(code, "replace"); + if (likely(replace)) { + PyObject *result = PyObject_Call(replace, __pyx_mstate_global->__pyx_empty_tuple, scratch_dict); + Py_DECREF(replace); + return result; + } + PyErr_Clear(); + return NULL; +} +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename) { + PyObject *code_object = NULL, *py_py_line = NULL, *py_funcname = NULL, *dict = NULL; + PyObject *replace = NULL, *getframe = NULL, *frame = NULL; + PyObject *exc_type, *exc_value, *exc_traceback; + int success = 0; + if (c_line) { + c_line = __Pyx_CLineForTraceback(__Pyx_PyThreadState_Current, c_line); + } + PyErr_Fetch(&exc_type, &exc_value, &exc_traceback); + code_object = __pyx_find_code_object(c_line ? -c_line : py_line); + if (!code_object) { + code_object = Py_CompileString("_getframe()", filename, Py_eval_input); + if (unlikely(!code_object)) goto bad; + py_py_line = PyLong_FromLong(py_line); + if (unlikely(!py_py_line)) goto bad; + if (c_line) { + py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + } else { + py_funcname = PyUnicode_FromString(funcname); + } + if (unlikely(!py_funcname)) goto bad; + dict = PyDict_New(); + if (unlikely(!dict)) goto bad; + { + PyObject *old_code_object = code_object; + code_object = __Pyx_PyCode_Replace_For_AddTraceback(code_object, dict, py_py_line, py_funcname); + Py_DECREF(old_code_object); + } + if (unlikely(!code_object)) goto bad; + __pyx_insert_code_object(c_line ? -c_line : py_line, code_object); + } else { + dict = PyDict_New(); + } + getframe = PySys_GetObject("_getframe"); + if (unlikely(!getframe)) goto bad; + if (unlikely(PyDict_SetItemString(dict, "_getframe", getframe))) goto bad; + frame = PyEval_EvalCode(code_object, dict, dict); + if (unlikely(!frame) || frame == Py_None) goto bad; + success = 1; + bad: + PyErr_Restore(exc_type, exc_value, exc_traceback); + Py_XDECREF(code_object); + Py_XDECREF(py_py_line); + Py_XDECREF(py_funcname); + Py_XDECREF(dict); + Py_XDECREF(replace); + if (success) { + PyTraceBack_Here( + (struct _frame*)frame); + } + Py_XDECREF(frame); +} +#else +static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( + const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = NULL; + PyObject *py_funcname = NULL; + if (c_line) { + py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + if (!py_funcname) goto bad; + funcname = PyUnicode_AsUTF8(py_funcname); + if (!funcname) goto bad; + } + py_code = PyCode_NewEmpty(filename, funcname, py_line); + Py_XDECREF(py_funcname); + return py_code; +bad: + Py_XDECREF(py_funcname); + return NULL; +} +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = 0; + PyFrameObject *py_frame = 0; + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject *ptype, *pvalue, *ptraceback; + if (c_line) { + c_line = __Pyx_CLineForTraceback(tstate, c_line); + } + py_code = __pyx_find_code_object(c_line ? -c_line : py_line); + if (!py_code) { + __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); + py_code = __Pyx_CreateCodeObjectForTraceback( + funcname, c_line, py_line, filename); + if (!py_code) { + /* If the code object creation fails, then we should clear the + fetched exception references and propagate the new exception */ + Py_XDECREF(ptype); + Py_XDECREF(pvalue); + Py_XDECREF(ptraceback); + goto bad; + } + __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); + __pyx_insert_code_object(c_line ? -c_line : py_line, py_code); + } + py_frame = PyFrame_New( + tstate, /*PyThreadState *tstate,*/ + py_code, /*PyCodeObject *code,*/ + __pyx_mstate_global->__pyx_d, /*PyObject *globals,*/ + 0 /*PyObject *locals*/ + ); + if (!py_frame) goto bad; + __Pyx_PyFrame_SetLineNumber(py_frame, py_line); + PyTraceBack_Here(py_frame); +bad: + Py_XDECREF(py_code); + Py_XDECREF(py_frame); +} +#endif + +/* PyObjectVectorCallKwBuilder */ +#if CYTHON_VECTORCALL +static int __Pyx_VectorcallBuilder_AddArg(PyObject *key, PyObject *value, PyObject *builder, PyObject **args, int n) { + (void)__Pyx_PyObject_FastCallDict; + if (__Pyx_PyTuple_SET_ITEM(builder, n, key) != (0)) return -1; + Py_INCREF(key); + args[n] = value; + return 0; +} +CYTHON_UNUSED static int __Pyx_VectorcallBuilder_AddArg_Check(PyObject *key, PyObject *value, PyObject *builder, PyObject **args, int n) { + (void)__Pyx_VectorcallBuilder_AddArgStr; + if (unlikely(!PyUnicode_Check(key))) { + PyErr_SetString(PyExc_TypeError, "keywords must be strings"); + return -1; + } + return __Pyx_VectorcallBuilder_AddArg(key, value, builder, args, n); +} +static int __Pyx_VectorcallBuilder_AddArgStr(const char *key, PyObject *value, PyObject *builder, PyObject **args, int n) { + PyObject *pyKey = PyUnicode_FromString(key); + if (!pyKey) return -1; + return __Pyx_VectorcallBuilder_AddArg(pyKey, value, builder, args, n); +} +#else // CYTHON_VECTORCALL +CYTHON_UNUSED static int __Pyx_VectorcallBuilder_AddArg_Check(PyObject *key, PyObject *value, PyObject *builder, CYTHON_UNUSED PyObject **args, CYTHON_UNUSED int n) { + if (unlikely(!PyUnicode_Check(key))) { + PyErr_SetString(PyExc_TypeError, "keywords must be strings"); + return -1; + } + return PyDict_SetItem(builder, key, value); +} +#endif + +/* CIntToPy */ +static CYTHON_INLINE PyObject* __Pyx_PyLong_From_uint64_t(uint64_t value) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const uint64_t neg_one = (uint64_t) -1, const_zero = (uint64_t) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(uint64_t) < sizeof(long)) { + return PyLong_FromLong((long) value); + } else if (sizeof(uint64_t) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); +#if !CYTHON_COMPILING_IN_PYPY + } else if (sizeof(uint64_t) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); +#endif + } + } else { + if (sizeof(uint64_t) <= sizeof(long)) { + return PyLong_FromLong((long) value); + } else if (sizeof(uint64_t) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); + } + } + { + unsigned char *bytes = (unsigned char *)&value; +#if !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x030d00A4 + if (is_unsigned) { + return PyLong_FromUnsignedNativeBytes(bytes, sizeof(value), -1); + } else { + return PyLong_FromNativeBytes(bytes, sizeof(value), -1); + } +#elif !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX < 0x030d0000 + int one = 1; int little = (int)*(unsigned char *)&one; + return _PyLong_FromByteArray(bytes, sizeof(uint64_t), + little, !is_unsigned); +#else + int one = 1; int little = (int)*(unsigned char *)&one; + PyObject *from_bytes, *result = NULL, *kwds = NULL; + PyObject *py_bytes = NULL, *order_str = NULL; + from_bytes = PyObject_GetAttrString((PyObject*)&PyLong_Type, "from_bytes"); + if (!from_bytes) return NULL; + py_bytes = PyBytes_FromStringAndSize((char*)bytes, sizeof(uint64_t)); + if (!py_bytes) goto limited_bad; + order_str = PyUnicode_FromString(little ? "little" : "big"); + if (!order_str) goto limited_bad; + { + PyObject *args[3+(CYTHON_VECTORCALL ? 1 : 0)] = { NULL, py_bytes, order_str }; + if (!is_unsigned) { + kwds = __Pyx_MakeVectorcallBuilderKwds(1); + if (!kwds) goto limited_bad; + if (__Pyx_VectorcallBuilder_AddArgStr("signed", __Pyx_NewRef(Py_True), kwds, args+3, 0) < 0) goto limited_bad; + } + result = __Pyx_Object_Vectorcall_CallFromBuilder(from_bytes, args+1, 2 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET, kwds); + } + limited_bad: + Py_XDECREF(kwds); + Py_XDECREF(order_str); + Py_XDECREF(py_bytes); + Py_XDECREF(from_bytes); + return result; +#endif + } +} + +/* FormatTypeName */ +#if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030d0000 +static __Pyx_TypeName +__Pyx_PyType_GetFullyQualifiedName(PyTypeObject* tp) +{ + PyObject *module = NULL, *name = NULL, *result = NULL; + #if __PYX_LIMITED_VERSION_HEX < 0x030b0000 + name = __Pyx_PyObject_GetAttrStr((PyObject *)tp, + __pyx_mstate_global->__pyx_n_u_qualname); + #else + name = PyType_GetQualName(tp); + #endif + if (unlikely(name == NULL) || unlikely(!PyUnicode_Check(name))) goto bad; + module = __Pyx_PyObject_GetAttrStr((PyObject *)tp, + __pyx_mstate_global->__pyx_n_u_module); + if (unlikely(module == NULL) || unlikely(!PyUnicode_Check(module))) goto bad; + if (PyUnicode_CompareWithASCIIString(module, "builtins") == 0) { + result = name; + name = NULL; + goto done; + } + result = PyUnicode_FromFormat("%U.%U", module, name); + if (unlikely(result == NULL)) goto bad; + done: + Py_XDECREF(name); + Py_XDECREF(module); + return result; + bad: + PyErr_Clear(); + if (name) { + result = name; + name = NULL; + } else { + result = __Pyx_NewRef(__pyx_mstate_global->__pyx_kp_u__2); + } + goto done; +} +#endif + +/* CIntToPy */ +static CYTHON_INLINE PyObject* __Pyx_PyLong_From_long(long value) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const long neg_one = (long) -1, const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(long) < sizeof(long)) { + return PyLong_FromLong((long) value); + } else if (sizeof(long) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); +#if !CYTHON_COMPILING_IN_PYPY + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); +#endif + } + } else { + if (sizeof(long) <= sizeof(long)) { + return PyLong_FromLong((long) value); + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); + } + } + { + unsigned char *bytes = (unsigned char *)&value; +#if !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x030d00A4 + if (is_unsigned) { + return PyLong_FromUnsignedNativeBytes(bytes, sizeof(value), -1); + } else { + return PyLong_FromNativeBytes(bytes, sizeof(value), -1); + } +#elif !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX < 0x030d0000 + int one = 1; int little = (int)*(unsigned char *)&one; + return _PyLong_FromByteArray(bytes, sizeof(long), + little, !is_unsigned); +#else + int one = 1; int little = (int)*(unsigned char *)&one; + PyObject *from_bytes, *result = NULL, *kwds = NULL; + PyObject *py_bytes = NULL, *order_str = NULL; + from_bytes = PyObject_GetAttrString((PyObject*)&PyLong_Type, "from_bytes"); + if (!from_bytes) return NULL; + py_bytes = PyBytes_FromStringAndSize((char*)bytes, sizeof(long)); + if (!py_bytes) goto limited_bad; + order_str = PyUnicode_FromString(little ? "little" : "big"); + if (!order_str) goto limited_bad; + { + PyObject *args[3+(CYTHON_VECTORCALL ? 1 : 0)] = { NULL, py_bytes, order_str }; + if (!is_unsigned) { + kwds = __Pyx_MakeVectorcallBuilderKwds(1); + if (!kwds) goto limited_bad; + if (__Pyx_VectorcallBuilder_AddArgStr("signed", __Pyx_NewRef(Py_True), kwds, args+3, 0) < 0) goto limited_bad; + } + result = __Pyx_Object_Vectorcall_CallFromBuilder(from_bytes, args+1, 2 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET, kwds); + } + limited_bad: + Py_XDECREF(kwds); + Py_XDECREF(order_str); + Py_XDECREF(py_bytes); + Py_XDECREF(from_bytes); + return result; +#endif + } +} + +/* CIntFromPyVerify */ +#define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0) +#define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1) +#define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc)\ + {\ + func_type value = func_value;\ + if (sizeof(target_type) < sizeof(func_type)) {\ + if (unlikely(value != (func_type) (target_type) value)) {\ + func_type zero = 0;\ + if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred()))\ + return (target_type) -1;\ + if (is_unsigned && unlikely(value < zero))\ + goto raise_neg_overflow;\ + else\ + goto raise_overflow;\ + }\ + }\ + return (target_type) value;\ + } + +/* CIntFromPy */ +static CYTHON_INLINE long __Pyx_PyLong_As_long(PyObject *x) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const long neg_one = (long) -1, const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (unlikely(!PyLong_Check(x))) { + long val; + PyObject *tmp = __Pyx_PyNumber_Long(x); + if (!tmp) return (long) -1; + val = __Pyx_PyLong_As_long(tmp); + Py_DECREF(tmp); + return val; + } + if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + if (unlikely(__Pyx_PyLong_IsNeg(x))) { + goto raise_neg_overflow; + } else if (__Pyx_PyLong_IsCompact(x)) { + __PYX_VERIFY_RETURN_INT(long, __Pyx_compact_upylong, __Pyx_PyLong_CompactValueUnsigned(x)) + } else { + const digit* digits = __Pyx_PyLong_Digits(x); + assert(__Pyx_PyLong_DigitCount(x) > 1); + switch (__Pyx_PyLong_DigitCount(x)) { + case 2: + if ((8 * sizeof(long) > 1 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(long) >= 2 * PyLong_SHIFT)) { + return (long) (((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 3: + if ((8 * sizeof(long) > 2 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(long) >= 3 * PyLong_SHIFT)) { + return (long) (((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 4: + if ((8 * sizeof(long) > 3 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(long) >= 4 * PyLong_SHIFT)) { + return (long) (((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + } + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030C00A7 + if (unlikely(Py_SIZE(x) < 0)) { + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (long) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if ((sizeof(long) <= sizeof(unsigned long))) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned long, PyLong_AsUnsignedLong(x)) + } else if ((sizeof(long) <= sizeof(unsigned PY_LONG_LONG))) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) + } + } else { +#if CYTHON_USE_PYLONG_INTERNALS + if (__Pyx_PyLong_IsCompact(x)) { + __PYX_VERIFY_RETURN_INT(long, __Pyx_compact_pylong, __Pyx_PyLong_CompactValue(x)) + } else { + const digit* digits = __Pyx_PyLong_Digits(x); + assert(__Pyx_PyLong_DigitCount(x) > 1); + switch (__Pyx_PyLong_SignedDigitCount(x)) { + case -2: + if ((8 * sizeof(long) - 1 > 1 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(long) - 1 > 2 * PyLong_SHIFT)) { + return (long) (((long)-1)*(((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 2: + if ((8 * sizeof(long) > 1 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(long) - 1 > 2 * PyLong_SHIFT)) { + return (long) ((((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -3: + if ((8 * sizeof(long) - 1 > 2 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(long) - 1 > 3 * PyLong_SHIFT)) { + return (long) (((long)-1)*(((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 3: + if ((8 * sizeof(long) > 2 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(long) - 1 > 3 * PyLong_SHIFT)) { + return (long) ((((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -4: + if ((8 * sizeof(long) - 1 > 3 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(long) - 1 > 4 * PyLong_SHIFT)) { + return (long) (((long)-1)*(((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 4: + if ((8 * sizeof(long) > 3 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(long) - 1 > 4 * PyLong_SHIFT)) { + return (long) ((((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + } + } +#endif + if ((sizeof(long) <= sizeof(long))) { + __PYX_VERIFY_RETURN_INT_EXC(long, long, PyLong_AsLong(x)) + } else if ((sizeof(long) <= sizeof(PY_LONG_LONG))) { + __PYX_VERIFY_RETURN_INT_EXC(long, PY_LONG_LONG, PyLong_AsLongLong(x)) + } + } + { + long val; + int ret = -1; +#if PY_VERSION_HEX >= 0x030d00A6 && !CYTHON_COMPILING_IN_LIMITED_API + Py_ssize_t bytes_copied = PyLong_AsNativeBytes( + x, &val, sizeof(val), Py_ASNATIVEBYTES_NATIVE_ENDIAN | (is_unsigned ? Py_ASNATIVEBYTES_UNSIGNED_BUFFER | Py_ASNATIVEBYTES_REJECT_NEGATIVE : 0)); + if (unlikely(bytes_copied == -1)) { + } else if (unlikely(bytes_copied > (Py_ssize_t) sizeof(val))) { + goto raise_overflow; + } else { + ret = 0; + } +#elif PY_VERSION_HEX < 0x030d0000 && !(CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_LIMITED_API) || defined(_PyLong_AsByteArray) + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + ret = _PyLong_AsByteArray((PyLongObject *)x, + bytes, sizeof(val), + is_little, !is_unsigned); +#else + PyObject *v; + PyObject *stepval = NULL, *mask = NULL, *shift = NULL; + int bits, remaining_bits, is_negative = 0; + int chunk_size = (sizeof(long) < 8) ? 30 : 62; + if (likely(PyLong_CheckExact(x))) { + v = __Pyx_NewRef(x); + } else { + v = PyNumber_Long(x); + if (unlikely(!v)) return (long) -1; + assert(PyLong_CheckExact(v)); + } + { + int result = PyObject_RichCompareBool(v, Py_False, Py_LT); + if (unlikely(result < 0)) { + Py_DECREF(v); + return (long) -1; + } + is_negative = result == 1; + } + if (is_unsigned && unlikely(is_negative)) { + Py_DECREF(v); + goto raise_neg_overflow; + } else if (is_negative) { + stepval = PyNumber_Invert(v); + Py_DECREF(v); + if (unlikely(!stepval)) + return (long) -1; + } else { + stepval = v; + } + v = NULL; + val = (long) 0; + mask = PyLong_FromLong((1L << chunk_size) - 1); if (unlikely(!mask)) goto done; + shift = PyLong_FromLong(chunk_size); if (unlikely(!shift)) goto done; + for (bits = 0; bits < (int) sizeof(long) * 8 - chunk_size; bits += chunk_size) { + PyObject *tmp, *digit; + long idigit; + digit = PyNumber_And(stepval, mask); + if (unlikely(!digit)) goto done; + idigit = PyLong_AsLong(digit); + Py_DECREF(digit); + if (unlikely(idigit < 0)) goto done; + val |= ((long) idigit) << bits; + tmp = PyNumber_Rshift(stepval, shift); + if (unlikely(!tmp)) goto done; + Py_DECREF(stepval); stepval = tmp; + } + Py_DECREF(shift); shift = NULL; + Py_DECREF(mask); mask = NULL; + { + long idigit = PyLong_AsLong(stepval); + if (unlikely(idigit < 0)) goto done; + remaining_bits = ((int) sizeof(long) * 8) - bits - (is_unsigned ? 0 : 1); + if (unlikely(idigit >= (1L << remaining_bits))) + goto raise_overflow; + val |= ((long) idigit) << bits; + } + if (!is_unsigned) { + if (unlikely(val & (((long) 1) << (sizeof(long) * 8 - 1)))) + goto raise_overflow; + if (is_negative) + val = ~val; + } + ret = 0; + done: + Py_XDECREF(shift); + Py_XDECREF(mask); + Py_XDECREF(stepval); +#endif + if (unlikely(ret)) + return (long) -1; + return val; + } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to long"); + return (long) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to long"); + return (long) -1; +} + +/* CIntFromPy */ +static CYTHON_INLINE int __Pyx_PyLong_As_int(PyObject *x) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const int neg_one = (int) -1, const_zero = (int) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (unlikely(!PyLong_Check(x))) { + int val; + PyObject *tmp = __Pyx_PyNumber_Long(x); + if (!tmp) return (int) -1; + val = __Pyx_PyLong_As_int(tmp); + Py_DECREF(tmp); + return val; + } + if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + if (unlikely(__Pyx_PyLong_IsNeg(x))) { + goto raise_neg_overflow; + } else if (__Pyx_PyLong_IsCompact(x)) { + __PYX_VERIFY_RETURN_INT(int, __Pyx_compact_upylong, __Pyx_PyLong_CompactValueUnsigned(x)) + } else { + const digit* digits = __Pyx_PyLong_Digits(x); + assert(__Pyx_PyLong_DigitCount(x) > 1); + switch (__Pyx_PyLong_DigitCount(x)) { + case 2: + if ((8 * sizeof(int) > 1 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(int) >= 2 * PyLong_SHIFT)) { + return (int) (((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 3: + if ((8 * sizeof(int) > 2 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(int) >= 3 * PyLong_SHIFT)) { + return (int) (((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 4: + if ((8 * sizeof(int) > 3 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(int) >= 4 * PyLong_SHIFT)) { + return (int) (((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + } + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030C00A7 + if (unlikely(Py_SIZE(x) < 0)) { + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (int) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if ((sizeof(int) <= sizeof(unsigned long))) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned long, PyLong_AsUnsignedLong(x)) + } else if ((sizeof(int) <= sizeof(unsigned PY_LONG_LONG))) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) + } + } else { +#if CYTHON_USE_PYLONG_INTERNALS + if (__Pyx_PyLong_IsCompact(x)) { + __PYX_VERIFY_RETURN_INT(int, __Pyx_compact_pylong, __Pyx_PyLong_CompactValue(x)) + } else { + const digit* digits = __Pyx_PyLong_Digits(x); + assert(__Pyx_PyLong_DigitCount(x) > 1); + switch (__Pyx_PyLong_SignedDigitCount(x)) { + case -2: + if ((8 * sizeof(int) - 1 > 1 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(int) - 1 > 2 * PyLong_SHIFT)) { + return (int) (((int)-1)*(((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 2: + if ((8 * sizeof(int) > 1 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(int) - 1 > 2 * PyLong_SHIFT)) { + return (int) ((((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -3: + if ((8 * sizeof(int) - 1 > 2 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(int) - 1 > 3 * PyLong_SHIFT)) { + return (int) (((int)-1)*(((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 3: + if ((8 * sizeof(int) > 2 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(int) - 1 > 3 * PyLong_SHIFT)) { + return (int) ((((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -4: + if ((8 * sizeof(int) - 1 > 3 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(int) - 1 > 4 * PyLong_SHIFT)) { + return (int) (((int)-1)*(((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 4: + if ((8 * sizeof(int) > 3 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(int) - 1 > 4 * PyLong_SHIFT)) { + return (int) ((((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + } + } +#endif + if ((sizeof(int) <= sizeof(long))) { + __PYX_VERIFY_RETURN_INT_EXC(int, long, PyLong_AsLong(x)) + } else if ((sizeof(int) <= sizeof(PY_LONG_LONG))) { + __PYX_VERIFY_RETURN_INT_EXC(int, PY_LONG_LONG, PyLong_AsLongLong(x)) + } + } + { + int val; + int ret = -1; +#if PY_VERSION_HEX >= 0x030d00A6 && !CYTHON_COMPILING_IN_LIMITED_API + Py_ssize_t bytes_copied = PyLong_AsNativeBytes( + x, &val, sizeof(val), Py_ASNATIVEBYTES_NATIVE_ENDIAN | (is_unsigned ? Py_ASNATIVEBYTES_UNSIGNED_BUFFER | Py_ASNATIVEBYTES_REJECT_NEGATIVE : 0)); + if (unlikely(bytes_copied == -1)) { + } else if (unlikely(bytes_copied > (Py_ssize_t) sizeof(val))) { + goto raise_overflow; + } else { + ret = 0; + } +#elif PY_VERSION_HEX < 0x030d0000 && !(CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_LIMITED_API) || defined(_PyLong_AsByteArray) + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + ret = _PyLong_AsByteArray((PyLongObject *)x, + bytes, sizeof(val), + is_little, !is_unsigned); +#else + PyObject *v; + PyObject *stepval = NULL, *mask = NULL, *shift = NULL; + int bits, remaining_bits, is_negative = 0; + int chunk_size = (sizeof(long) < 8) ? 30 : 62; + if (likely(PyLong_CheckExact(x))) { + v = __Pyx_NewRef(x); + } else { + v = PyNumber_Long(x); + if (unlikely(!v)) return (int) -1; + assert(PyLong_CheckExact(v)); + } + { + int result = PyObject_RichCompareBool(v, Py_False, Py_LT); + if (unlikely(result < 0)) { + Py_DECREF(v); + return (int) -1; + } + is_negative = result == 1; + } + if (is_unsigned && unlikely(is_negative)) { + Py_DECREF(v); + goto raise_neg_overflow; + } else if (is_negative) { + stepval = PyNumber_Invert(v); + Py_DECREF(v); + if (unlikely(!stepval)) + return (int) -1; + } else { + stepval = v; + } + v = NULL; + val = (int) 0; + mask = PyLong_FromLong((1L << chunk_size) - 1); if (unlikely(!mask)) goto done; + shift = PyLong_FromLong(chunk_size); if (unlikely(!shift)) goto done; + for (bits = 0; bits < (int) sizeof(int) * 8 - chunk_size; bits += chunk_size) { + PyObject *tmp, *digit; + long idigit; + digit = PyNumber_And(stepval, mask); + if (unlikely(!digit)) goto done; + idigit = PyLong_AsLong(digit); + Py_DECREF(digit); + if (unlikely(idigit < 0)) goto done; + val |= ((int) idigit) << bits; + tmp = PyNumber_Rshift(stepval, shift); + if (unlikely(!tmp)) goto done; + Py_DECREF(stepval); stepval = tmp; + } + Py_DECREF(shift); shift = NULL; + Py_DECREF(mask); mask = NULL; + { + long idigit = PyLong_AsLong(stepval); + if (unlikely(idigit < 0)) goto done; + remaining_bits = ((int) sizeof(int) * 8) - bits - (is_unsigned ? 0 : 1); + if (unlikely(idigit >= (1L << remaining_bits))) + goto raise_overflow; + val |= ((int) idigit) << bits; + } + if (!is_unsigned) { + if (unlikely(val & (((int) 1) << (sizeof(int) * 8 - 1)))) + goto raise_overflow; + if (is_negative) + val = ~val; + } + ret = 0; + done: + Py_XDECREF(shift); + Py_XDECREF(mask); + Py_XDECREF(stepval); +#endif + if (unlikely(ret)) + return (int) -1; + return val; + } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to int"); + return (int) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to int"); + return (int) -1; +} + +/* FastTypeChecks */ +#if CYTHON_COMPILING_IN_CPYTHON +static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) { + while (a) { + a = __Pyx_PyType_GetSlot(a, tp_base, PyTypeObject*); + if (a == b) + return 1; + } + return b == &PyBaseObject_Type; +} +static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) { + PyObject *mro; + if (a == b) return 1; + mro = a->tp_mro; + if (likely(mro)) { + Py_ssize_t i, n; + n = PyTuple_GET_SIZE(mro); + for (i = 0; i < n; i++) { + if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b) + return 1; + } + return 0; + } + return __Pyx_InBases(a, b); +} +static CYTHON_INLINE int __Pyx_IsAnySubtype2(PyTypeObject *cls, PyTypeObject *a, PyTypeObject *b) { + PyObject *mro; + if (cls == a || cls == b) return 1; + mro = cls->tp_mro; + if (likely(mro)) { + Py_ssize_t i, n; + n = PyTuple_GET_SIZE(mro); + for (i = 0; i < n; i++) { + PyObject *base = PyTuple_GET_ITEM(mro, i); + if (base == (PyObject *)a || base == (PyObject *)b) + return 1; + } + return 0; + } + return __Pyx_InBases(cls, a) || __Pyx_InBases(cls, b); +} +static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject *exc_type2) { + if (exc_type1) { + return __Pyx_IsAnySubtype2((PyTypeObject*)err, (PyTypeObject*)exc_type1, (PyTypeObject*)exc_type2); + } else { + return __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2); + } +} +static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { + Py_ssize_t i, n; + assert(PyExceptionClass_Check(exc_type)); + n = PyTuple_GET_SIZE(tuple); + for (i=0; i>= 8; + ++i; + } + __Pyx_cached_runtime_version = version; + } +} +#endif +static unsigned long __Pyx_get_runtime_version(void) { +#if __PYX_LIMITED_VERSION_HEX >= 0x030b0000 + return Py_Version & ~0xFFUL; +#else + return __Pyx_cached_runtime_version; +#endif +} + +/* CheckBinaryVersion */ +static int __Pyx_check_binary_version(unsigned long ct_version, unsigned long rt_version, int allow_newer) { + const unsigned long MAJOR_MINOR = 0xFFFF0000UL; + if ((rt_version & MAJOR_MINOR) == (ct_version & MAJOR_MINOR)) + return 0; + if (likely(allow_newer && (rt_version & MAJOR_MINOR) > (ct_version & MAJOR_MINOR))) + return 1; + { + char message[200]; + PyOS_snprintf(message, sizeof(message), + "compile time Python version %d.%d " + "of module '%.100s' " + "%s " + "runtime version %d.%d", + (int) (ct_version >> 24), (int) ((ct_version >> 16) & 0xFF), + __Pyx_MODULE_NAME, + (allow_newer) ? "was newer than" : "does not match", + (int) (rt_version >> 24), (int) ((rt_version >> 16) & 0xFF) + ); + return PyErr_WarnEx(NULL, message, 1); + } +} + +/* NewCodeObj */ +#if CYTHON_COMPILING_IN_LIMITED_API + static PyObject* __Pyx__PyCode_New(int a, int p, int k, int l, int s, int f, + PyObject *code, PyObject *c, PyObject* n, PyObject *v, + PyObject *fv, PyObject *cell, PyObject* fn, + PyObject *name, int fline, PyObject *lnos) { + PyObject *exception_table = NULL; + PyObject *types_module=NULL, *code_type=NULL, *result=NULL; + #if __PYX_LIMITED_VERSION_HEX < 0x030b0000 + PyObject *version_info; + PyObject *py_minor_version = NULL; + #endif + long minor_version = 0; + PyObject *type, *value, *traceback; + PyErr_Fetch(&type, &value, &traceback); + #if __PYX_LIMITED_VERSION_HEX >= 0x030b0000 + minor_version = 11; + #else + if (!(version_info = PySys_GetObject("version_info"))) goto end; + if (!(py_minor_version = PySequence_GetItem(version_info, 1))) goto end; + minor_version = PyLong_AsLong(py_minor_version); + Py_DECREF(py_minor_version); + if (minor_version == -1 && PyErr_Occurred()) goto end; + #endif + if (!(types_module = PyImport_ImportModule("types"))) goto end; + if (!(code_type = PyObject_GetAttrString(types_module, "CodeType"))) goto end; + if (minor_version <= 7) { + (void)p; + result = PyObject_CallFunction(code_type, "iiiiiOOOOOOiOOO", a, k, l, s, f, code, + c, n, v, fn, name, fline, lnos, fv, cell); + } else if (minor_version <= 10) { + result = PyObject_CallFunction(code_type, "iiiiiiOOOOOOiOOO", a,p, k, l, s, f, code, + c, n, v, fn, name, fline, lnos, fv, cell); + } else { + if (!(exception_table = PyBytes_FromStringAndSize(NULL, 0))) goto end; + result = PyObject_CallFunction(code_type, "iiiiiiOOOOOOOiOOOO", a,p, k, l, s, f, code, + c, n, v, fn, name, name, fline, lnos, exception_table, fv, cell); + } + end: + Py_XDECREF(code_type); + Py_XDECREF(exception_table); + Py_XDECREF(types_module); + if (type) { + PyErr_Restore(type, value, traceback); + } + return result; + } +#elif PY_VERSION_HEX >= 0x030B0000 + static PyCodeObject* __Pyx__PyCode_New(int a, int p, int k, int l, int s, int f, + PyObject *code, PyObject *c, PyObject* n, PyObject *v, + PyObject *fv, PyObject *cell, PyObject* fn, + PyObject *name, int fline, PyObject *lnos) { + PyCodeObject *result; + result = + #if PY_VERSION_HEX >= 0x030C0000 + PyUnstable_Code_NewWithPosOnlyArgs + #else + PyCode_NewWithPosOnlyArgs + #endif + (a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, name, fline, lnos, __pyx_mstate_global->__pyx_empty_bytes); + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030c00A1 + if (likely(result)) + result->_co_firsttraceable = 0; + #endif + return result; + } +#elif !CYTHON_COMPILING_IN_PYPY + #define __Pyx__PyCode_New(a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_NewWithPosOnlyArgs(a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) +#else + #define __Pyx__PyCode_New(a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) +#endif +static PyObject* __Pyx_PyCode_New( + const __Pyx_PyCode_New_function_description descr, + PyObject * const *varnames, + PyObject *filename, + PyObject *funcname, + PyObject *line_table, + PyObject *tuple_dedup_map +) { + PyObject *code_obj = NULL, *varnames_tuple_dedup = NULL, *code_bytes = NULL; + Py_ssize_t var_count = (Py_ssize_t) descr.nlocals; + PyObject *varnames_tuple = PyTuple_New(var_count); + if (unlikely(!varnames_tuple)) return NULL; + for (Py_ssize_t i=0; i < var_count; i++) { + Py_INCREF(varnames[i]); + if (__Pyx_PyTuple_SET_ITEM(varnames_tuple, i, varnames[i]) != (0)) goto done; + } + #if CYTHON_COMPILING_IN_LIMITED_API + varnames_tuple_dedup = PyDict_GetItem(tuple_dedup_map, varnames_tuple); + if (!varnames_tuple_dedup) { + if (unlikely(PyDict_SetItem(tuple_dedup_map, varnames_tuple, varnames_tuple) < 0)) goto done; + varnames_tuple_dedup = varnames_tuple; + } + #else + varnames_tuple_dedup = PyDict_SetDefault(tuple_dedup_map, varnames_tuple, varnames_tuple); + if (unlikely(!varnames_tuple_dedup)) goto done; + #endif + #if CYTHON_AVOID_BORROWED_REFS + Py_INCREF(varnames_tuple_dedup); + #endif + if (__PYX_LIMITED_VERSION_HEX >= (0x030b0000) && line_table != NULL && !CYTHON_COMPILING_IN_GRAAL) { + Py_ssize_t line_table_length = __Pyx_PyBytes_GET_SIZE(line_table); + #if !CYTHON_ASSUME_SAFE_SIZE + if (unlikely(line_table_length == -1)) goto done; + #endif + Py_ssize_t code_len = (line_table_length * 2 + 4) & ~3LL; + code_bytes = PyBytes_FromStringAndSize(NULL, code_len); + if (unlikely(!code_bytes)) goto done; + char* c_code_bytes = PyBytes_AsString(code_bytes); + if (unlikely(!c_code_bytes)) goto done; + memset(c_code_bytes, 0, (size_t) code_len); + } + code_obj = (PyObject*) __Pyx__PyCode_New( + (int) descr.argcount, + (int) descr.num_posonly_args, + (int) descr.num_kwonly_args, + (int) descr.nlocals, + 0, + (int) descr.flags, + code_bytes ? code_bytes : __pyx_mstate_global->__pyx_empty_bytes, + __pyx_mstate_global->__pyx_empty_tuple, + __pyx_mstate_global->__pyx_empty_tuple, + varnames_tuple_dedup, + __pyx_mstate_global->__pyx_empty_tuple, + __pyx_mstate_global->__pyx_empty_tuple, + filename, + funcname, + (int) descr.first_line, + (__PYX_LIMITED_VERSION_HEX >= (0x030b0000) && line_table) ? line_table : __pyx_mstate_global->__pyx_empty_bytes + ); +done: + Py_XDECREF(code_bytes); + #if CYTHON_AVOID_BORROWED_REFS + Py_XDECREF(varnames_tuple_dedup); + #endif + Py_DECREF(varnames_tuple); + return code_obj; +} + +/* DecompressString */ +static PyObject *__Pyx_DecompressString(const char *s, Py_ssize_t length, int algo) { + PyObject *module, *decompress, *compressed_bytes, *decompressed; + const char* module_name = algo == 3 ? "compression.zstd" : algo == 2 ? "bz2" : "zlib"; + PyObject *methodname = PyUnicode_FromString("decompress"); + if (unlikely(!methodname)) return NULL; + #if __PYX_LIMITED_VERSION_HEX >= 0x030e0000 + if (algo == 3) { + PyObject *fromlist = Py_BuildValue("[O]", methodname); + if (unlikely(!fromlist)) return NULL; + module = PyImport_ImportModuleLevel("compression.zstd", NULL, NULL, fromlist, 0); + Py_DECREF(fromlist); + } else + #endif + module = PyImport_ImportModule(module_name); + if (unlikely(!module)) goto import_failed; + decompress = PyObject_GetAttr(module, methodname); + if (unlikely(!decompress)) goto import_failed; + { + #ifdef __cplusplus + char *memview_bytes = const_cast(s); + #else + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wcast-qual" + #elif !defined(__INTEL_COMPILER) && defined(__GNUC__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wcast-qual" + #endif + char *memview_bytes = (char*) s; + #if defined(__clang__) + #pragma clang diagnostic pop + #elif !defined(__INTEL_COMPILER) && defined(__GNUC__) + #pragma GCC diagnostic pop + #endif + #endif + #if CYTHON_COMPILING_IN_LIMITED_API && !defined(PyBUF_READ) + int memview_flags = 0x100; + #else + int memview_flags = PyBUF_READ; + #endif + compressed_bytes = PyMemoryView_FromMemory(memview_bytes, length, memview_flags); + } + if (unlikely(!compressed_bytes)) { + Py_DECREF(decompress); + goto bad; + } + decompressed = PyObject_CallFunctionObjArgs(decompress, compressed_bytes, NULL); + Py_DECREF(compressed_bytes); + Py_DECREF(decompress); + Py_DECREF(module); + Py_DECREF(methodname); + return decompressed; +import_failed: + PyErr_Format(PyExc_ImportError, + "Failed to import '%.20s.decompress' - cannot initialise module strings. " + "String compression was configured with the C macro 'CYTHON_COMPRESS_STRINGS=%d'.", + module_name, algo); +bad: + Py_XDECREF(module); + Py_DECREF(methodname); + return NULL; +} + +#include +static CYTHON_INLINE Py_ssize_t __Pyx_ssize_strlen(const char *s) { + size_t len = strlen(s); + if (unlikely(len > (size_t) PY_SSIZE_T_MAX)) { + PyErr_SetString(PyExc_OverflowError, "byte string is too long"); + return -1; + } + return (Py_ssize_t) len; +} +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) { + Py_ssize_t len = __Pyx_ssize_strlen(c_str); + if (unlikely(len < 0)) return NULL; + return __Pyx_PyUnicode_FromStringAndSize(c_str, len); +} +static CYTHON_INLINE PyObject* __Pyx_PyByteArray_FromString(const char* c_str) { + Py_ssize_t len = __Pyx_ssize_strlen(c_str); + if (unlikely(len < 0)) return NULL; + return PyByteArray_FromStringAndSize(c_str, len); +} +static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject* o) { + Py_ssize_t ignore; + return __Pyx_PyObject_AsStringAndSize(o, &ignore); +} +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 +static CYTHON_INLINE const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { + if (unlikely(__Pyx_PyUnicode_READY(o) == -1)) return NULL; +#if CYTHON_COMPILING_IN_LIMITED_API + { + const char* result; + Py_ssize_t unicode_length; + CYTHON_MAYBE_UNUSED_VAR(unicode_length); // only for __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + #if __PYX_LIMITED_VERSION_HEX < 0x030A0000 + if (unlikely(PyArg_Parse(o, "s#", &result, length) < 0)) return NULL; + #else + result = PyUnicode_AsUTF8AndSize(o, length); + #endif + #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + unicode_length = PyUnicode_GetLength(o); + if (unlikely(unicode_length < 0)) return NULL; + if (unlikely(unicode_length != *length)) { + PyUnicode_AsASCIIString(o); + return NULL; + } + #endif + return result; + } +#else +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + if (likely(PyUnicode_IS_ASCII(o))) { + *length = PyUnicode_GET_LENGTH(o); + return PyUnicode_AsUTF8(o); + } else { + PyUnicode_AsASCIIString(o); + return NULL; + } +#else + return PyUnicode_AsUTF8AndSize(o, length); +#endif +#endif +} +#endif +static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) { +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 + if (PyUnicode_Check(o)) { + return __Pyx_PyUnicode_AsStringAndSize(o, length); + } else +#endif + if (PyByteArray_Check(o)) { +#if (CYTHON_ASSUME_SAFE_SIZE && CYTHON_ASSUME_SAFE_MACROS) || (CYTHON_COMPILING_IN_PYPY && (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE))) + *length = PyByteArray_GET_SIZE(o); + return PyByteArray_AS_STRING(o); +#else + *length = PyByteArray_Size(o); + if (*length == -1) return NULL; + return PyByteArray_AsString(o); +#endif + } else + { + char* result; + int r = PyBytes_AsStringAndSize(o, &result, length); + if (unlikely(r < 0)) { + return NULL; + } else { + return result; + } + } +} +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { + int is_true = x == Py_True; + if (is_true | (x == Py_False) | (x == Py_None)) return is_true; + else return PyObject_IsTrue(x); +} +static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject* x) { + int retval; + if (unlikely(!x)) return -1; + retval = __Pyx_PyObject_IsTrue(x); + Py_DECREF(x); + return retval; +} +static PyObject* __Pyx_PyNumber_LongWrongResultType(PyObject* result) { + __Pyx_TypeName result_type_name = __Pyx_PyType_GetFullyQualifiedName(Py_TYPE(result)); + if (PyLong_Check(result)) { + if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "__int__ returned non-int (type " __Pyx_FMT_TYPENAME "). " + "The ability to return an instance of a strict subclass of int is deprecated, " + "and may be removed in a future version of Python.", + result_type_name)) { + __Pyx_DECREF_TypeName(result_type_name); + Py_DECREF(result); + return NULL; + } + __Pyx_DECREF_TypeName(result_type_name); + return result; + } + PyErr_Format(PyExc_TypeError, + "__int__ returned non-int (type " __Pyx_FMT_TYPENAME ")", + result_type_name); + __Pyx_DECREF_TypeName(result_type_name); + Py_DECREF(result); + return NULL; +} +static CYTHON_INLINE PyObject* __Pyx_PyNumber_Long(PyObject* x) { +#if CYTHON_USE_TYPE_SLOTS + PyNumberMethods *m; +#endif + PyObject *res = NULL; + if (likely(PyLong_Check(x))) + return __Pyx_NewRef(x); +#if CYTHON_USE_TYPE_SLOTS + m = Py_TYPE(x)->tp_as_number; + if (likely(m && m->nb_int)) { + res = m->nb_int(x); + } +#else + if (!PyBytes_CheckExact(x) && !PyUnicode_CheckExact(x)) { + res = PyNumber_Long(x); + } +#endif + if (likely(res)) { + if (unlikely(!PyLong_CheckExact(res))) { + return __Pyx_PyNumber_LongWrongResultType(res); + } + } + else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, + "an integer is required"); + } + return res; +} +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { + Py_ssize_t ival; + PyObject *x; + if (likely(PyLong_CheckExact(b))) { + #if CYTHON_USE_PYLONG_INTERNALS + if (likely(__Pyx_PyLong_IsCompact(b))) { + return __Pyx_PyLong_CompactValue(b); + } else { + const digit* digits = __Pyx_PyLong_Digits(b); + const Py_ssize_t size = __Pyx_PyLong_SignedDigitCount(b); + switch (size) { + case 2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return (Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + } + } + #endif + return PyLong_AsSsize_t(b); + } + x = PyNumber_Index(b); + if (!x) return -1; + ival = PyLong_AsSsize_t(x); + Py_DECREF(x); + return ival; +} +static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject* o) { + if (sizeof(Py_hash_t) == sizeof(Py_ssize_t)) { + return (Py_hash_t) __Pyx_PyIndex_AsSsize_t(o); + } else { + Py_ssize_t ival; + PyObject *x; + x = PyNumber_Index(o); + if (!x) return -1; + ival = PyLong_AsLong(x); + Py_DECREF(x); + return ival; + } +} +static CYTHON_INLINE PyObject *__Pyx_Owned_Py_None(int b) { + CYTHON_UNUSED_VAR(b); + return __Pyx_NewRef(Py_None); +} +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { + return __Pyx_NewRef(b ? Py_True: Py_False); +} +static CYTHON_INLINE PyObject * __Pyx_PyLong_FromSize_t(size_t ival) { + return PyLong_FromSize_t(ival); +} + + +/* MultiPhaseInitModuleState */ +#if CYTHON_PEP489_MULTI_PHASE_INIT && CYTHON_USE_MODULE_STATE +#ifndef CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE +#if (CYTHON_COMPILING_IN_LIMITED_API || PY_VERSION_HEX >= 0x030C0000) + #define CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE 1 +#else + #define CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE 0 +#endif +#endif +#if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE && !CYTHON_ATOMICS +#error "Module state with PEP489 requires atomics. Currently that's one of\ + C11, C++11, gcc atomic intrinsics or MSVC atomic intrinsics" +#endif +#if !CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE +#define __Pyx_ModuleStateLookup_Lock() +#define __Pyx_ModuleStateLookup_Unlock() +#elif !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x030d0000 +static PyMutex __Pyx_ModuleStateLookup_mutex = {0}; +#define __Pyx_ModuleStateLookup_Lock() PyMutex_Lock(&__Pyx_ModuleStateLookup_mutex) +#define __Pyx_ModuleStateLookup_Unlock() PyMutex_Unlock(&__Pyx_ModuleStateLookup_mutex) +#elif defined(__cplusplus) && __cplusplus >= 201103L +#include +static std::mutex __Pyx_ModuleStateLookup_mutex; +#define __Pyx_ModuleStateLookup_Lock() __Pyx_ModuleStateLookup_mutex.lock() +#define __Pyx_ModuleStateLookup_Unlock() __Pyx_ModuleStateLookup_mutex.unlock() +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ > 201112L) && !defined(__STDC_NO_THREADS__) +#include +static mtx_t __Pyx_ModuleStateLookup_mutex; +static once_flag __Pyx_ModuleStateLookup_mutex_once_flag = ONCE_FLAG_INIT; +static void __Pyx_ModuleStateLookup_initialize_mutex(void) { + mtx_init(&__Pyx_ModuleStateLookup_mutex, mtx_plain); +} +#define __Pyx_ModuleStateLookup_Lock()\ + call_once(&__Pyx_ModuleStateLookup_mutex_once_flag, __Pyx_ModuleStateLookup_initialize_mutex);\ + mtx_lock(&__Pyx_ModuleStateLookup_mutex) +#define __Pyx_ModuleStateLookup_Unlock() mtx_unlock(&__Pyx_ModuleStateLookup_mutex) +#elif defined(HAVE_PTHREAD_H) +#include +static pthread_mutex_t __Pyx_ModuleStateLookup_mutex = PTHREAD_MUTEX_INITIALIZER; +#define __Pyx_ModuleStateLookup_Lock() pthread_mutex_lock(&__Pyx_ModuleStateLookup_mutex) +#define __Pyx_ModuleStateLookup_Unlock() pthread_mutex_unlock(&__Pyx_ModuleStateLookup_mutex) +#elif defined(_WIN32) +#include // synchapi.h on its own doesn't work +static SRWLOCK __Pyx_ModuleStateLookup_mutex = SRWLOCK_INIT; +#define __Pyx_ModuleStateLookup_Lock() AcquireSRWLockExclusive(&__Pyx_ModuleStateLookup_mutex) +#define __Pyx_ModuleStateLookup_Unlock() ReleaseSRWLockExclusive(&__Pyx_ModuleStateLookup_mutex) +#else +#error "No suitable lock available for CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE.\ + Requires C standard >= C11, or C++ standard >= C++11,\ + or pthreads, or the Windows 32 API, or Python >= 3.13." +#endif +typedef struct { + int64_t id; + PyObject *module; +} __Pyx_InterpreterIdAndModule; +typedef struct { + char interpreter_id_as_index; + Py_ssize_t count; + Py_ssize_t allocated; + __Pyx_InterpreterIdAndModule table[1]; +} __Pyx_ModuleStateLookupData; +#define __PYX_MODULE_STATE_LOOKUP_SMALL_SIZE 32 +#if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE +static __pyx_atomic_int_type __Pyx_ModuleStateLookup_read_counter = 0; +#endif +#if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE +static __pyx_atomic_ptr_type __Pyx_ModuleStateLookup_data = 0; +#else +static __Pyx_ModuleStateLookupData* __Pyx_ModuleStateLookup_data = NULL; +#endif +static __Pyx_InterpreterIdAndModule* __Pyx_State_FindModuleStateLookupTableLowerBound( + __Pyx_InterpreterIdAndModule* table, + Py_ssize_t count, + int64_t interpreterId) { + __Pyx_InterpreterIdAndModule* begin = table; + __Pyx_InterpreterIdAndModule* end = begin + count; + if (begin->id == interpreterId) { + return begin; + } + while ((end - begin) > __PYX_MODULE_STATE_LOOKUP_SMALL_SIZE) { + __Pyx_InterpreterIdAndModule* halfway = begin + (end - begin)/2; + if (halfway->id == interpreterId) { + return halfway; + } + if (halfway->id < interpreterId) { + begin = halfway; + } else { + end = halfway; + } + } + for (; begin < end; ++begin) { + if (begin->id >= interpreterId) return begin; + } + return begin; +} +static PyObject *__Pyx_State_FindModule(CYTHON_UNUSED void* dummy) { + int64_t interpreter_id = PyInterpreterState_GetID(__Pyx_PyInterpreterState_Get()); + if (interpreter_id == -1) return NULL; +#if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE + __Pyx_ModuleStateLookupData* data = (__Pyx_ModuleStateLookupData*)__pyx_atomic_pointer_load_relaxed(&__Pyx_ModuleStateLookup_data); + { + __pyx_atomic_incr_acq_rel(&__Pyx_ModuleStateLookup_read_counter); + if (likely(data)) { + __Pyx_ModuleStateLookupData* new_data = (__Pyx_ModuleStateLookupData*)__pyx_atomic_pointer_load_acquire(&__Pyx_ModuleStateLookup_data); + if (likely(data == new_data)) { + goto read_finished; + } + } + __pyx_atomic_decr_acq_rel(&__Pyx_ModuleStateLookup_read_counter); + __Pyx_ModuleStateLookup_Lock(); + __pyx_atomic_incr_relaxed(&__Pyx_ModuleStateLookup_read_counter); + data = (__Pyx_ModuleStateLookupData*)__pyx_atomic_pointer_load_relaxed(&__Pyx_ModuleStateLookup_data); + __Pyx_ModuleStateLookup_Unlock(); + } + read_finished:; +#else + __Pyx_ModuleStateLookupData* data = __Pyx_ModuleStateLookup_data; +#endif + __Pyx_InterpreterIdAndModule* found = NULL; + if (unlikely(!data)) goto end; + if (data->interpreter_id_as_index) { + if (interpreter_id < data->count) { + found = data->table+interpreter_id; + } + } else { + found = __Pyx_State_FindModuleStateLookupTableLowerBound( + data->table, data->count, interpreter_id); + } + end: + { + PyObject *result=NULL; + if (found && found->id == interpreter_id) { + result = found->module; + } +#if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE + __pyx_atomic_decr_acq_rel(&__Pyx_ModuleStateLookup_read_counter); +#endif + return result; + } +} +#if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE +static void __Pyx_ModuleStateLookup_wait_until_no_readers(void) { + while (__pyx_atomic_load(&__Pyx_ModuleStateLookup_read_counter) != 0); +} +#else +#define __Pyx_ModuleStateLookup_wait_until_no_readers() +#endif +static int __Pyx_State_AddModuleInterpIdAsIndex(__Pyx_ModuleStateLookupData **old_data, PyObject* module, int64_t interpreter_id) { + Py_ssize_t to_allocate = (*old_data)->allocated; + while (to_allocate <= interpreter_id) { + if (to_allocate == 0) to_allocate = 1; + else to_allocate *= 2; + } + __Pyx_ModuleStateLookupData *new_data = *old_data; + if (to_allocate != (*old_data)->allocated) { + new_data = (__Pyx_ModuleStateLookupData *)realloc( + *old_data, + sizeof(__Pyx_ModuleStateLookupData)+(to_allocate-1)*sizeof(__Pyx_InterpreterIdAndModule)); + if (!new_data) { + PyErr_NoMemory(); + return -1; + } + for (Py_ssize_t i = new_data->allocated; i < to_allocate; ++i) { + new_data->table[i].id = i; + new_data->table[i].module = NULL; + } + new_data->allocated = to_allocate; + } + new_data->table[interpreter_id].module = module; + if (new_data->count < interpreter_id+1) { + new_data->count = interpreter_id+1; + } + *old_data = new_data; + return 0; +} +static void __Pyx_State_ConvertFromInterpIdAsIndex(__Pyx_ModuleStateLookupData *data) { + __Pyx_InterpreterIdAndModule *read = data->table; + __Pyx_InterpreterIdAndModule *write = data->table; + __Pyx_InterpreterIdAndModule *end = read + data->count; + for (; readmodule) { + write->id = read->id; + write->module = read->module; + ++write; + } + } + data->count = write - data->table; + for (; writeid = 0; + write->module = NULL; + } + data->interpreter_id_as_index = 0; +} +static int __Pyx_State_AddModule(PyObject* module, CYTHON_UNUSED void* dummy) { + int64_t interpreter_id = PyInterpreterState_GetID(__Pyx_PyInterpreterState_Get()); + if (interpreter_id == -1) return -1; + int result = 0; + __Pyx_ModuleStateLookup_Lock(); +#if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE + __Pyx_ModuleStateLookupData *old_data = (__Pyx_ModuleStateLookupData *) + __pyx_atomic_pointer_exchange(&__Pyx_ModuleStateLookup_data, 0); +#else + __Pyx_ModuleStateLookupData *old_data = __Pyx_ModuleStateLookup_data; +#endif + __Pyx_ModuleStateLookupData *new_data = old_data; + if (!new_data) { + new_data = (__Pyx_ModuleStateLookupData *)calloc(1, sizeof(__Pyx_ModuleStateLookupData)); + if (!new_data) { + result = -1; + PyErr_NoMemory(); + goto end; + } + new_data->allocated = 1; + new_data->interpreter_id_as_index = 1; + } + __Pyx_ModuleStateLookup_wait_until_no_readers(); + if (new_data->interpreter_id_as_index) { + if (interpreter_id < __PYX_MODULE_STATE_LOOKUP_SMALL_SIZE) { + result = __Pyx_State_AddModuleInterpIdAsIndex(&new_data, module, interpreter_id); + goto end; + } + __Pyx_State_ConvertFromInterpIdAsIndex(new_data); + } + { + Py_ssize_t insert_at = 0; + { + __Pyx_InterpreterIdAndModule* lower_bound = __Pyx_State_FindModuleStateLookupTableLowerBound( + new_data->table, new_data->count, interpreter_id); + assert(lower_bound); + insert_at = lower_bound - new_data->table; + if (unlikely(insert_at < new_data->count && lower_bound->id == interpreter_id)) { + lower_bound->module = module; + goto end; // already in table, nothing more to do + } + } + if (new_data->count+1 >= new_data->allocated) { + Py_ssize_t to_allocate = (new_data->count+1)*2; + new_data = + (__Pyx_ModuleStateLookupData*)realloc( + new_data, + sizeof(__Pyx_ModuleStateLookupData) + + (to_allocate-1)*sizeof(__Pyx_InterpreterIdAndModule)); + if (!new_data) { + result = -1; + new_data = old_data; + PyErr_NoMemory(); + goto end; + } + new_data->allocated = to_allocate; + } + ++new_data->count; + int64_t last_id = interpreter_id; + PyObject *last_module = module; + for (Py_ssize_t i=insert_at; icount; ++i) { + int64_t current_id = new_data->table[i].id; + new_data->table[i].id = last_id; + last_id = current_id; + PyObject *current_module = new_data->table[i].module; + new_data->table[i].module = last_module; + last_module = current_module; + } + } + end: +#if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE + __pyx_atomic_pointer_exchange(&__Pyx_ModuleStateLookup_data, new_data); +#else + __Pyx_ModuleStateLookup_data = new_data; +#endif + __Pyx_ModuleStateLookup_Unlock(); + return result; +} +static int __Pyx_State_RemoveModule(CYTHON_UNUSED void* dummy) { + int64_t interpreter_id = PyInterpreterState_GetID(__Pyx_PyInterpreterState_Get()); + if (interpreter_id == -1) return -1; + __Pyx_ModuleStateLookup_Lock(); +#if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE + __Pyx_ModuleStateLookupData *data = (__Pyx_ModuleStateLookupData *) + __pyx_atomic_pointer_exchange(&__Pyx_ModuleStateLookup_data, 0); +#else + __Pyx_ModuleStateLookupData *data = __Pyx_ModuleStateLookup_data; +#endif + if (data->interpreter_id_as_index) { + if (interpreter_id < data->count) { + data->table[interpreter_id].module = NULL; + } + goto done; + } + { + __Pyx_ModuleStateLookup_wait_until_no_readers(); + __Pyx_InterpreterIdAndModule* lower_bound = __Pyx_State_FindModuleStateLookupTableLowerBound( + data->table, data->count, interpreter_id); + if (!lower_bound) goto done; + if (lower_bound->id != interpreter_id) goto done; + __Pyx_InterpreterIdAndModule *end = data->table+data->count; + for (;lower_boundid = (lower_bound+1)->id; + lower_bound->module = (lower_bound+1)->module; + } + } + --data->count; + if (data->count == 0) { + free(data); + data = NULL; + } + done: +#if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE + __pyx_atomic_pointer_exchange(&__Pyx_ModuleStateLookup_data, data); +#else + __Pyx_ModuleStateLookup_data = data; +#endif + __Pyx_ModuleStateLookup_Unlock(); + return 0; +} +#endif + +/* #### Code section: utility_code_pragmas_end ### */ +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + + + +/* #### Code section: end ### */ +#endif /* Py_PYTHON_H */ diff --git a/clickhouse_driver/_cityhash/cityhash.pyx b/clickhouse_driver/_cityhash/cityhash.pyx new file mode 100644 index 00000000..a2a3ef81 --- /dev/null +++ b/clickhouse_driver/_cityhash/cityhash.pyx @@ -0,0 +1,71 @@ +# cython: infer_types=True + +""" +A minimal Python wrapper around CityHash 1.0.2, the version of the +non-cryptographic hash algorithm used by ClickHouse for block checksums. + +Vendored from the clickhouse-cityhash package; see LICENSE in this directory. +""" + +__all__ = ["CityHash128"] + +cdef extern from * nogil: + ctypedef unsigned long int uint32_t + ctypedef unsigned long long int uint64_t + +cdef extern from "" namespace "std": + cdef cppclass pair[T, U]: + T first + U second + pair() + pair(pair&) + pair(T&, U&) + +cdef extern from "city.h" nogil: + ctypedef uint32_t uint32 + ctypedef uint64_t uint64 + ctypedef pair uint128 + cdef uint128[uint64, uint64] c_CityHash128 "CityHash128" (char *s, size_t len) + + +from cpython.buffer cimport PyObject_CheckBuffer +from cpython.buffer cimport PyBUF_SIMPLE +from cpython.buffer cimport Py_buffer +from cpython.buffer cimport PyObject_GetBuffer + +from cpython.unicode cimport PyUnicode_Check +from cpython.unicode cimport PyUnicode_AsUTF8String + +from cpython.bytes cimport PyBytes_Check +from cpython.bytes cimport PyBytes_GET_SIZE +from cpython.bytes cimport PyBytes_AS_STRING + +from cpython cimport Py_DECREF + + +cdef object _type_error(str argname, expected, value): + return TypeError( + "Argument '%s' has incorrect type (expected %s, got %s)" % + (argname, expected, type(value)) + ) + + +cpdef CityHash128(data): + """128-bit hash function for a bytes, str or buffer type.""" + cdef Py_buffer buf + cdef object obj + cdef pair[uint64, uint64] result + if PyUnicode_Check(data): + obj = PyUnicode_AsUTF8String(data) + PyObject_GetBuffer(obj, &buf, PyBUF_SIMPLE) + result = c_CityHash128(buf.buf, buf.len) + Py_DECREF(obj) + elif PyBytes_Check(data): + result = c_CityHash128(PyBytes_AS_STRING(data), + PyBytes_GET_SIZE(data)) + elif PyObject_CheckBuffer(data): + PyObject_GetBuffer(data, &buf, PyBUF_SIMPLE) + result = c_CityHash128(buf.buf, buf.len) + else: + raise _type_error("data", ["bytes", "str", "buffer"], data) + return 0x10000000000000000 * int(result.first) + int(result.second) diff --git a/clickhouse_driver/_cityhash/config.h b/clickhouse_driver/_cityhash/config.h new file mode 100644 index 00000000..278a2e12 --- /dev/null +++ b/clickhouse_driver/_cityhash/config.h @@ -0,0 +1,114 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* Define to 1 if the compiler supports __builtin_expect. */ +#define HAVE_BUILTIN_EXPECT 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "cityhash-discuss@googlegroups.com" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "CityHash" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "CityHash 1.1.1" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "cityhash" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.1.1" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT32_T */ + +/* Define for Solaris 2.5.1 so the uint64_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT64_T */ + +/* Define for Solaris 2.5.1 so the uint8_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT8_T */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* Define to `int' if does not define. */ +/* #undef ssize_t */ + +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint32_t */ + +/* Define to the type of an unsigned integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint64_t */ + +/* Define to the type of an unsigned integer type of width exactly 8 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint8_t */ diff --git a/clickhouse_driver/arrow/__init__.py b/clickhouse_driver/arrow/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/clickhouse_driver/arrow/convert.py b/clickhouse_driver/arrow/convert.py new file mode 100644 index 00000000..b33b2d2f --- /dev/null +++ b/clickhouse_driver/arrow/convert.py @@ -0,0 +1,313 @@ +import pyarrow as pa + +try: + import numpy as np +except ImportError: + np = None + +try: + import pandas as pd +except ImportError: + pd = None + +try: + from ..columns.arrow.stringcolumn import ArrowStringBuffers +except ImportError: + ArrowStringBuffers = None + +from .. import errors +from ..columns.util import get_inner_columns, get_inner_spec +from ..protocol import ServerPacketTypes +from .mapping import ( + UNSUPPORTED, get_type_and_converter, json_as_object, json_as_text +) + + +class ArrowStreamState(object): + """ + Tracks whether a streamed query was consumed to the end. + ``pyarrow.RecordBatchReader.close`` doesn't reach the underlying + generator, so the client uses this state to cancel unfinished + streams before the next query. + """ + __slots__ = ('connection', 'finished', 'cancelled') + + def __init__(self, connection): + self.connection = connection + self.finished = False + self.cancelled = False + + +def create_record_batch_reader(packet_generator, context, state=None, + field_metadata=True, arrow_types=None): + """ + Creates RecordBatchReader yielding one record batch per ClickHouse + block. Schema is built from the header block, so it's available before + any data block is received. + + Unless ``field_metadata`` is disabled, the original ClickHouse type + of each column is attached to its Arrow field as ``clickhouse_type`` + metadata. + + ``arrow_types`` maps column names to Arrow types, overriding the + default mapping. Columns of types without a default Arrow + representation (``JSON``) require an entry. + """ + strings_as_bytes = context.client_settings.get('strings_as_bytes', False) + + blocks = _data_blocks(packet_generator) + + first_block = next(blocks, None) + if first_block is None: + if state is not None: + state.finished = True + return pa.RecordBatchReader.from_batches(pa.schema([]), iter([])) + + columns_with_types = first_block.columns_with_types + fields = _resolve_fields( + columns_with_types, strings_as_bytes, arrow_types + ) + + # Header block contains no rows. + buffered = [first_block] if first_block.num_rows else [] + + # Types without explicit mapping are inferred from the first non-empty + # block. It has to be received before the schema can be built. + if any(type_ is None for type_, _ in fields): + while not buffered: + block = next(blocks, None) + if block is None: + break + if block.num_rows: + buffered.append(block) + + fields = _infer_missing_types(fields, buffered) + + schema = pa.schema([ + pa.field( + name, type_, + metadata={'clickhouse_type': spec} if field_metadata else None + ) + for (name, spec), (type_, _) in zip(columns_with_types, fields) + ]) + + def batches(): + for block in buffered: + yield _block_to_batch(block, schema, fields) + + while True: + # The stream may have been cancelled by a subsequent query + # on the same client. Reading further would consume packets + # of that query. + if state is not None and state.cancelled: + raise errors.PartiallyConsumedQueryError() + + block = next(blocks, None) + if block is None: + break + + if block.num_rows: + yield _block_to_batch(block, schema, fields) + + if state is not None: + state.finished = True + + return pa.RecordBatchReader.from_batches(schema, batches()) + + +def _is_json_spec(spec): + return spec == 'JSON' or spec.startswith('JSON(') + + +def _json_declared_converter(spec, declared, name): + """ + Composes JSON converters for a declared Arrow type, following + Nullable/Array/Map containers down to JSON positions. Returns + ``None`` when the spec contains no JSON at positions matched by + the declared type. + """ + if _is_json_spec(spec): + if pa.types.is_string(declared) or \ + pa.types.is_large_string(declared): + return json_as_text(name) + return json_as_object + + if spec.startswith('Nullable('): + return _json_declared_converter( + get_inner_spec('Nullable', spec), declared, name + ) + + if spec.startswith('Array(') and ( + pa.types.is_list(declared) or pa.types.is_large_list(declared)): + inner = _json_declared_converter( + get_inner_spec('Array', spec), declared.value_type, name + ) + if inner is None: + return None + + def converter(value, _converter=inner): + return [None if x is None else _converter(x) for x in value] + return converter + + if spec.startswith('Map(') and pa.types.is_map(declared): + _, value_spec = get_inner_columns(get_inner_spec('Map', spec)) + value_converter = _json_declared_converter( + value_spec, declared.item_type, name + ) + if value_converter is None: + return None + + def converter(value, _vc=value_converter): + return [ + (k, None if v is None else _vc(v)) + for k, v in value.items() + ] + return converter + + return None + + +def _resolve_fields(columns_with_types, strings_as_bytes, arrow_types): + fields = [] + for name, spec in columns_with_types: + type_, converter = get_type_and_converter(spec, strings_as_bytes) + + declared = (arrow_types or {}).get(name) + if declared is not None: + json_converter = _json_declared_converter(spec, declared, name) + if json_converter is not None: + converter = json_converter + type_ = declared + + elif type_ is UNSUPPORTED: + raise ValueError( + "Column '{0}' of type {1} has no default Arrow " + "representation. Pass arrow_types={{'{0}': " + "pyarrow.string()}} for JSON text, declare a struct " + 'type for structured output, or transform the column ' + 'in the query (e.g. toJSONString).'.format(name, spec) + ) + + fields.append((type_, converter)) + return fields + + +def _data_blocks(packet_generator): + for packet in packet_generator: + if getattr(packet, 'type', None) == ServerPacketTypes.DATA: + block = getattr(packet, 'block', None) + if block is not None: + yield block + + +def _infer_missing_types(fields, buffered): + rv = [] + for i, (type_, converter) in enumerate(fields): + if type_ is None: + if buffered: + column = buffered[0].get_columns()[i] + type_ = _column_to_array(column, None, converter).type + else: + type_ = pa.null() + rv.append((type_, converter)) + return rv + + +def _block_to_batch(block, schema, fields): + arrays = [ + _column_to_array(column, type_, converter) + for column, (type_, converter) in zip(block.get_columns(), fields) + ] + return pa.RecordBatch.from_arrays(arrays, schema=schema) + + +def _column_to_array(column, type_, converter): + if ArrowStringBuffers is not None and \ + isinstance(column, ArrowStringBuffers): + return _string_buffers_to_array(column, type_) + + if np is not None and isinstance(column, np.ma.MaskedArray): + return _masked_to_array(column, type_, converter) + + # Numeric and datetime64 NumPy columns are handled by Arrow without + # copying. + if np is not None and isinstance(column, np.ndarray) and \ + column.dtype.kind in 'iufbM': + return pa.array(column, type=type_) + + if pd is not None and isinstance(column, pd.Categorical): + if converter is None: + # Categorical maps to Arrow dictionary array without + # iterating over values. + dictionary = pa.array(column) + return dictionary.cast(type_) if type_ is not None \ + else dictionary + column = [None if pd.isna(x) else x for x in column] + + if converter is not None: + column = [None if x is None else converter(x) for x in column] + + return pa.array(column, type=type_) + + +def _string_buffers_to_array(column, type_): + """ + Assembles a string/binary array directly from wire-format buffers: + concatenated bytes + offsets, no per-string Python objects. The + binary -> string cast validates UTF-8 in C. + """ + n_items = len(column) + offsets = np.frombuffer(column.offsets, dtype=np.int64) + + if offsets[-1] > 2 ** 31 - 1: + raise ValueError( + 'Block string data exceeds 2GiB. ' + 'Lower max_block_size to stream it.' + ) + + validity = None + if column.nulls_map is not None: + validity = pa.py_buffer( + np.packbits(column.nulls_map == 0, bitorder='little') + ) + + binary = pa.Array.from_buffers(pa.binary(), n_items, [ + validity, + pa.py_buffer(offsets.astype(np.int32)), + pa.py_buffer(column.data) + ]) + + if type_ is None or type_ == pa.string(): + return binary.cast(pa.string()) + return binary + + +def _masked_to_array(column, type_, converter): + """ + Nullable columns come from the NumPy path as masked arrays: raw + values with placeholders in NULL slots plus the nulls map. Arrow + stores exactly that, so the values buffer is reused as is and the + nulls map is packed into the validity bitmap. + """ + mask = np.ma.getmaskarray(column) + data = column.data + + if converter is not None: + values = [ + None if is_null else converter(x) + for x, is_null in zip(data, mask) + ] + return pa.array(values, type=type_, mask=mask) + + if data.dtype.kind not in 'iufbM': + return pa.array(data, type=type_, mask=mask) + + # pa.array copies values slot by slot when mask is passed. Packing + # the validity bitmap manually is ~20x faster. + data_array = pa.array(data) if type_ is None else \ + pa.array(data, type=type_) + validity = pa.py_buffer(np.packbits(~mask, bitorder='little')) + return pa.Array.from_buffers( + data_array.type, len(data_array), + [validity, data_array.buffers()[1]] + ) diff --git a/clickhouse_driver/arrow/mapping.py b/clickhouse_driver/arrow/mapping.py new file mode 100644 index 00000000..216e2ab1 --- /dev/null +++ b/clickhouse_driver/arrow/mapping.py @@ -0,0 +1,219 @@ +import json + +import pyarrow as pa + +from ..columns.util import ( + get_inner_columns, get_inner_columns_with_types, get_inner_spec +) + +SIMPLE_TYPES = { + 'Int8': pa.int8(), + 'Int16': pa.int16(), + 'Int32': pa.int32(), + 'Int64': pa.int64(), + 'UInt8': pa.uint8(), + 'UInt16': pa.uint16(), + 'UInt32': pa.uint32(), + 'UInt64': pa.uint64(), + 'Float32': pa.float32(), + 'Float64': pa.float64(), + 'Date': pa.date32(), + 'Date32': pa.date32(), + 'Bool': pa.bool_(), + 'Nothing': pa.null() +} + +# Types represented by rich Python objects are stringified. +STRINGIFIED_TYPES = {'UUID', 'IPv4', 'IPv6'} + +DECIMAL_PRECISIONS = { + 'Decimal32': 9, + 'Decimal64': 18, + 'Decimal128': 38, + 'Decimal256': 76 +} + + +#: Types with no default Arrow representation: an explicit +#: ``arrow_types`` entry is required for such columns. +UNSUPPORTED = object() + + +def json_as_text(column_name): + """ + JSON column value to JSON text. Requires + output_format_native_write_json_as_string=1: the server sends JSON + text which is passed through as is. There is deliberately no + client-side serialization fallback to avoid performance bottlenecks. + """ + def converter(value): + if isinstance(value, str): + return value or '{}' + + raise ValueError( + "Column '{0}': JSON text output requires server-side " + 'serialization. Set ' + 'output_format_native_write_json_as_string=1 in query ' + 'settings (ClickHouse 24.10+) or transform the column in ' + 'the query with toJSONString().'.format(column_name) + ) + + return converter + + +def json_as_object(value): + """JSON column value to python objects for structured types.""" + if isinstance(value, str): + return json.loads(value) if value else {} + return value + + +def get_type_and_converter(spec, strings_as_bytes=False): + """ + Maps ClickHouse type spec into pair (Arrow type, converter). + + Arrow type is ``None`` for types without explicit mapping. Their Arrow + type is inferred from data later. + + Converter is a callable applied to each non-NULL value before array + construction or ``None`` if values can be handled by Arrow as is. + """ + spec = spec.strip() + + if spec in SIMPLE_TYPES: + return SIMPLE_TYPES[spec], None + + if spec in STRINGIFIED_TYPES: + return pa.string(), str + + if spec == 'JSON' or spec.startswith('JSON('): + # No default representation: dynamic paths make every implicit + # choice either lossy or unstable. Requires arrow_types. + return UNSUPPORTED, None + + if spec == 'String' or spec.startswith('FixedString'): + if strings_as_bytes: + return pa.binary(), None + return pa.string(), None + + if spec.startswith('Enum'): + return pa.string(), None + + if spec.startswith('Nullable('): + return get_type_and_converter( + get_inner_spec('Nullable', spec), strings_as_bytes + ) + + if spec.startswith('LowCardinality('): + return get_type_and_converter( + get_inner_spec('LowCardinality', spec), strings_as_bytes + ) + + if spec.startswith('SimpleAggregateFunction('): + inner_spec = get_inner_columns( + get_inner_spec('SimpleAggregateFunction', spec) + )[-1] + return get_type_and_converter(inner_spec, strings_as_bytes) + + if spec.startswith('Array('): + inner_type, inner_converter = get_type_and_converter( + get_inner_spec('Array', spec), strings_as_bytes + ) + if inner_type is None or inner_type is UNSUPPORTED: + return inner_type, None + + if inner_converter is None: + converter = None + else: + def converter(value, _converter=inner_converter): + return [ + None if x is None else _converter(x) for x in value + ] + + return pa.list_(inner_type), converter + + if spec.startswith('Map('): + key_spec, value_spec = get_inner_columns(get_inner_spec('Map', spec)) + key_type, key_converter = get_type_and_converter( + key_spec, strings_as_bytes + ) + value_type, value_converter = get_type_and_converter( + value_spec, strings_as_bytes + ) + for t in (key_type, value_type): + if t is None or t is UNSUPPORTED: + return t, None + + if key_converter is None and value_converter is None: + converter = None + else: + def converter(value, _kc=key_converter, _vc=value_converter): + return [ + ( + _kc(k) if _kc else k, + (None if v is None else _vc(v)) if _vc else v + ) + for k, v in value.items() + ] + + return pa.map_(key_type, value_type), converter + + if spec.startswith("Object('json')"): + # Legacy JSON type (servers 22.3-24.x): same dynamic nature, + # same treatment as JSON. + return UNSUPPORTED, None + + if spec.startswith('Tuple(') or spec.startswith('Nested('): + # No explicit mapping (inference applies), but unsupported + # element types must not leak into inference. + prefix = 'Tuple' if spec.startswith('Tuple(') else 'Nested' + inner_columns = get_inner_columns_with_types( + get_inner_spec(prefix, spec) + ) + for _, inner_spec in inner_columns: + inner_type, _ = get_type_and_converter( + inner_spec, strings_as_bytes + ) + if inner_type is UNSUPPORTED: + return UNSUPPORTED, None + return None, None + + if spec.startswith('Decimal'): + if spec.startswith('Decimal('): + precision, scale = [ + int(x) for x in get_inner_spec('Decimal', spec).split(',') + ] + else: + prefix = spec.split('(')[0] + if prefix not in DECIMAL_PRECISIONS: + return None, None + precision = DECIMAL_PRECISIONS[prefix] + scale = int(get_inner_spec(prefix, spec)) + + if precision <= 38: + return pa.decimal128(precision, scale), None + return pa.decimal256(precision, scale), None + + if spec.startswith('DateTime64('): + params = get_inner_columns(get_inner_spec('DateTime64', spec)) + precision = int(params[0]) + tz = params[1].strip("'") if len(params) > 1 else None + + if precision == 0: + unit = 's' + elif precision <= 3: + unit = 'ms' + elif precision <= 6: + unit = 'us' + else: + unit = 'ns' + + return pa.timestamp(unit, tz=tz), None + + if spec.startswith('DateTime'): + tz = None + if spec.startswith('DateTime('): + tz = get_inner_spec('DateTime', spec).strip("'") + return pa.timestamp('s', tz=tz), None + + return None, None diff --git a/clickhouse_driver/bufferedreader.c b/clickhouse_driver/bufferedreader.c index 2799e9c7..baccae04 100644 --- a/clickhouse_driver/bufferedreader.c +++ b/clickhouse_driver/bufferedreader.c @@ -1,5 +1,18 @@ /* Generated by Cython 3.2.0 */ +/* BEGIN: Cython Metadata +{ + "distutils": { + "depends": [], + "name": "clickhouse_driver.bufferedreader", + "sources": [ + "/Users/kgustyr/dev/clickhouse-driver/clickhouse_driver/bufferedreader.pyx" + ] + }, + "module_name": "clickhouse_driver.bufferedreader" +} +END: Cython Metadata */ + #ifndef PY_SSIZE_T_CLEAN #define PY_SSIZE_T_CLEAN #endif /* PY_SSIZE_T_CLEAN */ @@ -1368,11 +1381,11 @@ static const char *__pyx_filename; static const char* const __pyx_f[] = { "clickhouse_driver/bufferedreader.pyx", - "cpython/contextvars.pxd", + ".covenv/lib/python3.11/site-packages/Cython/Includes/cpython/contextvars.pxd", "", - "cpython/type.pxd", - "cpython/bool.pxd", - "cpython/complex.pxd", + ".covenv/lib/python3.11/site-packages/Cython/Includes/cpython/type.pxd", + ".covenv/lib/python3.11/site-packages/Cython/Includes/cpython/bool.pxd", + ".covenv/lib/python3.11/site-packages/Cython/Includes/cpython/complex.pxd", }; /* #### Code section: utility_code_proto_before_types ### */ /* Atomics.proto */ @@ -1594,7 +1607,7 @@ struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader { }; -/* "clickhouse_driver/bufferedreader.pyx":229 +/* "clickhouse_driver/bufferedreader.pyx":317 * * * cdef class BufferedSocketReader(BufferedReader): # <<<<<<<<<<<<<< @@ -1607,7 +1620,7 @@ struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedSocketReader { }; -/* "clickhouse_driver/bufferedreader.pyx":243 +/* "clickhouse_driver/bufferedreader.pyx":331 * * * cdef class CompressedBufferedReader(BufferedReader): # <<<<<<<<<<<<<< @@ -2610,8 +2623,9 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_4read(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self, unsigned PY_LONG_LONG __pyx_v_unread); /* proto */ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_6read_one(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self); /* proto */ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_8read_strings(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self, unsigned PY_LONG_LONG __pyx_v_n_items, PyObject *__pyx_v_encoding); /* proto */ -static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_10read_fixed_strings_as_bytes(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self, Py_ssize_t __pyx_v_n_items, Py_ssize_t __pyx_v_length); /* proto */ -static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_12read_fixed_strings(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self, Py_ssize_t __pyx_v_n_items, Py_ssize_t __pyx_v_length, PyObject *__pyx_v_encoding); /* proto */ +static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_10read_strings_arrow(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self, unsigned PY_LONG_LONG __pyx_v_n_items); /* proto */ +static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_12read_fixed_strings_as_bytes(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self, Py_ssize_t __pyx_v_n_items, Py_ssize_t __pyx_v_length); /* proto */ +static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_14read_fixed_strings(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self, Py_ssize_t __pyx_v_n_items, Py_ssize_t __pyx_v_length, PyObject *__pyx_v_encoding); /* proto */ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_8position___get__(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self); /* proto */ static int __pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_8position_2__set__(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self, PyObject *__pyx_v_value); /* proto */ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_19current_buffer_size___get__(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self); /* proto */ @@ -2619,8 +2633,8 @@ static int __pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_19curr static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_6buffer___get__(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self); /* proto */ static int __pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_6buffer_2__set__(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self, PyObject *__pyx_v_value); /* proto */ static int __pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_6buffer_4__del__(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_14__reduce_cython__(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_16__setstate_cython__(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self, PyObject *__pyx_v___pyx_state); /* proto */ +static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_16__reduce_cython__(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_18__setstate_cython__(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self, PyObject *__pyx_v___pyx_state); /* proto */ static int __pyx_pf_17clickhouse_driver_14bufferedreader_20BufferedSocketReader___init__(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedSocketReader *__pyx_v_self, PyObject *__pyx_v_sock, PyObject *__pyx_v_bufsize); /* proto */ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_20BufferedSocketReader_2read_into_buffer(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedSocketReader *__pyx_v_self); /* proto */ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_20BufferedSocketReader_4__reduce_cython__(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedSocketReader *__pyx_v_self); /* proto */ @@ -2668,8 +2682,8 @@ typedef struct { __Pyx_CachedCFunction __pyx_umethod_PyDict_Type_pop; __Pyx_CachedCFunction __pyx_umethod_PyDict_Type_values; PyObject *__pyx_tuple[4]; - PyObject *__pyx_codeobj_tab[17]; - PyObject *__pyx_string_tab[120]; + PyObject *__pyx_codeobj_tab[18]; + PyObject *__pyx_string_tab[127]; PyObject *__pyx_number_tab[3]; /* #### Code section: module_state_contents ### */ /* CommonTypesMetaclass.module_state_decls */ @@ -2734,103 +2748,110 @@ static __pyx_mstatetype * const __pyx_mstate_global = &__pyx_mstate_global_stati #define __pyx_n_u_BufferedReader_read_into_buffer __pyx_string_tab[20] #define __pyx_n_u_BufferedReader_read_one __pyx_string_tab[21] #define __pyx_n_u_BufferedReader_read_strings __pyx_string_tab[22] -#define __pyx_n_u_BufferedSocketReader __pyx_string_tab[23] -#define __pyx_n_u_BufferedSocketReader___reduce_cy __pyx_string_tab[24] -#define __pyx_n_u_BufferedSocketReader___setstate __pyx_string_tab[25] -#define __pyx_n_u_BufferedSocketReader_read_into_b __pyx_string_tab[26] -#define __pyx_n_u_CompressedBufferedReader __pyx_string_tab[27] -#define __pyx_n_u_CompressedBufferedReader___reduc __pyx_string_tab[28] -#define __pyx_n_u_CompressedBufferedReader___setst __pyx_string_tab[29] -#define __pyx_n_u_CompressedBufferedReader_read_in __pyx_string_tab[30] -#define __pyx_n_u_Pyx_PyDict_NextRef __pyx_string_tab[31] -#define __pyx_n_u_asyncio_coroutines __pyx_string_tab[32] -#define __pyx_n_u_b __pyx_string_tab[33] -#define __pyx_n_u_buffer_ptr __pyx_string_tab[34] -#define __pyx_n_u_bufsize __pyx_string_tab[35] -#define __pyx_n_u_bytes_read __pyx_string_tab[36] -#define __pyx_n_u_c_encoding __pyx_string_tab[37] -#define __pyx_n_u_c_string __pyx_string_tab[38] -#define __pyx_n_u_c_string_size __pyx_string_tab[39] -#define __pyx_n_u_clickhouse_driver_bufferedreader __pyx_string_tab[40] -#define __pyx_n_u_cline_in_traceback __pyx_string_tab[41] -#define __pyx_n_u_data __pyx_string_tab[42] -#define __pyx_n_u_data_ptr __pyx_string_tab[43] -#define __pyx_n_u_dict __pyx_string_tab[44] -#define __pyx_n_u_dict_2 __pyx_string_tab[45] -#define __pyx_n_u_encode __pyx_string_tab[46] -#define __pyx_n_u_encoding __pyx_string_tab[47] -#define __pyx_n_u_func __pyx_string_tab[48] -#define __pyx_n_u_getstate __pyx_string_tab[49] -#define __pyx_n_u_i __pyx_string_tab[50] -#define __pyx_n_u_init __pyx_string_tab[51] -#define __pyx_n_u_is_coroutine __pyx_string_tab[52] -#define __pyx_n_u_item __pyx_string_tab[53] -#define __pyx_n_u_items __pyx_string_tab[54] -#define __pyx_n_u_j __pyx_string_tab[55] -#define __pyx_n_u_length __pyx_string_tab[56] -#define __pyx_n_u_main __pyx_string_tab[57] -#define __pyx_n_u_module __pyx_string_tab[58] -#define __pyx_n_u_n_items __pyx_string_tab[59] -#define __pyx_n_u_name __pyx_string_tab[60] -#define __pyx_n_u_new __pyx_string_tab[61] -#define __pyx_n_u_next_position __pyx_string_tab[62] -#define __pyx_n_u_object __pyx_string_tab[63] -#define __pyx_n_u_pop __pyx_string_tab[64] -#define __pyx_n_u_pyx_checksum __pyx_string_tab[65] -#define __pyx_n_u_pyx_result __pyx_string_tab[66] -#define __pyx_n_u_pyx_state __pyx_string_tab[67] -#define __pyx_n_u_pyx_type __pyx_string_tab[68] -#define __pyx_n_u_pyx_unpickle_BufferedReader __pyx_string_tab[69] -#define __pyx_n_u_pyx_unpickle_BufferedSocketRea __pyx_string_tab[70] -#define __pyx_n_u_pyx_unpickle_CompressedBuffere __pyx_string_tab[71] -#define __pyx_n_u_qualname __pyx_string_tab[72] -#define __pyx_n_u_read __pyx_string_tab[73] -#define __pyx_n_u_read_block __pyx_string_tab[74] -#define __pyx_n_u_read_bytes __pyx_string_tab[75] -#define __pyx_n_u_read_fixed_strings __pyx_string_tab[76] -#define __pyx_n_u_read_fixed_strings_as_bytes __pyx_string_tab[77] -#define __pyx_n_u_read_into_buffer __pyx_string_tab[78] -#define __pyx_n_u_read_one __pyx_string_tab[79] -#define __pyx_n_u_read_strings __pyx_string_tab[80] -#define __pyx_n_u_recv_into __pyx_string_tab[81] -#define __pyx_n_u_reduce __pyx_string_tab[82] -#define __pyx_n_u_reduce_cython __pyx_string_tab[83] -#define __pyx_n_u_reduce_ex __pyx_string_tab[84] -#define __pyx_n_u_right __pyx_string_tab[85] -#define __pyx_n_u_rv __pyx_string_tab[86] -#define __pyx_n_u_self __pyx_string_tab[87] -#define __pyx_n_u_set_name __pyx_string_tab[88] -#define __pyx_n_u_setdefault __pyx_string_tab[89] -#define __pyx_n_u_setstate __pyx_string_tab[90] -#define __pyx_n_u_setstate_cython __pyx_string_tab[91] -#define __pyx_n_u_shift __pyx_string_tab[92] -#define __pyx_n_u_size __pyx_string_tab[93] -#define __pyx_n_u_sock __pyx_string_tab[94] -#define __pyx_n_u_state __pyx_string_tab[95] -#define __pyx_n_u_super __pyx_string_tab[96] -#define __pyx_n_u_t __pyx_string_tab[97] -#define __pyx_n_u_test __pyx_string_tab[98] -#define __pyx_n_u_unread __pyx_string_tab[99] -#define __pyx_n_u_update __pyx_string_tab[100] -#define __pyx_n_u_use_setstate __pyx_string_tab[101] -#define __pyx_n_u_values __pyx_string_tab[102] -#define __pyx_kp_b_iso88591_1A_4AT_a_0_1_xwaq_q_1_y_QfA_E_a __pyx_string_tab[103] -#define __pyx_kp_b_iso88591_2_6 __pyx_string_tab[104] -#define __pyx_kp_b_iso88591_6avQ __pyx_string_tab[105] -#define __pyx_kp_b_iso88591_AV1 __pyx_string_tab[106] -#define __pyx_kp_b_iso88591_A_1_r_Q_4q_A_A_5_WARt1_4AT_U_gRq __pyx_string_tab[107] -#define __pyx_kp_b_iso88591_A_4uJat1_4_Cq_1 __pyx_string_tab[108] -#define __pyx_kp_b_iso88591_A_4z_D_A_T_Q_M_q __pyx_string_tab[109] -#define __pyx_kp_b_iso88591_A_9Cq_4_31IQ_87_1_t5_aq_hl_7_A_4 __pyx_string_tab[110] -#define __pyx_kp_b_iso88591_A_Jiq_Kq_3at1_4_Cq_1 __pyx_string_tab[111] -#define __pyx_kp_b_iso88591_A_a __pyx_string_tab[112] -#define __pyx_kp_b_iso88591_A_t5_aq_1A_E_aq_AQhar_9A_Qa_AWCq __pyx_string_tab[113] -#define __pyx_kp_b_iso88591_T_4D_4q_G1F_a_vWE_Q_q_q_5T_GST __pyx_string_tab[114] -#define __pyx_kp_b_iso88591_T_4D_4q_G1F_a_vWE_Q_q_q_9_Qg_PW __pyx_string_tab[115] -#define __pyx_kp_b_iso88591_T_4D_G1F_a_vWE_Q_q_q_t1G_gQ_t1G __pyx_string_tab[116] -#define __pyx_kp_b_iso88591_q_0_kQR_7_0_1B_PQ_1 __pyx_string_tab[117] -#define __pyx_kp_b_iso88591_q_0_kQR_81A_7_VVdde_1 __pyx_string_tab[118] -#define __pyx_kp_b_iso88591_q_0_kQR_xq_7_6a7Nn_1 __pyx_string_tab[119] +#define __pyx_n_u_BufferedReader_read_strings_arro __pyx_string_tab[23] +#define __pyx_n_u_BufferedSocketReader __pyx_string_tab[24] +#define __pyx_n_u_BufferedSocketReader___reduce_cy __pyx_string_tab[25] +#define __pyx_n_u_BufferedSocketReader___setstate __pyx_string_tab[26] +#define __pyx_n_u_BufferedSocketReader_read_into_b __pyx_string_tab[27] +#define __pyx_n_u_CompressedBufferedReader __pyx_string_tab[28] +#define __pyx_n_u_CompressedBufferedReader___reduc __pyx_string_tab[29] +#define __pyx_n_u_CompressedBufferedReader___setst __pyx_string_tab[30] +#define __pyx_n_u_CompressedBufferedReader_read_in __pyx_string_tab[31] +#define __pyx_n_u_Pyx_PyDict_NextRef __pyx_string_tab[32] +#define __pyx_n_u_asyncio_coroutines __pyx_string_tab[33] +#define __pyx_n_u_b __pyx_string_tab[34] +#define __pyx_n_u_buffer_ptr __pyx_string_tab[35] +#define __pyx_n_u_bufsize __pyx_string_tab[36] +#define __pyx_n_u_bytes_read __pyx_string_tab[37] +#define __pyx_n_u_c_encoding __pyx_string_tab[38] +#define __pyx_n_u_c_string __pyx_string_tab[39] +#define __pyx_n_u_c_string_size __pyx_string_tab[40] +#define __pyx_n_u_clickhouse_driver_bufferedreader __pyx_string_tab[41] +#define __pyx_n_u_cline_in_traceback __pyx_string_tab[42] +#define __pyx_n_u_data __pyx_string_tab[43] +#define __pyx_n_u_data_capacity __pyx_string_tab[44] +#define __pyx_n_u_data_ptr __pyx_string_tab[45] +#define __pyx_n_u_data_size __pyx_string_tab[46] +#define __pyx_n_u_dict __pyx_string_tab[47] +#define __pyx_n_u_dict_2 __pyx_string_tab[48] +#define __pyx_n_u_encode __pyx_string_tab[49] +#define __pyx_n_u_encoding __pyx_string_tab[50] +#define __pyx_n_u_func __pyx_string_tab[51] +#define __pyx_n_u_getstate __pyx_string_tab[52] +#define __pyx_n_u_i __pyx_string_tab[53] +#define __pyx_n_u_init __pyx_string_tab[54] +#define __pyx_n_u_is_coroutine __pyx_string_tab[55] +#define __pyx_n_u_item __pyx_string_tab[56] +#define __pyx_n_u_items __pyx_string_tab[57] +#define __pyx_n_u_j __pyx_string_tab[58] +#define __pyx_n_u_length __pyx_string_tab[59] +#define __pyx_n_u_main __pyx_string_tab[60] +#define __pyx_n_u_module __pyx_string_tab[61] +#define __pyx_n_u_n_items __pyx_string_tab[62] +#define __pyx_n_u_name __pyx_string_tab[63] +#define __pyx_n_u_new __pyx_string_tab[64] +#define __pyx_n_u_next_position __pyx_string_tab[65] +#define __pyx_n_u_object __pyx_string_tab[66] +#define __pyx_n_u_offsets __pyx_string_tab[67] +#define __pyx_n_u_offsets_ptr __pyx_string_tab[68] +#define __pyx_n_u_pop __pyx_string_tab[69] +#define __pyx_n_u_pyx_checksum __pyx_string_tab[70] +#define __pyx_n_u_pyx_result __pyx_string_tab[71] +#define __pyx_n_u_pyx_state __pyx_string_tab[72] +#define __pyx_n_u_pyx_type __pyx_string_tab[73] +#define __pyx_n_u_pyx_unpickle_BufferedReader __pyx_string_tab[74] +#define __pyx_n_u_pyx_unpickle_BufferedSocketRea __pyx_string_tab[75] +#define __pyx_n_u_pyx_unpickle_CompressedBuffere __pyx_string_tab[76] +#define __pyx_n_u_qualname __pyx_string_tab[77] +#define __pyx_n_u_read __pyx_string_tab[78] +#define __pyx_n_u_read_block __pyx_string_tab[79] +#define __pyx_n_u_read_bytes __pyx_string_tab[80] +#define __pyx_n_u_read_fixed_strings __pyx_string_tab[81] +#define __pyx_n_u_read_fixed_strings_as_bytes __pyx_string_tab[82] +#define __pyx_n_u_read_into_buffer __pyx_string_tab[83] +#define __pyx_n_u_read_one __pyx_string_tab[84] +#define __pyx_n_u_read_strings __pyx_string_tab[85] +#define __pyx_n_u_read_strings_arrow __pyx_string_tab[86] +#define __pyx_n_u_recv_into __pyx_string_tab[87] +#define __pyx_n_u_reduce __pyx_string_tab[88] +#define __pyx_n_u_reduce_cython __pyx_string_tab[89] +#define __pyx_n_u_reduce_ex __pyx_string_tab[90] +#define __pyx_n_u_right __pyx_string_tab[91] +#define __pyx_n_u_rv __pyx_string_tab[92] +#define __pyx_n_u_self __pyx_string_tab[93] +#define __pyx_n_u_set_name __pyx_string_tab[94] +#define __pyx_n_u_setdefault __pyx_string_tab[95] +#define __pyx_n_u_setstate __pyx_string_tab[96] +#define __pyx_n_u_setstate_cython __pyx_string_tab[97] +#define __pyx_n_u_shift __pyx_string_tab[98] +#define __pyx_n_u_size __pyx_string_tab[99] +#define __pyx_n_u_sock __pyx_string_tab[100] +#define __pyx_n_u_state __pyx_string_tab[101] +#define __pyx_n_u_super __pyx_string_tab[102] +#define __pyx_n_u_t __pyx_string_tab[103] +#define __pyx_n_u_test __pyx_string_tab[104] +#define __pyx_n_u_unread __pyx_string_tab[105] +#define __pyx_n_u_update __pyx_string_tab[106] +#define __pyx_n_u_use_setstate __pyx_string_tab[107] +#define __pyx_n_u_values __pyx_string_tab[108] +#define __pyx_kp_b_iso88591_1A_4AT_a_0_1_xwaq_q_1_y_QfA_E_a __pyx_string_tab[109] +#define __pyx_kp_b_iso88591_2_6 __pyx_string_tab[110] +#define __pyx_kp_b_iso88591_6avQ __pyx_string_tab[111] +#define __pyx_kp_b_iso88591_AV1 __pyx_string_tab[112] +#define __pyx_kp_b_iso88591_A_1_r_Q_4q_A_A_5_WARt1_4AT_U_gRq __pyx_string_tab[113] +#define __pyx_kp_b_iso88591_A_4AT_2XRs_A_m3Gq_1E_A_0_Bb_XRq __pyx_string_tab[114] +#define __pyx_kp_b_iso88591_A_4uJat1_4_Cq_1 __pyx_string_tab[115] +#define __pyx_kp_b_iso88591_A_4z_D_A_T_Q_M_q __pyx_string_tab[116] +#define __pyx_kp_b_iso88591_A_9Cq_4_31IQ_87_1_t5_aq_hl_7_A_4 __pyx_string_tab[117] +#define __pyx_kp_b_iso88591_A_Jiq_Kq_3at1_4_Cq_1 __pyx_string_tab[118] +#define __pyx_kp_b_iso88591_A_a __pyx_string_tab[119] +#define __pyx_kp_b_iso88591_A_t5_aq_1A_E_aq_AQhar_9A_Qa_AWCq __pyx_string_tab[120] +#define __pyx_kp_b_iso88591_T_4D_4q_G1F_a_vWE_Q_q_q_5T_GST __pyx_string_tab[121] +#define __pyx_kp_b_iso88591_T_4D_4q_G1F_a_vWE_Q_q_q_9_Qg_PW __pyx_string_tab[122] +#define __pyx_kp_b_iso88591_T_4D_G1F_a_vWE_Q_q_q_t1G_gQ_t1G __pyx_string_tab[123] +#define __pyx_kp_b_iso88591_q_0_kQR_7_0_1B_PQ_1 __pyx_string_tab[124] +#define __pyx_kp_b_iso88591_q_0_kQR_81A_7_VVdde_1 __pyx_string_tab[125] +#define __pyx_kp_b_iso88591_q_0_kQR_xq_7_6a7Nn_1 __pyx_string_tab[126] #define __pyx_int_72267464 __pyx_number_tab[0] #define __pyx_int_98621312 __pyx_number_tab[1] #define __pyx_int_110699518 __pyx_number_tab[2] @@ -2858,8 +2879,8 @@ static CYTHON_SMALL_CODE int __pyx_m_clear(PyObject *m) { Py_CLEAR(clear_module_state->__pyx_ptype_17clickhouse_driver_14bufferedreader_CompressedBufferedReader); Py_CLEAR(clear_module_state->__pyx_type_17clickhouse_driver_14bufferedreader_CompressedBufferedReader); for (int i=0; i<4; ++i) { Py_CLEAR(clear_module_state->__pyx_tuple[i]); } - for (int i=0; i<17; ++i) { Py_CLEAR(clear_module_state->__pyx_codeobj_tab[i]); } - for (int i=0; i<120; ++i) { Py_CLEAR(clear_module_state->__pyx_string_tab[i]); } + for (int i=0; i<18; ++i) { Py_CLEAR(clear_module_state->__pyx_codeobj_tab[i]); } + for (int i=0; i<127; ++i) { Py_CLEAR(clear_module_state->__pyx_string_tab[i]); } for (int i=0; i<3; ++i) { Py_CLEAR(clear_module_state->__pyx_number_tab[i]); } /* #### Code section: module_state_clear_contents ### */ /* CommonTypesMetaclass.module_state_clear */ @@ -2893,8 +2914,8 @@ static CYTHON_SMALL_CODE int __pyx_m_traverse(PyObject *m, visitproc visit, void Py_VISIT(traverse_module_state->__pyx_ptype_17clickhouse_driver_14bufferedreader_CompressedBufferedReader); Py_VISIT(traverse_module_state->__pyx_type_17clickhouse_driver_14bufferedreader_CompressedBufferedReader); for (int i=0; i<4; ++i) { __Pyx_VISIT_CONST(traverse_module_state->__pyx_tuple[i]); } - for (int i=0; i<17; ++i) { __Pyx_VISIT_CONST(traverse_module_state->__pyx_codeobj_tab[i]); } - for (int i=0; i<120; ++i) { __Pyx_VISIT_CONST(traverse_module_state->__pyx_string_tab[i]); } + for (int i=0; i<18; ++i) { __Pyx_VISIT_CONST(traverse_module_state->__pyx_codeobj_tab[i]); } + for (int i=0; i<127; ++i) { __Pyx_VISIT_CONST(traverse_module_state->__pyx_string_tab[i]); } for (int i=0; i<3; ++i) { __Pyx_VISIT_CONST(traverse_module_state->__pyx_number_tab[i]); } /* #### Code section: module_state_traverse_contents ### */ /* CommonTypesMetaclass.module_state_traverse */ @@ -5055,7 +5076,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ * * return items # <<<<<<<<<<<<<< * - * def read_fixed_strings_as_bytes(self, Py_ssize_t n_items, + * def read_strings_arrow(self, unsigned long long n_items): */ __Pyx_XDECREF(__pyx_r); __Pyx_INCREF(__pyx_v_items); @@ -5090,21 +5111,711 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ /* "clickhouse_driver/bufferedreader.pyx":179 * return items * + * def read_strings_arrow(self, unsigned long long n_items): # <<<<<<<<<<<<<< + * """ + * Reads ``n_items`` varint-prefixed strings into Arrow-style +*/ + +/* Python wrapper */ +static PyObject *__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_11read_strings_arrow(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +); /*proto*/ +PyDoc_STRVAR(__pyx_doc_17clickhouse_driver_14bufferedreader_14BufferedReader_10read_strings_arrow, "\n Reads ``n_items`` varint-prefixed strings into Arrow-style\n buffers without creating per-string Python objects.\n\n Returns (offsets, data) pair of bytearrays: ``offsets`` holds\n ``n_items + 1`` little-endian int64 values, ``data`` holds\n concatenated string bytes.\n "); +static PyMethodDef __pyx_mdef_17clickhouse_driver_14bufferedreader_14BufferedReader_11read_strings_arrow = {"read_strings_arrow", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_11read_strings_arrow, __Pyx_METH_FASTCALL|METH_KEYWORDS, __pyx_doc_17clickhouse_driver_14bufferedreader_14BufferedReader_10read_strings_arrow}; +static PyObject *__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_11read_strings_arrow(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +) { + unsigned PY_LONG_LONG __pyx_v_n_items; + #if !CYTHON_METH_FASTCALL + CYTHON_UNUSED Py_ssize_t __pyx_nargs; + #endif + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject* values[1] = {0}; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("read_strings_arrow (wrapper)", 0); + #if !CYTHON_METH_FASTCALL + #if CYTHON_ASSUME_SAFE_SIZE + __pyx_nargs = PyTuple_GET_SIZE(__pyx_args); + #else + __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL; + #endif + #endif + __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs); + { + PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_n_items,0}; + const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0; + if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 179, __pyx_L3_error) + if (__pyx_kwds_len > 0) { + switch (__pyx_nargs) { + case 1: + values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 179, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + const Py_ssize_t kwd_pos_args = __pyx_nargs; + if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "read_strings_arrow", 0) < (0)) __PYX_ERR(0, 179, __pyx_L3_error) + for (Py_ssize_t i = __pyx_nargs; i < 1; i++) { + if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("read_strings_arrow", 1, 1, 1, i); __PYX_ERR(0, 179, __pyx_L3_error) } + } + } else if (unlikely(__pyx_nargs != 1)) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 179, __pyx_L3_error) + } + __pyx_v_n_items = __Pyx_PyLong_As_unsigned_PY_LONG_LONG(values[0]); if (unlikely((__pyx_v_n_items == (unsigned PY_LONG_LONG)-1) && PyErr_Occurred())) __PYX_ERR(0, 179, __pyx_L3_error) + } + goto __pyx_L6_skip; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("read_strings_arrow", 1, 1, 1, __pyx_nargs); __PYX_ERR(0, 179, __pyx_L3_error) + __pyx_L6_skip:; + goto __pyx_L4_argument_unpacking_done; + __pyx_L3_error:; + for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { + Py_XDECREF(values[__pyx_temp]); + } + __Pyx_AddTraceback("clickhouse_driver.bufferedreader.BufferedReader.read_strings_arrow", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_10read_strings_arrow(((struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *)__pyx_v_self), __pyx_v_n_items); + + /* function exit code */ + for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { + Py_XDECREF(values[__pyx_temp]); + } + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_10read_strings_arrow(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self, unsigned PY_LONG_LONG __pyx_v_n_items) { + unsigned PY_LONG_LONG __pyx_v_i; + char *__pyx_v_buffer_ptr; + unsigned PY_LONG_LONG __pyx_v_right; + unsigned PY_LONG_LONG __pyx_v_size; + unsigned PY_LONG_LONG __pyx_v_shift; + unsigned PY_LONG_LONG __pyx_v_bytes_read; + unsigned PY_LONG_LONG __pyx_v_b; + PyObject *__pyx_v_offsets = NULL; + PY_LONG_LONG *__pyx_v_offsets_ptr; + unsigned PY_LONG_LONG __pyx_v_data_size; + unsigned PY_LONG_LONG __pyx_v_data_capacity; + PyObject *__pyx_v_data = NULL; + char *__pyx_v_data_ptr; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + size_t __pyx_t_4; + unsigned PY_LONG_LONG __pyx_t_5; + int __pyx_t_6; + unsigned PY_LONG_LONG __pyx_t_7; + unsigned PY_LONG_LONG __pyx_t_8; + int __pyx_t_9; + unsigned PY_LONG_LONG __pyx_t_10; + unsigned PY_LONG_LONG __pyx_t_11; + unsigned PY_LONG_LONG __pyx_t_12; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("read_strings_arrow", 0); + + /* "clickhouse_driver/bufferedreader.pyx":190 + * cdef unsigned long long i + * # Buffer vars + * cdef char* buffer_ptr = PyByteArray_AsString(self.buffer) # <<<<<<<<<<<<<< + * cdef unsigned long long right + * # String length vars +*/ + __pyx_t_1 = __pyx_v_self->buffer; + __Pyx_INCREF(__pyx_t_1); + __pyx_v_buffer_ptr = PyByteArray_AsString(__pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "clickhouse_driver/bufferedreader.pyx":196 + * cdef unsigned long long b + * + * offsets = bytearray((n_items + 1) * 8) # <<<<<<<<<<<<<< + * cdef long long* offsets_ptr = PyByteArray_AsString( + * offsets +*/ + __pyx_t_2 = NULL; + __pyx_t_3 = __Pyx_PyLong_From_unsigned_PY_LONG_LONG(((__pyx_v_n_items + 1) * 8)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 196, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = 1; + { + PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_3}; + __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)(&PyByteArray_Type), __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 196, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + } + __pyx_v_offsets = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "clickhouse_driver/bufferedreader.pyx":197 + * + * offsets = bytearray((n_items + 1) * 8) + * cdef long long* offsets_ptr = PyByteArray_AsString( # <<<<<<<<<<<<<< + * offsets + * ) +*/ + __pyx_v_offsets_ptr = ((PY_LONG_LONG *)PyByteArray_AsString(__pyx_v_offsets)); + + /* "clickhouse_driver/bufferedreader.pyx":200 + * offsets + * ) + * offsets_ptr[0] = 0 # <<<<<<<<<<<<<< + * + * cdef unsigned long long data_size = 0 +*/ + (__pyx_v_offsets_ptr[0]) = 0; + + /* "clickhouse_driver/bufferedreader.pyx":202 + * offsets_ptr[0] = 0 + * + * cdef unsigned long long data_size = 0 # <<<<<<<<<<<<<< + * cdef unsigned long long data_capacity = 65536 if \ + * n_items * 8 < 65536 else n_items * 8 +*/ + __pyx_v_data_size = 0; + + /* "clickhouse_driver/bufferedreader.pyx":204 + * cdef unsigned long long data_size = 0 + * cdef unsigned long long data_capacity = 65536 if \ + * n_items * 8 < 65536 else n_items * 8 # <<<<<<<<<<<<<< + * data = bytearray(data_capacity) + * cdef char* data_ptr = PyByteArray_AsString(data) +*/ + __pyx_t_6 = ((__pyx_v_n_items * 8) < 0x10000); + if (__pyx_t_6) { + __pyx_t_5 = 0x10000; + } else { + __pyx_t_5 = (__pyx_v_n_items * 8); + } + __pyx_v_data_capacity = __pyx_t_5; + + /* "clickhouse_driver/bufferedreader.pyx":205 + * cdef unsigned long long data_capacity = 65536 if \ + * n_items * 8 < 65536 else n_items * 8 + * data = bytearray(data_capacity) # <<<<<<<<<<<<<< + * cdef char* data_ptr = PyByteArray_AsString(data) + * +*/ + __pyx_t_3 = NULL; + __pyx_t_2 = __Pyx_PyLong_From_unsigned_PY_LONG_LONG(__pyx_v_data_capacity); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 205, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = 1; + { + PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_t_2}; + __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)(&PyByteArray_Type), __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 205, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + } + __pyx_v_data = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "clickhouse_driver/bufferedreader.pyx":206 + * n_items * 8 < 65536 else n_items * 8 + * data = bytearray(data_capacity) + * cdef char* data_ptr = PyByteArray_AsString(data) # <<<<<<<<<<<<<< + * + * for i in range(n_items): +*/ + __pyx_v_data_ptr = PyByteArray_AsString(__pyx_v_data); + + /* "clickhouse_driver/bufferedreader.pyx":208 + * cdef char* data_ptr = PyByteArray_AsString(data) + * + * for i in range(n_items): # <<<<<<<<<<<<<< + * shift = size = 0 + * +*/ + __pyx_t_5 = __pyx_v_n_items; + __pyx_t_7 = __pyx_t_5; + for (__pyx_t_8 = 0; __pyx_t_8 < __pyx_t_7; __pyx_t_8+=1) { + __pyx_v_i = __pyx_t_8; + + /* "clickhouse_driver/bufferedreader.pyx":209 + * + * for i in range(n_items): + * shift = size = 0 # <<<<<<<<<<<<<< + * + * # Read string size +*/ + __pyx_v_shift = 0; + __pyx_v_size = 0; + + /* "clickhouse_driver/bufferedreader.pyx":212 + * + * # Read string size + * while True: # <<<<<<<<<<<<<< + * if self.position == self.current_buffer_size: + * self.read_into_buffer() +*/ + while (1) { + + /* "clickhouse_driver/bufferedreader.pyx":213 + * # Read string size + * while True: + * if self.position == self.current_buffer_size: # <<<<<<<<<<<<<< + * self.read_into_buffer() + * # `read_into_buffer` can override buffer +*/ + __pyx_t_6 = (__pyx_v_self->position == __pyx_v_self->current_buffer_size); + if (__pyx_t_6) { + + /* "clickhouse_driver/bufferedreader.pyx":214 + * while True: + * if self.position == self.current_buffer_size: + * self.read_into_buffer() # <<<<<<<<<<<<<< + * # `read_into_buffer` can override buffer + * buffer_ptr = PyByteArray_AsString(self.buffer) +*/ + __pyx_t_2 = ((PyObject *)__pyx_v_self); + __Pyx_INCREF(__pyx_t_2); + __pyx_t_4 = 0; + { + PyObject *__pyx_callargs[2] = {__pyx_t_2, NULL}; + __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_read_into_buffer, __pyx_callargs+__pyx_t_4, (1-__pyx_t_4) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 214, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + } + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "clickhouse_driver/bufferedreader.pyx":216 + * self.read_into_buffer() + * # `read_into_buffer` can override buffer + * buffer_ptr = PyByteArray_AsString(self.buffer) # <<<<<<<<<<<<<< + * self.position = 0 + * +*/ + __pyx_t_1 = __pyx_v_self->buffer; + __Pyx_INCREF(__pyx_t_1); + __pyx_v_buffer_ptr = PyByteArray_AsString(__pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "clickhouse_driver/bufferedreader.pyx":217 + * # `read_into_buffer` can override buffer + * buffer_ptr = PyByteArray_AsString(self.buffer) + * self.position = 0 # <<<<<<<<<<<<<< + * + * b = buffer_ptr[self.position] +*/ + __pyx_v_self->position = 0; + + /* "clickhouse_driver/bufferedreader.pyx":213 + * # Read string size + * while True: + * if self.position == self.current_buffer_size: # <<<<<<<<<<<<<< + * self.read_into_buffer() + * # `read_into_buffer` can override buffer +*/ + } + + /* "clickhouse_driver/bufferedreader.pyx":219 + * self.position = 0 + * + * b = buffer_ptr[self.position] # <<<<<<<<<<<<<< + * self.position += 1 + * +*/ + __pyx_v_b = (__pyx_v_buffer_ptr[__pyx_v_self->position]); + + /* "clickhouse_driver/bufferedreader.pyx":220 + * + * b = buffer_ptr[self.position] + * self.position += 1 # <<<<<<<<<<<<<< + * + * size |= (b & 0x7f) << shift +*/ + __pyx_v_self->position = (__pyx_v_self->position + 1); + + /* "clickhouse_driver/bufferedreader.pyx":222 + * self.position += 1 + * + * size |= (b & 0x7f) << shift # <<<<<<<<<<<<<< + * if b < 0x80: + * break +*/ + __pyx_v_size = (__pyx_v_size | ((__pyx_v_b & 0x7f) << __pyx_v_shift)); + + /* "clickhouse_driver/bufferedreader.pyx":223 + * + * size |= (b & 0x7f) << shift + * if b < 0x80: # <<<<<<<<<<<<<< + * break + * +*/ + __pyx_t_6 = (__pyx_v_b < 0x80); + if (__pyx_t_6) { + + /* "clickhouse_driver/bufferedreader.pyx":224 + * size |= (b & 0x7f) << shift + * if b < 0x80: + * break # <<<<<<<<<<<<<< + * + * shift += 7 +*/ + goto __pyx_L6_break; + + /* "clickhouse_driver/bufferedreader.pyx":223 + * + * size |= (b & 0x7f) << shift + * if b < 0x80: # <<<<<<<<<<<<<< + * break + * +*/ + } + + /* "clickhouse_driver/bufferedreader.pyx":226 + * break + * + * shift += 7 # <<<<<<<<<<<<<< + * + * if data_size + size > data_capacity: +*/ + __pyx_v_shift = (__pyx_v_shift + 7); + } + __pyx_L6_break:; + + /* "clickhouse_driver/bufferedreader.pyx":228 + * shift += 7 + * + * if data_size + size > data_capacity: # <<<<<<<<<<<<<< + * while data_capacity < data_size + size: + * data_capacity *= 2 +*/ + __pyx_t_6 = ((__pyx_v_data_size + __pyx_v_size) > __pyx_v_data_capacity); + if (__pyx_t_6) { + + /* "clickhouse_driver/bufferedreader.pyx":229 + * + * if data_size + size > data_capacity: + * while data_capacity < data_size + size: # <<<<<<<<<<<<<< + * data_capacity *= 2 + * PyByteArray_Resize(data, data_capacity) +*/ + while (1) { + __pyx_t_6 = (__pyx_v_data_capacity < (__pyx_v_data_size + __pyx_v_size)); + if (!__pyx_t_6) break; + + /* "clickhouse_driver/bufferedreader.pyx":230 + * if data_size + size > data_capacity: + * while data_capacity < data_size + size: + * data_capacity *= 2 # <<<<<<<<<<<<<< + * PyByteArray_Resize(data, data_capacity) + * data_ptr = PyByteArray_AsString(data) +*/ + __pyx_v_data_capacity = (__pyx_v_data_capacity * 2); + } + + /* "clickhouse_driver/bufferedreader.pyx":231 + * while data_capacity < data_size + size: + * data_capacity *= 2 + * PyByteArray_Resize(data, data_capacity) # <<<<<<<<<<<<<< + * data_ptr = PyByteArray_AsString(data) + * +*/ + __pyx_t_9 = PyByteArray_Resize(__pyx_v_data, __pyx_v_data_capacity); if (unlikely(__pyx_t_9 == ((int)-1))) __PYX_ERR(0, 231, __pyx_L1_error) + + /* "clickhouse_driver/bufferedreader.pyx":232 + * data_capacity *= 2 + * PyByteArray_Resize(data, data_capacity) + * data_ptr = PyByteArray_AsString(data) # <<<<<<<<<<<<<< + * + * right = self.position + size +*/ + __pyx_v_data_ptr = PyByteArray_AsString(__pyx_v_data); + + /* "clickhouse_driver/bufferedreader.pyx":228 + * shift += 7 + * + * if data_size + size > data_capacity: # <<<<<<<<<<<<<< + * while data_capacity < data_size + size: + * data_capacity *= 2 +*/ + } + + /* "clickhouse_driver/bufferedreader.pyx":234 + * data_ptr = PyByteArray_AsString(data) + * + * right = self.position + size # <<<<<<<<<<<<<< + * + * if right > self.current_buffer_size: +*/ + __pyx_v_right = (__pyx_v_self->position + __pyx_v_size); + + /* "clickhouse_driver/bufferedreader.pyx":236 + * right = self.position + size + * + * if right > self.current_buffer_size: # <<<<<<<<<<<<<< + * # String spans multiple reader buffers. + * bytes_read = self.current_buffer_size - self.position +*/ + __pyx_t_6 = (__pyx_v_right > __pyx_v_self->current_buffer_size); + if (__pyx_t_6) { + + /* "clickhouse_driver/bufferedreader.pyx":238 + * if right > self.current_buffer_size: + * # String spans multiple reader buffers. + * bytes_read = self.current_buffer_size - self.position # <<<<<<<<<<<<<< + * memcpy(&data_ptr[data_size], &buffer_ptr[self.position], + * bytes_read) +*/ + __pyx_v_bytes_read = (__pyx_v_self->current_buffer_size - __pyx_v_self->position); + + /* "clickhouse_driver/bufferedreader.pyx":239 + * # String spans multiple reader buffers. + * bytes_read = self.current_buffer_size - self.position + * memcpy(&data_ptr[data_size], &buffer_ptr[self.position], # <<<<<<<<<<<<<< + * bytes_read) + * +*/ + (void)(memcpy((&(__pyx_v_data_ptr[__pyx_v_data_size])), (&(__pyx_v_buffer_ptr[__pyx_v_self->position])), __pyx_v_bytes_read)); + + /* "clickhouse_driver/bufferedreader.pyx":242 + * bytes_read) + * + * while bytes_read != size: # <<<<<<<<<<<<<< + * self.position = size - bytes_read + * +*/ + while (1) { + __pyx_t_6 = (__pyx_v_bytes_read != __pyx_v_size); + if (!__pyx_t_6) break; + + /* "clickhouse_driver/bufferedreader.pyx":243 + * + * while bytes_read != size: + * self.position = size - bytes_read # <<<<<<<<<<<<<< + * + * self.read_into_buffer() +*/ + __pyx_v_self->position = (__pyx_v_size - __pyx_v_bytes_read); + + /* "clickhouse_driver/bufferedreader.pyx":245 + * self.position = size - bytes_read + * + * self.read_into_buffer() # <<<<<<<<<<<<<< + * # `read_into_buffer` can override buffer + * buffer_ptr = PyByteArray_AsString(self.buffer) +*/ + __pyx_t_2 = ((PyObject *)__pyx_v_self); + __Pyx_INCREF(__pyx_t_2); + __pyx_t_4 = 0; + { + PyObject *__pyx_callargs[2] = {__pyx_t_2, NULL}; + __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_read_into_buffer, __pyx_callargs+__pyx_t_4, (1-__pyx_t_4) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 245, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + } + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "clickhouse_driver/bufferedreader.pyx":247 + * self.read_into_buffer() + * # `read_into_buffer` can override buffer + * buffer_ptr = PyByteArray_AsString(self.buffer) # <<<<<<<<<<<<<< + * # There can be not enough data in buffer. + * self.position = min( +*/ + __pyx_t_1 = __pyx_v_self->buffer; + __Pyx_INCREF(__pyx_t_1); + __pyx_v_buffer_ptr = PyByteArray_AsString(__pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "clickhouse_driver/bufferedreader.pyx":250 + * # There can be not enough data in buffer. + * self.position = min( + * self.position, self.current_buffer_size # <<<<<<<<<<<<<< + * ) + * memcpy(&data_ptr[data_size + bytes_read], buffer_ptr, +*/ + __pyx_t_10 = __pyx_v_self->current_buffer_size; + __pyx_t_11 = __pyx_v_self->position; + __pyx_t_6 = (__pyx_t_10 < __pyx_t_11); + if (__pyx_t_6) { + __pyx_t_12 = __pyx_t_10; + } else { + __pyx_t_12 = __pyx_t_11; + } + + /* "clickhouse_driver/bufferedreader.pyx":249 + * buffer_ptr = PyByteArray_AsString(self.buffer) + * # There can be not enough data in buffer. + * self.position = min( # <<<<<<<<<<<<<< + * self.position, self.current_buffer_size + * ) +*/ + __pyx_v_self->position = __pyx_t_12; + + /* "clickhouse_driver/bufferedreader.pyx":252 + * self.position, self.current_buffer_size + * ) + * memcpy(&data_ptr[data_size + bytes_read], buffer_ptr, # <<<<<<<<<<<<<< + * self.position) + * bytes_read += self.position +*/ + (void)(memcpy((&(__pyx_v_data_ptr[(__pyx_v_data_size + __pyx_v_bytes_read)])), __pyx_v_buffer_ptr, __pyx_v_self->position)); + + /* "clickhouse_driver/bufferedreader.pyx":254 + * memcpy(&data_ptr[data_size + bytes_read], buffer_ptr, + * self.position) + * bytes_read += self.position # <<<<<<<<<<<<<< + * + * else: +*/ + __pyx_v_bytes_read = (__pyx_v_bytes_read + __pyx_v_self->position); + } + + /* "clickhouse_driver/bufferedreader.pyx":236 + * right = self.position + size + * + * if right > self.current_buffer_size: # <<<<<<<<<<<<<< + * # String spans multiple reader buffers. + * bytes_read = self.current_buffer_size - self.position +*/ + goto __pyx_L12; + } + + /* "clickhouse_driver/bufferedreader.pyx":257 + * + * else: + * memcpy(&data_ptr[data_size], &buffer_ptr[self.position], # <<<<<<<<<<<<<< + * size) + * self.position = right +*/ + /*else*/ { + + /* "clickhouse_driver/bufferedreader.pyx":258 + * else: + * memcpy(&data_ptr[data_size], &buffer_ptr[self.position], + * size) # <<<<<<<<<<<<<< + * self.position = right + * +*/ + (void)(memcpy((&(__pyx_v_data_ptr[__pyx_v_data_size])), (&(__pyx_v_buffer_ptr[__pyx_v_self->position])), __pyx_v_size)); + + /* "clickhouse_driver/bufferedreader.pyx":259 + * memcpy(&data_ptr[data_size], &buffer_ptr[self.position], + * size) + * self.position = right # <<<<<<<<<<<<<< + * + * data_size += size +*/ + __pyx_v_self->position = __pyx_v_right; + } + __pyx_L12:; + + /* "clickhouse_driver/bufferedreader.pyx":261 + * self.position = right + * + * data_size += size # <<<<<<<<<<<<<< + * offsets_ptr[i + 1] = data_size + * +*/ + __pyx_v_data_size = (__pyx_v_data_size + __pyx_v_size); + + /* "clickhouse_driver/bufferedreader.pyx":262 + * + * data_size += size + * offsets_ptr[i + 1] = data_size # <<<<<<<<<<<<<< + * + * PyByteArray_Resize(data, data_size) +*/ + (__pyx_v_offsets_ptr[(__pyx_v_i + 1)]) = ((PY_LONG_LONG)__pyx_v_data_size); + } + + /* "clickhouse_driver/bufferedreader.pyx":264 + * offsets_ptr[i + 1] = data_size + * + * PyByteArray_Resize(data, data_size) # <<<<<<<<<<<<<< + * return offsets, data + * +*/ + __pyx_t_9 = PyByteArray_Resize(__pyx_v_data, __pyx_v_data_size); if (unlikely(__pyx_t_9 == ((int)-1))) __PYX_ERR(0, 264, __pyx_L1_error) + + /* "clickhouse_driver/bufferedreader.pyx":265 + * + * PyByteArray_Resize(data, data_size) + * return offsets, data # <<<<<<<<<<<<<< + * + * def read_fixed_strings_as_bytes(self, Py_ssize_t n_items, +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 265, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v_offsets); + __Pyx_GIVEREF(__pyx_v_offsets); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_offsets) != (0)) __PYX_ERR(0, 265, __pyx_L1_error); + __Pyx_INCREF(__pyx_v_data); + __Pyx_GIVEREF(__pyx_v_data); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_data) != (0)) __PYX_ERR(0, 265, __pyx_L1_error); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "clickhouse_driver/bufferedreader.pyx":179 + * return items + * + * def read_strings_arrow(self, unsigned long long n_items): # <<<<<<<<<<<<<< + * """ + * Reads ``n_items`` varint-prefixed strings into Arrow-style +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_AddTraceback("clickhouse_driver.bufferedreader.BufferedReader.read_strings_arrow", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_offsets); + __Pyx_XDECREF(__pyx_v_data); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "clickhouse_driver/bufferedreader.pyx":267 + * return offsets, data + * * def read_fixed_strings_as_bytes(self, Py_ssize_t n_items, # <<<<<<<<<<<<<< * Py_ssize_t length): * cdef Py_ssize_t i */ /* Python wrapper */ -static PyObject *__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_11read_fixed_strings_as_bytes(PyObject *__pyx_v_self, +static PyObject *__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_13read_fixed_strings_as_bytes(PyObject *__pyx_v_self, #if CYTHON_METH_FASTCALL PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds #else PyObject *__pyx_args, PyObject *__pyx_kwds #endif ); /*proto*/ -static PyMethodDef __pyx_mdef_17clickhouse_driver_14bufferedreader_14BufferedReader_11read_fixed_strings_as_bytes = {"read_fixed_strings_as_bytes", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_11read_fixed_strings_as_bytes, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}; -static PyObject *__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_11read_fixed_strings_as_bytes(PyObject *__pyx_v_self, +static PyMethodDef __pyx_mdef_17clickhouse_driver_14bufferedreader_14BufferedReader_13read_fixed_strings_as_bytes = {"read_fixed_strings_as_bytes", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_13read_fixed_strings_as_bytes, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_13read_fixed_strings_as_bytes(PyObject *__pyx_v_self, #if CYTHON_METH_FASTCALL PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds #else @@ -5135,39 +5846,39 @@ PyObject *__pyx_args, PyObject *__pyx_kwds { PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_n_items,&__pyx_mstate_global->__pyx_n_u_length,0}; const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0; - if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 179, __pyx_L3_error) + if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 267, __pyx_L3_error) if (__pyx_kwds_len > 0) { switch (__pyx_nargs) { case 2: values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1); - if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 179, __pyx_L3_error) + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 267, __pyx_L3_error) CYTHON_FALLTHROUGH; case 1: values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0); - if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 179, __pyx_L3_error) + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 267, __pyx_L3_error) CYTHON_FALLTHROUGH; case 0: break; default: goto __pyx_L5_argtuple_error; } const Py_ssize_t kwd_pos_args = __pyx_nargs; - if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "read_fixed_strings_as_bytes", 0) < (0)) __PYX_ERR(0, 179, __pyx_L3_error) + if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "read_fixed_strings_as_bytes", 0) < (0)) __PYX_ERR(0, 267, __pyx_L3_error) for (Py_ssize_t i = __pyx_nargs; i < 2; i++) { - if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("read_fixed_strings_as_bytes", 1, 2, 2, i); __PYX_ERR(0, 179, __pyx_L3_error) } + if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("read_fixed_strings_as_bytes", 1, 2, 2, i); __PYX_ERR(0, 267, __pyx_L3_error) } } } else if (unlikely(__pyx_nargs != 2)) { goto __pyx_L5_argtuple_error; } else { values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0); - if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 179, __pyx_L3_error) + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 267, __pyx_L3_error) values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1); - if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 179, __pyx_L3_error) + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 267, __pyx_L3_error) } - __pyx_v_n_items = __Pyx_PyIndex_AsSsize_t(values[0]); if (unlikely((__pyx_v_n_items == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 179, __pyx_L3_error) - __pyx_v_length = __Pyx_PyIndex_AsSsize_t(values[1]); if (unlikely((__pyx_v_length == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 180, __pyx_L3_error) + __pyx_v_n_items = __Pyx_PyIndex_AsSsize_t(values[0]); if (unlikely((__pyx_v_n_items == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 267, __pyx_L3_error) + __pyx_v_length = __Pyx_PyIndex_AsSsize_t(values[1]); if (unlikely((__pyx_v_length == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 268, __pyx_L3_error) } goto __pyx_L6_skip; __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("read_fixed_strings_as_bytes", 1, 2, 2, __pyx_nargs); __PYX_ERR(0, 179, __pyx_L3_error) + __Pyx_RaiseArgtupleInvalid("read_fixed_strings_as_bytes", 1, 2, 2, __pyx_nargs); __PYX_ERR(0, 267, __pyx_L3_error) __pyx_L6_skip:; goto __pyx_L4_argument_unpacking_done; __pyx_L3_error:; @@ -5178,7 +5889,7 @@ PyObject *__pyx_args, PyObject *__pyx_kwds __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; - __pyx_r = __pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_10read_fixed_strings_as_bytes(((struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *)__pyx_v_self), __pyx_v_n_items, __pyx_v_length); + __pyx_r = __pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_12read_fixed_strings_as_bytes(((struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *)__pyx_v_self), __pyx_v_n_items, __pyx_v_length); /* function exit code */ for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { @@ -5188,7 +5899,7 @@ PyObject *__pyx_args, PyObject *__pyx_kwds return __pyx_r; } -static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_10read_fixed_strings_as_bytes(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self, Py_ssize_t __pyx_v_n_items, Py_ssize_t __pyx_v_length) { +static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_12read_fixed_strings_as_bytes(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self, Py_ssize_t __pyx_v_n_items, Py_ssize_t __pyx_v_length) { Py_ssize_t __pyx_v_i; PyObject *__pyx_v_data = NULL; char *__pyx_v_data_ptr; @@ -5209,7 +5920,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ int __pyx_clineno = 0; __Pyx_RefNannySetupContext("read_fixed_strings_as_bytes", 0); - /* "clickhouse_driver/bufferedreader.pyx":182 + /* "clickhouse_driver/bufferedreader.pyx":270 * Py_ssize_t length): * cdef Py_ssize_t i * data = self.read(length * n_items) # <<<<<<<<<<<<<< @@ -5218,7 +5929,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ */ __pyx_t_2 = ((PyObject *)__pyx_v_self); __Pyx_INCREF(__pyx_t_2); - __pyx_t_3 = PyLong_FromSsize_t((__pyx_v_length * __pyx_v_n_items)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 182, __pyx_L1_error) + __pyx_t_3 = PyLong_FromSsize_t((__pyx_v_length * __pyx_v_n_items)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 270, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = 0; { @@ -5226,35 +5937,35 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_read, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 182, __pyx_L1_error) + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 270, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); } __pyx_v_data = __pyx_t_1; __pyx_t_1 = 0; - /* "clickhouse_driver/bufferedreader.pyx":183 + /* "clickhouse_driver/bufferedreader.pyx":271 * cdef Py_ssize_t i * data = self.read(length * n_items) * cdef char* data_ptr = PyBytes_AsString(data) # <<<<<<<<<<<<<< * * items = PyTuple_New(n_items) */ - __pyx_t_5 = PyBytes_AsString(__pyx_v_data); if (unlikely(__pyx_t_5 == ((void *)NULL))) __PYX_ERR(0, 183, __pyx_L1_error) + __pyx_t_5 = PyBytes_AsString(__pyx_v_data); if (unlikely(__pyx_t_5 == ((void *)NULL))) __PYX_ERR(0, 271, __pyx_L1_error) __pyx_v_data_ptr = __pyx_t_5; - /* "clickhouse_driver/bufferedreader.pyx":185 + /* "clickhouse_driver/bufferedreader.pyx":273 * cdef char* data_ptr = PyBytes_AsString(data) * * items = PyTuple_New(n_items) # <<<<<<<<<<<<<< * for i in range(n_items): * item = PyBytes_FromStringAndSize(&data_ptr[i * length], length) */ - __pyx_t_1 = PyTuple_New(__pyx_v_n_items); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 185, __pyx_L1_error) + __pyx_t_1 = PyTuple_New(__pyx_v_n_items); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 273, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_v_items = ((PyObject*)__pyx_t_1); __pyx_t_1 = 0; - /* "clickhouse_driver/bufferedreader.pyx":186 + /* "clickhouse_driver/bufferedreader.pyx":274 * * items = PyTuple_New(n_items) * for i in range(n_items): # <<<<<<<<<<<<<< @@ -5266,19 +5977,19 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ for (__pyx_t_8 = 0; __pyx_t_8 < __pyx_t_7; __pyx_t_8+=1) { __pyx_v_i = __pyx_t_8; - /* "clickhouse_driver/bufferedreader.pyx":187 + /* "clickhouse_driver/bufferedreader.pyx":275 * items = PyTuple_New(n_items) * for i in range(n_items): * item = PyBytes_FromStringAndSize(&data_ptr[i * length], length) # <<<<<<<<<<<<<< * Py_INCREF(item) * PyTuple_SET_ITEM(items, i, item) */ - __pyx_t_1 = PyBytes_FromStringAndSize((&(__pyx_v_data_ptr[(__pyx_v_i * __pyx_v_length)])), __pyx_v_length); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 187, __pyx_L1_error) + __pyx_t_1 = PyBytes_FromStringAndSize((&(__pyx_v_data_ptr[(__pyx_v_i * __pyx_v_length)])), __pyx_v_length); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 275, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_XDECREF_SET(__pyx_v_item, ((PyObject*)__pyx_t_1)); __pyx_t_1 = 0; - /* "clickhouse_driver/bufferedreader.pyx":188 + /* "clickhouse_driver/bufferedreader.pyx":276 * for i in range(n_items): * item = PyBytes_FromStringAndSize(&data_ptr[i * length], length) * Py_INCREF(item) # <<<<<<<<<<<<<< @@ -5287,7 +5998,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ */ Py_INCREF(__pyx_v_item); - /* "clickhouse_driver/bufferedreader.pyx":189 + /* "clickhouse_driver/bufferedreader.pyx":277 * item = PyBytes_FromStringAndSize(&data_ptr[i * length], length) * Py_INCREF(item) * PyTuple_SET_ITEM(items, i, item) # <<<<<<<<<<<<<< @@ -5297,7 +6008,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ PyTuple_SET_ITEM(__pyx_v_items, __pyx_v_i, __pyx_v_item); } - /* "clickhouse_driver/bufferedreader.pyx":190 + /* "clickhouse_driver/bufferedreader.pyx":278 * Py_INCREF(item) * PyTuple_SET_ITEM(items, i, item) * return items # <<<<<<<<<<<<<< @@ -5309,8 +6020,8 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ __pyx_r = __pyx_v_items; goto __pyx_L0; - /* "clickhouse_driver/bufferedreader.pyx":179 - * return items + /* "clickhouse_driver/bufferedreader.pyx":267 + * return offsets, data * * def read_fixed_strings_as_bytes(self, Py_ssize_t n_items, # <<<<<<<<<<<<<< * Py_ssize_t length): @@ -5333,7 +6044,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ return __pyx_r; } -/* "clickhouse_driver/bufferedreader.pyx":192 +/* "clickhouse_driver/bufferedreader.pyx":280 * return items * * def read_fixed_strings(self, Py_ssize_t n_items, Py_ssize_t length, # <<<<<<<<<<<<<< @@ -5342,15 +6053,15 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ */ /* Python wrapper */ -static PyObject *__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_13read_fixed_strings(PyObject *__pyx_v_self, +static PyObject *__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_15read_fixed_strings(PyObject *__pyx_v_self, #if CYTHON_METH_FASTCALL PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds #else PyObject *__pyx_args, PyObject *__pyx_kwds #endif ); /*proto*/ -static PyMethodDef __pyx_mdef_17clickhouse_driver_14bufferedreader_14BufferedReader_13read_fixed_strings = {"read_fixed_strings", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_13read_fixed_strings, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}; -static PyObject *__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_13read_fixed_strings(PyObject *__pyx_v_self, +static PyMethodDef __pyx_mdef_17clickhouse_driver_14bufferedreader_14BufferedReader_15read_fixed_strings = {"read_fixed_strings", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_15read_fixed_strings, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_15read_fixed_strings(PyObject *__pyx_v_self, #if CYTHON_METH_FASTCALL PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds #else @@ -5382,28 +6093,28 @@ PyObject *__pyx_args, PyObject *__pyx_kwds { PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_n_items,&__pyx_mstate_global->__pyx_n_u_length,&__pyx_mstate_global->__pyx_n_u_encoding,0}; const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0; - if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 192, __pyx_L3_error) + if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 280, __pyx_L3_error) if (__pyx_kwds_len > 0) { switch (__pyx_nargs) { case 3: values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2); - if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 192, __pyx_L3_error) + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 280, __pyx_L3_error) CYTHON_FALLTHROUGH; case 2: values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1); - if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 192, __pyx_L3_error) + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 280, __pyx_L3_error) CYTHON_FALLTHROUGH; case 1: values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0); - if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 192, __pyx_L3_error) + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 280, __pyx_L3_error) CYTHON_FALLTHROUGH; case 0: break; default: goto __pyx_L5_argtuple_error; } const Py_ssize_t kwd_pos_args = __pyx_nargs; - if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "read_fixed_strings", 0) < (0)) __PYX_ERR(0, 192, __pyx_L3_error) + if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "read_fixed_strings", 0) < (0)) __PYX_ERR(0, 280, __pyx_L3_error) - /* "clickhouse_driver/bufferedreader.pyx":193 + /* "clickhouse_driver/bufferedreader.pyx":281 * * def read_fixed_strings(self, Py_ssize_t n_items, Py_ssize_t length, * encoding=None): # <<<<<<<<<<<<<< @@ -5412,31 +6123,31 @@ PyObject *__pyx_args, PyObject *__pyx_kwds */ if (!values[2]) values[2] = __Pyx_NewRef(((PyObject *)Py_None)); for (Py_ssize_t i = __pyx_nargs; i < 2; i++) { - if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("read_fixed_strings", 0, 2, 3, i); __PYX_ERR(0, 192, __pyx_L3_error) } + if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("read_fixed_strings", 0, 2, 3, i); __PYX_ERR(0, 280, __pyx_L3_error) } } } else { switch (__pyx_nargs) { case 3: values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2); - if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 192, __pyx_L3_error) + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 280, __pyx_L3_error) CYTHON_FALLTHROUGH; case 2: values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1); - if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 192, __pyx_L3_error) + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 280, __pyx_L3_error) values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0); - if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 192, __pyx_L3_error) + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 280, __pyx_L3_error) break; default: goto __pyx_L5_argtuple_error; } if (!values[2]) values[2] = __Pyx_NewRef(((PyObject *)Py_None)); } - __pyx_v_n_items = __Pyx_PyIndex_AsSsize_t(values[0]); if (unlikely((__pyx_v_n_items == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 192, __pyx_L3_error) - __pyx_v_length = __Pyx_PyIndex_AsSsize_t(values[1]); if (unlikely((__pyx_v_length == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 192, __pyx_L3_error) + __pyx_v_n_items = __Pyx_PyIndex_AsSsize_t(values[0]); if (unlikely((__pyx_v_n_items == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 280, __pyx_L3_error) + __pyx_v_length = __Pyx_PyIndex_AsSsize_t(values[1]); if (unlikely((__pyx_v_length == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 280, __pyx_L3_error) __pyx_v_encoding = values[2]; } goto __pyx_L6_skip; __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("read_fixed_strings", 0, 2, 3, __pyx_nargs); __PYX_ERR(0, 192, __pyx_L3_error) + __Pyx_RaiseArgtupleInvalid("read_fixed_strings", 0, 2, 3, __pyx_nargs); __PYX_ERR(0, 280, __pyx_L3_error) __pyx_L6_skip:; goto __pyx_L4_argument_unpacking_done; __pyx_L3_error:; @@ -5447,9 +6158,9 @@ PyObject *__pyx_args, PyObject *__pyx_kwds __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; - __pyx_r = __pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_12read_fixed_strings(((struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *)__pyx_v_self), __pyx_v_n_items, __pyx_v_length, __pyx_v_encoding); + __pyx_r = __pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_14read_fixed_strings(((struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *)__pyx_v_self), __pyx_v_n_items, __pyx_v_length, __pyx_v_encoding); - /* "clickhouse_driver/bufferedreader.pyx":192 + /* "clickhouse_driver/bufferedreader.pyx":280 * return items * * def read_fixed_strings(self, Py_ssize_t n_items, Py_ssize_t length, # <<<<<<<<<<<<<< @@ -5465,7 +6176,7 @@ PyObject *__pyx_args, PyObject *__pyx_kwds return __pyx_r; } -static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_12read_fixed_strings(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self, Py_ssize_t __pyx_v_n_items, Py_ssize_t __pyx_v_length, PyObject *__pyx_v_encoding) { +static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_14read_fixed_strings(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self, Py_ssize_t __pyx_v_n_items, Py_ssize_t __pyx_v_length, PyObject *__pyx_v_encoding) { Py_ssize_t __pyx_v_i; Py_ssize_t __pyx_v_j; char *__pyx_v_c_encoding; @@ -5497,7 +6208,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ __Pyx_RefNannySetupContext("read_fixed_strings", 0); __Pyx_INCREF(__pyx_v_encoding); - /* "clickhouse_driver/bufferedreader.pyx":194 + /* "clickhouse_driver/bufferedreader.pyx":282 * def read_fixed_strings(self, Py_ssize_t n_items, Py_ssize_t length, * encoding=None): * if encoding is None: # <<<<<<<<<<<<<< @@ -5507,7 +6218,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ __pyx_t_1 = (__pyx_v_encoding == Py_None); if (__pyx_t_1) { - /* "clickhouse_driver/bufferedreader.pyx":195 + /* "clickhouse_driver/bufferedreader.pyx":283 * encoding=None): * if encoding is None: * return self.read_fixed_strings_as_bytes(n_items, length) # <<<<<<<<<<<<<< @@ -5517,9 +6228,9 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ __Pyx_XDECREF(__pyx_r); __pyx_t_3 = ((PyObject *)__pyx_v_self); __Pyx_INCREF(__pyx_t_3); - __pyx_t_4 = PyLong_FromSsize_t(__pyx_v_n_items); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 195, __pyx_L1_error) + __pyx_t_4 = PyLong_FromSsize_t(__pyx_v_n_items); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 283, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); - __pyx_t_5 = PyLong_FromSsize_t(__pyx_v_length); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 195, __pyx_L1_error) + __pyx_t_5 = PyLong_FromSsize_t(__pyx_v_length); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 283, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_5); __pyx_t_6 = 0; { @@ -5528,14 +6239,14 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 195, __pyx_L1_error) + if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 283, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); } __pyx_r = __pyx_t_2; __pyx_t_2 = 0; goto __pyx_L0; - /* "clickhouse_driver/bufferedreader.pyx":194 + /* "clickhouse_driver/bufferedreader.pyx":282 * def read_fixed_strings(self, Py_ssize_t n_items, Py_ssize_t length, * encoding=None): * if encoding is None: # <<<<<<<<<<<<<< @@ -5544,7 +6255,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ */ } - /* "clickhouse_driver/bufferedreader.pyx":198 + /* "clickhouse_driver/bufferedreader.pyx":286 * * cdef Py_ssize_t i, j * encoding = encoding.encode('utf-8') # <<<<<<<<<<<<<< @@ -5558,23 +6269,23 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ PyObject *__pyx_callargs[2] = {__pyx_t_5, __pyx_mstate_global->__pyx_kp_u_utf_8}; __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_6, (2-__pyx_t_6) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; - if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 198, __pyx_L1_error) + if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 286, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); } __Pyx_DECREF_SET(__pyx_v_encoding, __pyx_t_2); __pyx_t_2 = 0; - /* "clickhouse_driver/bufferedreader.pyx":199 + /* "clickhouse_driver/bufferedreader.pyx":287 * cdef Py_ssize_t i, j * encoding = encoding.encode('utf-8') * cdef char* c_encoding = encoding # <<<<<<<<<<<<<< * data = self.read(length * n_items) * cdef char* data_ptr = PyBytes_AsString(data) */ - __pyx_t_7 = __Pyx_PyObject_AsWritableString(__pyx_v_encoding); if (unlikely((!__pyx_t_7) && PyErr_Occurred())) __PYX_ERR(0, 199, __pyx_L1_error) + __pyx_t_7 = __Pyx_PyObject_AsWritableString(__pyx_v_encoding); if (unlikely((!__pyx_t_7) && PyErr_Occurred())) __PYX_ERR(0, 287, __pyx_L1_error) __pyx_v_c_encoding = __pyx_t_7; - /* "clickhouse_driver/bufferedreader.pyx":200 + /* "clickhouse_driver/bufferedreader.pyx":288 * encoding = encoding.encode('utf-8') * cdef char* c_encoding = encoding * data = self.read(length * n_items) # <<<<<<<<<<<<<< @@ -5583,7 +6294,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ */ __pyx_t_5 = ((PyObject *)__pyx_v_self); __Pyx_INCREF(__pyx_t_5); - __pyx_t_4 = PyLong_FromSsize_t((__pyx_v_length * __pyx_v_n_items)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 200, __pyx_L1_error) + __pyx_t_4 = PyLong_FromSsize_t((__pyx_v_length * __pyx_v_n_items)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 288, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_6 = 0; { @@ -5591,23 +6302,23 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_read, __pyx_callargs+__pyx_t_6, (2-__pyx_t_6) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 200, __pyx_L1_error) + if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 288, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); } __pyx_v_data = __pyx_t_2; __pyx_t_2 = 0; - /* "clickhouse_driver/bufferedreader.pyx":201 + /* "clickhouse_driver/bufferedreader.pyx":289 * cdef char* c_encoding = encoding * data = self.read(length * n_items) * cdef char* data_ptr = PyBytes_AsString(data) # <<<<<<<<<<<<<< * * cdef char* c_string = PyMem_Malloc(length + 1) */ - __pyx_t_7 = PyBytes_AsString(__pyx_v_data); if (unlikely(__pyx_t_7 == ((void *)NULL))) __PYX_ERR(0, 201, __pyx_L1_error) + __pyx_t_7 = PyBytes_AsString(__pyx_v_data); if (unlikely(__pyx_t_7 == ((void *)NULL))) __PYX_ERR(0, 289, __pyx_L1_error) __pyx_v_data_ptr = __pyx_t_7; - /* "clickhouse_driver/bufferedreader.pyx":203 + /* "clickhouse_driver/bufferedreader.pyx":291 * cdef char* data_ptr = PyBytes_AsString(data) * * cdef char* c_string = PyMem_Malloc(length + 1) # <<<<<<<<<<<<<< @@ -5616,7 +6327,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ */ __pyx_v_c_string = ((char *)PyMem_Malloc((__pyx_v_length + 1))); - /* "clickhouse_driver/bufferedreader.pyx":204 + /* "clickhouse_driver/bufferedreader.pyx":292 * * cdef char* c_string = PyMem_Malloc(length + 1) * if not c_string: # <<<<<<<<<<<<<< @@ -5626,16 +6337,16 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ __pyx_t_1 = (!(__pyx_v_c_string != 0)); if (unlikely(__pyx_t_1)) { - /* "clickhouse_driver/bufferedreader.pyx":205 + /* "clickhouse_driver/bufferedreader.pyx":293 * cdef char* c_string = PyMem_Malloc(length + 1) * if not c_string: * raise MemoryError() # <<<<<<<<<<<<<< * c_string[length] = 0 * */ - PyErr_NoMemory(); __PYX_ERR(0, 205, __pyx_L1_error) + PyErr_NoMemory(); __PYX_ERR(0, 293, __pyx_L1_error) - /* "clickhouse_driver/bufferedreader.pyx":204 + /* "clickhouse_driver/bufferedreader.pyx":292 * * cdef char* c_string = PyMem_Malloc(length + 1) * if not c_string: # <<<<<<<<<<<<<< @@ -5644,7 +6355,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ */ } - /* "clickhouse_driver/bufferedreader.pyx":206 + /* "clickhouse_driver/bufferedreader.pyx":294 * if not c_string: * raise MemoryError() * c_string[length] = 0 # <<<<<<<<<<<<<< @@ -5653,19 +6364,19 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ */ (__pyx_v_c_string[__pyx_v_length]) = 0; - /* "clickhouse_driver/bufferedreader.pyx":208 + /* "clickhouse_driver/bufferedreader.pyx":296 * c_string[length] = 0 * * items = PyTuple_New(n_items) # <<<<<<<<<<<<<< * for i in range(n_items): * memcpy(c_string, &data_ptr[i * length], length) */ - __pyx_t_2 = PyTuple_New(__pyx_v_n_items); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 208, __pyx_L1_error) + __pyx_t_2 = PyTuple_New(__pyx_v_n_items); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 296, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __pyx_v_items = ((PyObject*)__pyx_t_2); __pyx_t_2 = 0; - /* "clickhouse_driver/bufferedreader.pyx":209 + /* "clickhouse_driver/bufferedreader.pyx":297 * * items = PyTuple_New(n_items) * for i in range(n_items): # <<<<<<<<<<<<<< @@ -5677,7 +6388,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ for (__pyx_t_10 = 0; __pyx_t_10 < __pyx_t_9; __pyx_t_10+=1) { __pyx_v_i = __pyx_t_10; - /* "clickhouse_driver/bufferedreader.pyx":210 + /* "clickhouse_driver/bufferedreader.pyx":298 * items = PyTuple_New(n_items) * for i in range(n_items): * memcpy(c_string, &data_ptr[i * length], length) # <<<<<<<<<<<<<< @@ -5686,7 +6397,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ */ (void)(memcpy(__pyx_v_c_string, (&(__pyx_v_data_ptr[(__pyx_v_i * __pyx_v_length)])), __pyx_v_length)); - /* "clickhouse_driver/bufferedreader.pyx":213 + /* "clickhouse_driver/bufferedreader.pyx":301 * * # Get last non zero byte of string from the end. * j = length - 1 # <<<<<<<<<<<<<< @@ -5695,7 +6406,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ */ __pyx_v_j = (__pyx_v_length - 1); - /* "clickhouse_driver/bufferedreader.pyx":214 + /* "clickhouse_driver/bufferedreader.pyx":302 * # Get last non zero byte of string from the end. * j = length - 1 * while j >= 0 and not c_string[j]: # <<<<<<<<<<<<<< @@ -5714,7 +6425,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ __pyx_L9_bool_binop_done:; if (!__pyx_t_1) break; - /* "clickhouse_driver/bufferedreader.pyx":215 + /* "clickhouse_driver/bufferedreader.pyx":303 * j = length - 1 * while j >= 0 and not c_string[j]: * j -= 1 # <<<<<<<<<<<<<< @@ -5724,7 +6435,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ __pyx_v_j = (__pyx_v_j - 1); } - /* "clickhouse_driver/bufferedreader.pyx":217 + /* "clickhouse_driver/bufferedreader.pyx":305 * j -= 1 * * try: # <<<<<<<<<<<<<< @@ -5740,19 +6451,19 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ __Pyx_XGOTREF(__pyx_t_14); /*try:*/ { - /* "clickhouse_driver/bufferedreader.pyx":218 + /* "clickhouse_driver/bufferedreader.pyx":306 * * try: * item = c_string[:j + 1].decode(c_encoding) # <<<<<<<<<<<<<< * except UnicodeDecodeError: * item = PyBytes_FromStringAndSize(c_string, length) */ - __pyx_t_2 = __Pyx_decode_c_string(__pyx_v_c_string, 0, (__pyx_v_j + 1), __pyx_v_c_encoding, NULL, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 218, __pyx_L11_error) + __pyx_t_2 = __Pyx_decode_c_string(__pyx_v_c_string, 0, (__pyx_v_j + 1), __pyx_v_c_encoding, NULL, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 306, __pyx_L11_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_XDECREF_SET(__pyx_v_item, __pyx_t_2); __pyx_t_2 = 0; - /* "clickhouse_driver/bufferedreader.pyx":217 + /* "clickhouse_driver/bufferedreader.pyx":305 * j -= 1 * * try: # <<<<<<<<<<<<<< @@ -5770,7 +6481,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; - /* "clickhouse_driver/bufferedreader.pyx":219 + /* "clickhouse_driver/bufferedreader.pyx":307 * try: * item = c_string[:j + 1].decode(c_encoding) * except UnicodeDecodeError: # <<<<<<<<<<<<<< @@ -5780,19 +6491,19 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ __pyx_t_15 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(((PyTypeObject*)PyExc_UnicodeDecodeError)))); if (__pyx_t_15) { __Pyx_AddTraceback("clickhouse_driver.bufferedreader.BufferedReader.read_fixed_strings", __pyx_clineno, __pyx_lineno, __pyx_filename); - if (__Pyx_GetException(&__pyx_t_2, &__pyx_t_4, &__pyx_t_5) < 0) __PYX_ERR(0, 219, __pyx_L13_except_error) + if (__Pyx_GetException(&__pyx_t_2, &__pyx_t_4, &__pyx_t_5) < 0) __PYX_ERR(0, 307, __pyx_L13_except_error) __Pyx_XGOTREF(__pyx_t_2); __Pyx_XGOTREF(__pyx_t_4); __Pyx_XGOTREF(__pyx_t_5); - /* "clickhouse_driver/bufferedreader.pyx":220 + /* "clickhouse_driver/bufferedreader.pyx":308 * item = c_string[:j + 1].decode(c_encoding) * except UnicodeDecodeError: * item = PyBytes_FromStringAndSize(c_string, length) # <<<<<<<<<<<<<< * Py_INCREF(item) * PyTuple_SET_ITEM(items, i, item) */ - __pyx_t_3 = PyBytes_FromStringAndSize(__pyx_v_c_string, __pyx_v_length); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 220, __pyx_L13_except_error) + __pyx_t_3 = PyBytes_FromStringAndSize(__pyx_v_c_string, __pyx_v_length); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 308, __pyx_L13_except_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_XDECREF_SET(__pyx_v_item, __pyx_t_3); __pyx_t_3 = 0; @@ -5803,7 +6514,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ } goto __pyx_L13_except_error; - /* "clickhouse_driver/bufferedreader.pyx":217 + /* "clickhouse_driver/bufferedreader.pyx":305 * j -= 1 * * try: # <<<<<<<<<<<<<< @@ -5824,7 +6535,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ __pyx_L18_try_end:; } - /* "clickhouse_driver/bufferedreader.pyx":221 + /* "clickhouse_driver/bufferedreader.pyx":309 * except UnicodeDecodeError: * item = PyBytes_FromStringAndSize(c_string, length) * Py_INCREF(item) # <<<<<<<<<<<<<< @@ -5833,7 +6544,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ */ Py_INCREF(__pyx_v_item); - /* "clickhouse_driver/bufferedreader.pyx":222 + /* "clickhouse_driver/bufferedreader.pyx":310 * item = PyBytes_FromStringAndSize(c_string, length) * Py_INCREF(item) * PyTuple_SET_ITEM(items, i, item) # <<<<<<<<<<<<<< @@ -5843,7 +6554,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ PyTuple_SET_ITEM(__pyx_v_items, __pyx_v_i, __pyx_v_item); } - /* "clickhouse_driver/bufferedreader.pyx":224 + /* "clickhouse_driver/bufferedreader.pyx":312 * PyTuple_SET_ITEM(items, i, item) * * PyMem_Free(c_string) # <<<<<<<<<<<<<< @@ -5852,7 +6563,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ */ PyMem_Free(__pyx_v_c_string); - /* "clickhouse_driver/bufferedreader.pyx":226 + /* "clickhouse_driver/bufferedreader.pyx":314 * PyMem_Free(c_string) * * return items # <<<<<<<<<<<<<< @@ -5864,7 +6575,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ __pyx_r = __pyx_v_items; goto __pyx_L0; - /* "clickhouse_driver/bufferedreader.pyx":192 + /* "clickhouse_driver/bufferedreader.pyx":280 * return items * * def read_fixed_strings(self, Py_ssize_t n_items, Py_ssize_t length, # <<<<<<<<<<<<<< @@ -6169,15 +6880,15 @@ static int __pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_6buffe */ /* Python wrapper */ -static PyObject *__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_15__reduce_cython__(PyObject *__pyx_v_self, +static PyObject *__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_17__reduce_cython__(PyObject *__pyx_v_self, #if CYTHON_METH_FASTCALL PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds #else PyObject *__pyx_args, PyObject *__pyx_kwds #endif ); /*proto*/ -static PyMethodDef __pyx_mdef_17clickhouse_driver_14bufferedreader_14BufferedReader_15__reduce_cython__ = {"__reduce_cython__", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_15__reduce_cython__, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}; -static PyObject *__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_15__reduce_cython__(PyObject *__pyx_v_self, +static PyMethodDef __pyx_mdef_17clickhouse_driver_14bufferedreader_14BufferedReader_17__reduce_cython__ = {"__reduce_cython__", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_17__reduce_cython__, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_17__reduce_cython__(PyObject *__pyx_v_self, #if CYTHON_METH_FASTCALL PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds #else @@ -6203,14 +6914,14 @@ PyObject *__pyx_args, PyObject *__pyx_kwds const Py_ssize_t __pyx_kwds_len = unlikely(__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0; if (unlikely(__pyx_kwds_len < 0)) return NULL; if (unlikely(__pyx_kwds_len > 0)) {__Pyx_RejectKeywords("__reduce_cython__", __pyx_kwds); return NULL;} - __pyx_r = __pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_14__reduce_cython__(((struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *)__pyx_v_self)); + __pyx_r = __pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_16__reduce_cython__(((struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *)__pyx_v_self)); /* function exit code */ __Pyx_RefNannyFinishContext(); return __pyx_r; } -static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_14__reduce_cython__(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self) { +static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_16__reduce_cython__(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self) { PyObject *__pyx_v_state = 0; PyObject *__pyx_v__dict = 0; int __pyx_v_use_setstate; @@ -6449,15 +7160,15 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ */ /* Python wrapper */ -static PyObject *__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_17__setstate_cython__(PyObject *__pyx_v_self, +static PyObject *__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_19__setstate_cython__(PyObject *__pyx_v_self, #if CYTHON_METH_FASTCALL PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds #else PyObject *__pyx_args, PyObject *__pyx_kwds #endif ); /*proto*/ -static PyMethodDef __pyx_mdef_17clickhouse_driver_14bufferedreader_14BufferedReader_17__setstate_cython__ = {"__setstate_cython__", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_17__setstate_cython__, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}; -static PyObject *__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_17__setstate_cython__(PyObject *__pyx_v_self, +static PyMethodDef __pyx_mdef_17clickhouse_driver_14bufferedreader_14BufferedReader_19__setstate_cython__ = {"__setstate_cython__", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_19__setstate_cython__, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_19__setstate_cython__(PyObject *__pyx_v_self, #if CYTHON_METH_FASTCALL PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds #else @@ -6523,7 +7234,7 @@ PyObject *__pyx_args, PyObject *__pyx_kwds __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; - __pyx_r = __pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_16__setstate_cython__(((struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *)__pyx_v_self), __pyx_v___pyx_state); + __pyx_r = __pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_18__setstate_cython__(((struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *)__pyx_v_self), __pyx_v___pyx_state); /* function exit code */ for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { @@ -6533,7 +7244,7 @@ PyObject *__pyx_args, PyObject *__pyx_kwds return __pyx_r; } -static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_16__setstate_cython__(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self, PyObject *__pyx_v___pyx_state) { +static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_18__setstate_cython__(struct __pyx_obj_17clickhouse_driver_14bufferedreader_BufferedReader *__pyx_v_self, PyObject *__pyx_v___pyx_state) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; @@ -6581,7 +7292,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_14BufferedReader_ return __pyx_r; } -/* "clickhouse_driver/bufferedreader.pyx":232 +/* "clickhouse_driver/bufferedreader.pyx":320 * cdef object sock * * def __init__(self, sock, bufsize): # <<<<<<<<<<<<<< @@ -6612,39 +7323,39 @@ static int __pyx_pw_17clickhouse_driver_14bufferedreader_20BufferedSocketReader_ { PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_sock,&__pyx_mstate_global->__pyx_n_u_bufsize,0}; const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_VARARGS(__pyx_kwds) : 0; - if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 232, __pyx_L3_error) + if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 320, __pyx_L3_error) if (__pyx_kwds_len > 0) { switch (__pyx_nargs) { case 2: values[1] = __Pyx_ArgRef_VARARGS(__pyx_args, 1); - if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 232, __pyx_L3_error) + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 320, __pyx_L3_error) CYTHON_FALLTHROUGH; case 1: values[0] = __Pyx_ArgRef_VARARGS(__pyx_args, 0); - if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 232, __pyx_L3_error) + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 320, __pyx_L3_error) CYTHON_FALLTHROUGH; case 0: break; default: goto __pyx_L5_argtuple_error; } const Py_ssize_t kwd_pos_args = __pyx_nargs; - if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "__init__", 0) < (0)) __PYX_ERR(0, 232, __pyx_L3_error) + if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "__init__", 0) < (0)) __PYX_ERR(0, 320, __pyx_L3_error) for (Py_ssize_t i = __pyx_nargs; i < 2; i++) { - if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, i); __PYX_ERR(0, 232, __pyx_L3_error) } + if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, i); __PYX_ERR(0, 320, __pyx_L3_error) } } } else if (unlikely(__pyx_nargs != 2)) { goto __pyx_L5_argtuple_error; } else { values[0] = __Pyx_ArgRef_VARARGS(__pyx_args, 0); - if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 232, __pyx_L3_error) + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 320, __pyx_L3_error) values[1] = __Pyx_ArgRef_VARARGS(__pyx_args, 1); - if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 232, __pyx_L3_error) + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 320, __pyx_L3_error) } __pyx_v_sock = values[0]; __pyx_v_bufsize = values[1]; } goto __pyx_L6_skip; __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, __pyx_nargs); __PYX_ERR(0, 232, __pyx_L3_error) + __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, __pyx_nargs); __PYX_ERR(0, 320, __pyx_L3_error) __pyx_L6_skip:; goto __pyx_L4_argument_unpacking_done; __pyx_L3_error:; @@ -6678,7 +7389,7 @@ static int __pyx_pf_17clickhouse_driver_14bufferedreader_20BufferedSocketReader_ int __pyx_clineno = 0; __Pyx_RefNannySetupContext("__init__", 0); - /* "clickhouse_driver/bufferedreader.pyx":233 + /* "clickhouse_driver/bufferedreader.pyx":321 * * def __init__(self, sock, bufsize): * self.sock = sock # <<<<<<<<<<<<<< @@ -6691,7 +7402,7 @@ static int __pyx_pf_17clickhouse_driver_14bufferedreader_20BufferedSocketReader_ __Pyx_DECREF(__pyx_v_self->sock); __pyx_v_self->sock = __pyx_v_sock; - /* "clickhouse_driver/bufferedreader.pyx":234 + /* "clickhouse_driver/bufferedreader.pyx":322 * def __init__(self, sock, bufsize): * self.sock = sock * super(BufferedSocketReader, self).__init__(bufsize) # <<<<<<<<<<<<<< @@ -6704,7 +7415,7 @@ static int __pyx_pf_17clickhouse_driver_14bufferedreader_20BufferedSocketReader_ PyObject *__pyx_callargs[3] = {__pyx_t_4, ((PyObject *)__pyx_mstate_global->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedSocketReader), ((PyObject *)__pyx_v_self)}; __pyx_t_3 = __Pyx_PyObject_FastCall((PyObject*)__pyx_builtin_super, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; - if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 234, __pyx_L1_error) + if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 322, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); } __pyx_t_2 = __pyx_t_3; @@ -6715,12 +7426,12 @@ static int __pyx_pf_17clickhouse_driver_14bufferedreader_20BufferedSocketReader_ __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_init, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 234, __pyx_L1_error) + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 322, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); } __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "clickhouse_driver/bufferedreader.pyx":232 + /* "clickhouse_driver/bufferedreader.pyx":320 * cdef object sock * * def __init__(self, sock, bufsize): # <<<<<<<<<<<<<< @@ -6743,7 +7454,7 @@ static int __pyx_pf_17clickhouse_driver_14bufferedreader_20BufferedSocketReader_ return __pyx_r; } -/* "clickhouse_driver/bufferedreader.pyx":236 +/* "clickhouse_driver/bufferedreader.pyx":324 * super(BufferedSocketReader, self).__init__(bufsize) * * def read_into_buffer(self): # <<<<<<<<<<<<<< @@ -6806,7 +7517,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_20BufferedSocketR int __pyx_clineno = 0; __Pyx_RefNannySetupContext("read_into_buffer", 0); - /* "clickhouse_driver/bufferedreader.pyx":237 + /* "clickhouse_driver/bufferedreader.pyx":325 * * def read_into_buffer(self): * self.current_buffer_size = self.sock.recv_into(self.buffer) # <<<<<<<<<<<<<< @@ -6820,14 +7531,14 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_20BufferedSocketR PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_v_self->__pyx_base.buffer}; __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_recv_into, __pyx_callargs+__pyx_t_3, (2-__pyx_t_3) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 237, __pyx_L1_error) + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 325, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); } - __pyx_t_4 = __Pyx_PyLong_As_unsigned_PY_LONG_LONG(__pyx_t_1); if (unlikely((__pyx_t_4 == (unsigned PY_LONG_LONG)-1) && PyErr_Occurred())) __PYX_ERR(0, 237, __pyx_L1_error) + __pyx_t_4 = __Pyx_PyLong_As_unsigned_PY_LONG_LONG(__pyx_t_1); if (unlikely((__pyx_t_4 == (unsigned PY_LONG_LONG)-1) && PyErr_Occurred())) __PYX_ERR(0, 325, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_v_self->__pyx_base.current_buffer_size = __pyx_t_4; - /* "clickhouse_driver/bufferedreader.pyx":239 + /* "clickhouse_driver/bufferedreader.pyx":327 * self.current_buffer_size = self.sock.recv_into(self.buffer) * * if self.current_buffer_size == 0: # <<<<<<<<<<<<<< @@ -6837,7 +7548,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_20BufferedSocketR __pyx_t_5 = (__pyx_v_self->__pyx_base.current_buffer_size == 0); if (unlikely(__pyx_t_5)) { - /* "clickhouse_driver/bufferedreader.pyx":240 + /* "clickhouse_driver/bufferedreader.pyx":328 * * if self.current_buffer_size == 0: * raise EOFError('Unexpected EOF while reading bytes') # <<<<<<<<<<<<<< @@ -6850,14 +7561,14 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_20BufferedSocketR PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_mstate_global->__pyx_kp_u_Unexpected_EOF_while_reading_byt}; __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)(((PyTypeObject*)PyExc_EOFError)), __pyx_callargs+__pyx_t_3, (2-__pyx_t_3) | (__pyx_t_3*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 240, __pyx_L1_error) + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 328, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); } __Pyx_Raise(__pyx_t_1, 0, 0, 0); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __PYX_ERR(0, 240, __pyx_L1_error) + __PYX_ERR(0, 328, __pyx_L1_error) - /* "clickhouse_driver/bufferedreader.pyx":239 + /* "clickhouse_driver/bufferedreader.pyx":327 * self.current_buffer_size = self.sock.recv_into(self.buffer) * * if self.current_buffer_size == 0: # <<<<<<<<<<<<<< @@ -6866,7 +7577,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_20BufferedSocketR */ } - /* "clickhouse_driver/bufferedreader.pyx":236 + /* "clickhouse_driver/bufferedreader.pyx":324 * super(BufferedSocketReader, self).__init__(bufsize) * * def read_into_buffer(self): # <<<<<<<<<<<<<< @@ -7310,7 +8021,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_20BufferedSocketR return __pyx_r; } -/* "clickhouse_driver/bufferedreader.pyx":246 +/* "clickhouse_driver/bufferedreader.pyx":334 * cdef object read_block * * def __init__(self, read_block, bufsize): # <<<<<<<<<<<<<< @@ -7341,39 +8052,39 @@ static int __pyx_pw_17clickhouse_driver_14bufferedreader_24CompressedBufferedRea { PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_read_block,&__pyx_mstate_global->__pyx_n_u_bufsize,0}; const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_VARARGS(__pyx_kwds) : 0; - if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 246, __pyx_L3_error) + if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 334, __pyx_L3_error) if (__pyx_kwds_len > 0) { switch (__pyx_nargs) { case 2: values[1] = __Pyx_ArgRef_VARARGS(__pyx_args, 1); - if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 246, __pyx_L3_error) + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 334, __pyx_L3_error) CYTHON_FALLTHROUGH; case 1: values[0] = __Pyx_ArgRef_VARARGS(__pyx_args, 0); - if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 246, __pyx_L3_error) + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 334, __pyx_L3_error) CYTHON_FALLTHROUGH; case 0: break; default: goto __pyx_L5_argtuple_error; } const Py_ssize_t kwd_pos_args = __pyx_nargs; - if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "__init__", 0) < (0)) __PYX_ERR(0, 246, __pyx_L3_error) + if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "__init__", 0) < (0)) __PYX_ERR(0, 334, __pyx_L3_error) for (Py_ssize_t i = __pyx_nargs; i < 2; i++) { - if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, i); __PYX_ERR(0, 246, __pyx_L3_error) } + if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, i); __PYX_ERR(0, 334, __pyx_L3_error) } } } else if (unlikely(__pyx_nargs != 2)) { goto __pyx_L5_argtuple_error; } else { values[0] = __Pyx_ArgRef_VARARGS(__pyx_args, 0); - if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 246, __pyx_L3_error) + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 334, __pyx_L3_error) values[1] = __Pyx_ArgRef_VARARGS(__pyx_args, 1); - if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 246, __pyx_L3_error) + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 334, __pyx_L3_error) } __pyx_v_read_block = values[0]; __pyx_v_bufsize = values[1]; } goto __pyx_L6_skip; __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, __pyx_nargs); __PYX_ERR(0, 246, __pyx_L3_error) + __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, __pyx_nargs); __PYX_ERR(0, 334, __pyx_L3_error) __pyx_L6_skip:; goto __pyx_L4_argument_unpacking_done; __pyx_L3_error:; @@ -7407,7 +8118,7 @@ static int __pyx_pf_17clickhouse_driver_14bufferedreader_24CompressedBufferedRea int __pyx_clineno = 0; __Pyx_RefNannySetupContext("__init__", 0); - /* "clickhouse_driver/bufferedreader.pyx":247 + /* "clickhouse_driver/bufferedreader.pyx":335 * * def __init__(self, read_block, bufsize): * self.read_block = read_block # <<<<<<<<<<<<<< @@ -7420,7 +8131,7 @@ static int __pyx_pf_17clickhouse_driver_14bufferedreader_24CompressedBufferedRea __Pyx_DECREF(__pyx_v_self->read_block); __pyx_v_self->read_block = __pyx_v_read_block; - /* "clickhouse_driver/bufferedreader.pyx":248 + /* "clickhouse_driver/bufferedreader.pyx":336 * def __init__(self, read_block, bufsize): * self.read_block = read_block * super(CompressedBufferedReader, self).__init__(bufsize) # <<<<<<<<<<<<<< @@ -7433,7 +8144,7 @@ static int __pyx_pf_17clickhouse_driver_14bufferedreader_24CompressedBufferedRea PyObject *__pyx_callargs[3] = {__pyx_t_4, ((PyObject *)__pyx_mstate_global->__pyx_ptype_17clickhouse_driver_14bufferedreader_CompressedBufferedReader), ((PyObject *)__pyx_v_self)}; __pyx_t_3 = __Pyx_PyObject_FastCall((PyObject*)__pyx_builtin_super, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; - if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 248, __pyx_L1_error) + if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 336, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); } __pyx_t_2 = __pyx_t_3; @@ -7444,12 +8155,12 @@ static int __pyx_pf_17clickhouse_driver_14bufferedreader_24CompressedBufferedRea __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_init, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 248, __pyx_L1_error) + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 336, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); } __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - /* "clickhouse_driver/bufferedreader.pyx":246 + /* "clickhouse_driver/bufferedreader.pyx":334 * cdef object read_block * * def __init__(self, read_block, bufsize): # <<<<<<<<<<<<<< @@ -7472,7 +8183,7 @@ static int __pyx_pf_17clickhouse_driver_14bufferedreader_24CompressedBufferedRea return __pyx_r; } -/* "clickhouse_driver/bufferedreader.pyx":250 +/* "clickhouse_driver/bufferedreader.pyx":338 * super(CompressedBufferedReader, self).__init__(bufsize) * * def read_into_buffer(self): # <<<<<<<<<<<<<< @@ -7538,7 +8249,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_24CompressedBuffe int __pyx_clineno = 0; __Pyx_RefNannySetupContext("read_into_buffer", 0); - /* "clickhouse_driver/bufferedreader.pyx":251 + /* "clickhouse_driver/bufferedreader.pyx":339 * * def read_into_buffer(self): * self.buffer = bytearray(self.read_block()) # <<<<<<<<<<<<<< @@ -7566,7 +8277,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_24CompressedBuffe __pyx_t_3 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_5, __pyx_callargs+__pyx_t_6, (1-__pyx_t_6) | (__pyx_t_6*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 251, __pyx_L1_error) + if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 339, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); } __pyx_t_6 = 1; @@ -7575,7 +8286,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_24CompressedBuffe __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)(&PyByteArray_Type), __pyx_callargs+__pyx_t_6, (2-__pyx_t_6) | (__pyx_t_6*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 251, __pyx_L1_error) + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 339, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); } __Pyx_GIVEREF(__pyx_t_1); @@ -7584,7 +8295,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_24CompressedBuffe __pyx_v_self->__pyx_base.buffer = ((PyObject*)__pyx_t_1); __pyx_t_1 = 0; - /* "clickhouse_driver/bufferedreader.pyx":252 + /* "clickhouse_driver/bufferedreader.pyx":340 * def read_into_buffer(self): * self.buffer = bytearray(self.read_block()) * self.current_buffer_size = len(self.buffer) # <<<<<<<<<<<<<< @@ -7595,13 +8306,13 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_24CompressedBuffe __Pyx_INCREF(__pyx_t_1); if (unlikely(__pyx_t_1 == Py_None)) { PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); - __PYX_ERR(0, 252, __pyx_L1_error) + __PYX_ERR(0, 340, __pyx_L1_error) } - __pyx_t_7 = __Pyx_PyByteArray_GET_SIZE(__pyx_t_1); if (unlikely(__pyx_t_7 == ((Py_ssize_t)-1))) __PYX_ERR(0, 252, __pyx_L1_error) + __pyx_t_7 = __Pyx_PyByteArray_GET_SIZE(__pyx_t_1); if (unlikely(__pyx_t_7 == ((Py_ssize_t)-1))) __PYX_ERR(0, 340, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_v_self->__pyx_base.current_buffer_size = __pyx_t_7; - /* "clickhouse_driver/bufferedreader.pyx":254 + /* "clickhouse_driver/bufferedreader.pyx":342 * self.current_buffer_size = len(self.buffer) * * if self.current_buffer_size == 0: # <<<<<<<<<<<<<< @@ -7610,7 +8321,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_24CompressedBuffe __pyx_t_8 = (__pyx_v_self->__pyx_base.current_buffer_size == 0); if (unlikely(__pyx_t_8)) { - /* "clickhouse_driver/bufferedreader.pyx":255 + /* "clickhouse_driver/bufferedreader.pyx":343 * * if self.current_buffer_size == 0: * raise EOFError('Unexpected EOF while reading bytes') # <<<<<<<<<<<<<< @@ -7621,14 +8332,14 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_24CompressedBuffe PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_mstate_global->__pyx_kp_u_Unexpected_EOF_while_reading_byt}; __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)(((PyTypeObject*)PyExc_EOFError)), __pyx_callargs+__pyx_t_6, (2-__pyx_t_6) | (__pyx_t_6*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 255, __pyx_L1_error) + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 343, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); } __Pyx_Raise(__pyx_t_1, 0, 0, 0); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __PYX_ERR(0, 255, __pyx_L1_error) + __PYX_ERR(0, 343, __pyx_L1_error) - /* "clickhouse_driver/bufferedreader.pyx":254 + /* "clickhouse_driver/bufferedreader.pyx":342 * self.current_buffer_size = len(self.buffer) * * if self.current_buffer_size == 0: # <<<<<<<<<<<<<< @@ -7636,7 +8347,7 @@ static PyObject *__pyx_pf_17clickhouse_driver_14bufferedreader_24CompressedBuffe */ } - /* "clickhouse_driver/bufferedreader.pyx":250 + /* "clickhouse_driver/bufferedreader.pyx":338 * super(CompressedBufferedReader, self).__init__(bufsize) * * def read_into_buffer(self): # <<<<<<<<<<<<<< @@ -9081,10 +9792,11 @@ static PyMethodDef __pyx_methods_17clickhouse_driver_14bufferedreader_BufferedRe {"read", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_5read, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}, {"read_one", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_7read_one, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}, {"read_strings", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_9read_strings, __Pyx_METH_FASTCALL|METH_KEYWORDS, __pyx_doc_17clickhouse_driver_14bufferedreader_14BufferedReader_8read_strings}, - {"read_fixed_strings_as_bytes", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_11read_fixed_strings_as_bytes, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}, - {"read_fixed_strings", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_13read_fixed_strings, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}, - {"__reduce_cython__", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_15__reduce_cython__, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}, - {"__setstate_cython__", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_17__setstate_cython__, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}, + {"read_strings_arrow", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_11read_strings_arrow, __Pyx_METH_FASTCALL|METH_KEYWORDS, __pyx_doc_17clickhouse_driver_14bufferedreader_14BufferedReader_10read_strings_arrow}, + {"read_fixed_strings_as_bytes", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_13read_fixed_strings_as_bytes, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}, + {"read_fixed_strings", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_15read_fixed_strings, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}, + {"__reduce_cython__", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_17__reduce_cython__, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}, + {"__setstate_cython__", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_17clickhouse_driver_14bufferedreader_14BufferedReader_19__setstate_cython__, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}, {0, 0, 0, 0} }; @@ -9579,12 +10291,12 @@ static int __Pyx_modinit_type_init_code(__pyx_mstatetype *__pyx_mstate) { if (PyObject_SetAttr(__pyx_m, __pyx_mstate_global->__pyx_n_u_BufferedReader, (PyObject *) __pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedReader) < (0)) __PYX_ERR(0, 10, __pyx_L1_error) if (__Pyx_setup_reduce((PyObject *) __pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedReader) < (0)) __PYX_ERR(0, 10, __pyx_L1_error) #if CYTHON_USE_TYPE_SPECS - __pyx_t_1 = PyTuple_Pack(1, (PyObject *)__pyx_mstate_global->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedReader); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 229, __pyx_L1_error) + __pyx_t_1 = PyTuple_Pack(1, (PyObject *)__pyx_mstate_global->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedReader); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 317, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedSocketReader = (PyTypeObject *) __Pyx_PyType_FromModuleAndSpec(__pyx_m, &__pyx_type_17clickhouse_driver_14bufferedreader_BufferedSocketReader_spec, __pyx_t_1); __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; - if (unlikely(!__pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedSocketReader)) __PYX_ERR(0, 229, __pyx_L1_error) - if (__Pyx_fix_up_extension_type_from_spec(&__pyx_type_17clickhouse_driver_14bufferedreader_BufferedSocketReader_spec, __pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedSocketReader) < (0)) __PYX_ERR(0, 229, __pyx_L1_error) + if (unlikely(!__pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedSocketReader)) __PYX_ERR(0, 317, __pyx_L1_error) + if (__Pyx_fix_up_extension_type_from_spec(&__pyx_type_17clickhouse_driver_14bufferedreader_BufferedSocketReader_spec, __pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedSocketReader) < (0)) __PYX_ERR(0, 317, __pyx_L1_error) #else __pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedSocketReader = &__pyx_type_17clickhouse_driver_14bufferedreader_BufferedSocketReader; #endif @@ -9592,7 +10304,7 @@ static int __Pyx_modinit_type_init_code(__pyx_mstatetype *__pyx_mstate) { __pyx_mstate_global->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedSocketReader->tp_base = __pyx_mstate_global->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedReader; #endif #if !CYTHON_USE_TYPE_SPECS - if (__Pyx_PyType_Ready(__pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedSocketReader) < (0)) __PYX_ERR(0, 229, __pyx_L1_error) + if (__Pyx_PyType_Ready(__pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedSocketReader) < (0)) __PYX_ERR(0, 317, __pyx_L1_error) #endif #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000 PyUnstable_Object_EnableDeferredRefcount((PyObject*)__pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedSocketReader); @@ -9602,15 +10314,15 @@ static int __Pyx_modinit_type_init_code(__pyx_mstatetype *__pyx_mstate) { __pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedSocketReader->tp_getattro = PyObject_GenericGetAttr; } #endif - if (PyObject_SetAttr(__pyx_m, __pyx_mstate_global->__pyx_n_u_BufferedSocketReader, (PyObject *) __pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedSocketReader) < (0)) __PYX_ERR(0, 229, __pyx_L1_error) - if (__Pyx_setup_reduce((PyObject *) __pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedSocketReader) < (0)) __PYX_ERR(0, 229, __pyx_L1_error) + if (PyObject_SetAttr(__pyx_m, __pyx_mstate_global->__pyx_n_u_BufferedSocketReader, (PyObject *) __pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedSocketReader) < (0)) __PYX_ERR(0, 317, __pyx_L1_error) + if (__Pyx_setup_reduce((PyObject *) __pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedSocketReader) < (0)) __PYX_ERR(0, 317, __pyx_L1_error) #if CYTHON_USE_TYPE_SPECS - __pyx_t_1 = PyTuple_Pack(1, (PyObject *)__pyx_mstate_global->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedReader); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 243, __pyx_L1_error) + __pyx_t_1 = PyTuple_Pack(1, (PyObject *)__pyx_mstate_global->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedReader); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 331, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_CompressedBufferedReader = (PyTypeObject *) __Pyx_PyType_FromModuleAndSpec(__pyx_m, &__pyx_type_17clickhouse_driver_14bufferedreader_CompressedBufferedReader_spec, __pyx_t_1); __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; - if (unlikely(!__pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_CompressedBufferedReader)) __PYX_ERR(0, 243, __pyx_L1_error) - if (__Pyx_fix_up_extension_type_from_spec(&__pyx_type_17clickhouse_driver_14bufferedreader_CompressedBufferedReader_spec, __pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_CompressedBufferedReader) < (0)) __PYX_ERR(0, 243, __pyx_L1_error) + if (unlikely(!__pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_CompressedBufferedReader)) __PYX_ERR(0, 331, __pyx_L1_error) + if (__Pyx_fix_up_extension_type_from_spec(&__pyx_type_17clickhouse_driver_14bufferedreader_CompressedBufferedReader_spec, __pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_CompressedBufferedReader) < (0)) __PYX_ERR(0, 331, __pyx_L1_error) #else __pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_CompressedBufferedReader = &__pyx_type_17clickhouse_driver_14bufferedreader_CompressedBufferedReader; #endif @@ -9618,7 +10330,7 @@ static int __Pyx_modinit_type_init_code(__pyx_mstatetype *__pyx_mstate) { __pyx_mstate_global->__pyx_ptype_17clickhouse_driver_14bufferedreader_CompressedBufferedReader->tp_base = __pyx_mstate_global->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedReader; #endif #if !CYTHON_USE_TYPE_SPECS - if (__Pyx_PyType_Ready(__pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_CompressedBufferedReader) < (0)) __PYX_ERR(0, 243, __pyx_L1_error) + if (__Pyx_PyType_Ready(__pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_CompressedBufferedReader) < (0)) __PYX_ERR(0, 331, __pyx_L1_error) #endif #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000 PyUnstable_Object_EnableDeferredRefcount((PyObject*)__pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_CompressedBufferedReader); @@ -9628,8 +10340,8 @@ static int __Pyx_modinit_type_init_code(__pyx_mstatetype *__pyx_mstate) { __pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_CompressedBufferedReader->tp_getattro = PyObject_GenericGetAttr; } #endif - if (PyObject_SetAttr(__pyx_m, __pyx_mstate_global->__pyx_n_u_CompressedBufferedReader, (PyObject *) __pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_CompressedBufferedReader) < (0)) __PYX_ERR(0, 243, __pyx_L1_error) - if (__Pyx_setup_reduce((PyObject *) __pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_CompressedBufferedReader) < (0)) __PYX_ERR(0, 243, __pyx_L1_error) + if (PyObject_SetAttr(__pyx_m, __pyx_mstate_global->__pyx_n_u_CompressedBufferedReader, (PyObject *) __pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_CompressedBufferedReader) < (0)) __PYX_ERR(0, 331, __pyx_L1_error) + if (__Pyx_setup_reduce((PyObject *) __pyx_mstate->__pyx_ptype_17clickhouse_driver_14bufferedreader_CompressedBufferedReader) < (0)) __PYX_ERR(0, 331, __pyx_L1_error) __Pyx_RefNannyFinishContext(); return 0; __pyx_L1_error:; @@ -10039,32 +10751,47 @@ __Pyx_RefNannySetupContext("PyInit_bufferedreader", 0); /* "clickhouse_driver/bufferedreader.pyx":179 * return items * + * def read_strings_arrow(self, unsigned long long n_items): # <<<<<<<<<<<<<< + * """ + * Reads ``n_items`` varint-prefixed strings into Arrow-style +*/ + __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_14BufferedReader_11read_strings_arrow, __Pyx_CYFUNCTION_CCLASS, __pyx_mstate_global->__pyx_n_u_BufferedReader_read_strings_arro, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[4])); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 179, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000 + PyUnstable_Object_EnableDeferredRefcount(__pyx_t_2); + #endif + if (__Pyx_SetItemOnTypeDict(__pyx_mstate_global->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedReader, __pyx_mstate_global->__pyx_n_u_read_strings_arrow, __pyx_t_2) < (0)) __PYX_ERR(0, 179, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "clickhouse_driver/bufferedreader.pyx":267 + * return offsets, data + * * def read_fixed_strings_as_bytes(self, Py_ssize_t n_items, # <<<<<<<<<<<<<< * Py_ssize_t length): * cdef Py_ssize_t i */ - __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_14BufferedReader_11read_fixed_strings_as_bytes, __Pyx_CYFUNCTION_CCLASS, __pyx_mstate_global->__pyx_n_u_BufferedReader_read_fixed_string, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[4])); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 179, __pyx_L1_error) + __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_14BufferedReader_13read_fixed_strings_as_bytes, __Pyx_CYFUNCTION_CCLASS, __pyx_mstate_global->__pyx_n_u_BufferedReader_read_fixed_string, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[5])); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 267, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000 PyUnstable_Object_EnableDeferredRefcount(__pyx_t_2); #endif - if (__Pyx_SetItemOnTypeDict(__pyx_mstate_global->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedReader, __pyx_mstate_global->__pyx_n_u_read_fixed_strings_as_bytes, __pyx_t_2) < (0)) __PYX_ERR(0, 179, __pyx_L1_error) + if (__Pyx_SetItemOnTypeDict(__pyx_mstate_global->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedReader, __pyx_mstate_global->__pyx_n_u_read_fixed_strings_as_bytes, __pyx_t_2) < (0)) __PYX_ERR(0, 267, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - /* "clickhouse_driver/bufferedreader.pyx":192 + /* "clickhouse_driver/bufferedreader.pyx":280 * return items * * def read_fixed_strings(self, Py_ssize_t n_items, Py_ssize_t length, # <<<<<<<<<<<<<< * encoding=None): * if encoding is None: */ - __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_14BufferedReader_13read_fixed_strings, __Pyx_CYFUNCTION_CCLASS, __pyx_mstate_global->__pyx_n_u_BufferedReader_read_fixed_string_2, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[5])); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 192, __pyx_L1_error) + __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_14BufferedReader_15read_fixed_strings, __Pyx_CYFUNCTION_CCLASS, __pyx_mstate_global->__pyx_n_u_BufferedReader_read_fixed_string_2, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[6])); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 280, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000 PyUnstable_Object_EnableDeferredRefcount(__pyx_t_2); #endif __Pyx_CyFunction_SetDefaultsTuple(__pyx_t_2, __pyx_mstate_global->__pyx_tuple[3]); - if (__Pyx_SetItemOnTypeDict(__pyx_mstate_global->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedReader, __pyx_mstate_global->__pyx_n_u_read_fixed_strings, __pyx_t_2) < (0)) __PYX_ERR(0, 192, __pyx_L1_error) + if (__Pyx_SetItemOnTypeDict(__pyx_mstate_global->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedReader, __pyx_mstate_global->__pyx_n_u_read_fixed_strings, __pyx_t_2) < (0)) __PYX_ERR(0, 280, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "(tree fragment)":1 @@ -10072,7 +10799,7 @@ __Pyx_RefNannySetupContext("PyInit_bufferedreader", 0); * cdef tuple state * cdef object _dict */ - __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_14BufferedReader_15__reduce_cython__, __Pyx_CYFUNCTION_CCLASS, __pyx_mstate_global->__pyx_n_u_BufferedReader___reduce_cython, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[6])); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 1, __pyx_L1_error) + __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_14BufferedReader_17__reduce_cython__, __Pyx_CYFUNCTION_CCLASS, __pyx_mstate_global->__pyx_n_u_BufferedReader___reduce_cython, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[7])); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 1, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000 PyUnstable_Object_EnableDeferredRefcount(__pyx_t_2); @@ -10086,7 +10813,7 @@ __Pyx_RefNannySetupContext("PyInit_bufferedreader", 0); * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< * __pyx_unpickle_BufferedReader__set_state(self, __pyx_state) */ - __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_14BufferedReader_17__setstate_cython__, __Pyx_CYFUNCTION_CCLASS, __pyx_mstate_global->__pyx_n_u_BufferedReader___setstate_cython, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[7])); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 16, __pyx_L1_error) + __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_14BufferedReader_19__setstate_cython__, __Pyx_CYFUNCTION_CCLASS, __pyx_mstate_global->__pyx_n_u_BufferedReader___setstate_cython, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[8])); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 16, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000 PyUnstable_Object_EnableDeferredRefcount(__pyx_t_2); @@ -10094,19 +10821,19 @@ __Pyx_RefNannySetupContext("PyInit_bufferedreader", 0); if (__Pyx_SetItemOnTypeDict(__pyx_mstate_global->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedReader, __pyx_mstate_global->__pyx_n_u_setstate_cython, __pyx_t_2) < (0)) __PYX_ERR(2, 16, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - /* "clickhouse_driver/bufferedreader.pyx":236 + /* "clickhouse_driver/bufferedreader.pyx":324 * super(BufferedSocketReader, self).__init__(bufsize) * * def read_into_buffer(self): # <<<<<<<<<<<<<< * self.current_buffer_size = self.sock.recv_into(self.buffer) * */ - __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_20BufferedSocketReader_3read_into_buffer, __Pyx_CYFUNCTION_CCLASS, __pyx_mstate_global->__pyx_n_u_BufferedSocketReader_read_into_b, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[8])); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 236, __pyx_L1_error) + __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_20BufferedSocketReader_3read_into_buffer, __Pyx_CYFUNCTION_CCLASS, __pyx_mstate_global->__pyx_n_u_BufferedSocketReader_read_into_b, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[9])); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 324, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000 PyUnstable_Object_EnableDeferredRefcount(__pyx_t_2); #endif - if (__Pyx_SetItemOnTypeDict(__pyx_mstate_global->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedSocketReader, __pyx_mstate_global->__pyx_n_u_read_into_buffer, __pyx_t_2) < (0)) __PYX_ERR(0, 236, __pyx_L1_error) + if (__Pyx_SetItemOnTypeDict(__pyx_mstate_global->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedSocketReader, __pyx_mstate_global->__pyx_n_u_read_into_buffer, __pyx_t_2) < (0)) __PYX_ERR(0, 324, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "(tree fragment)":1 @@ -10114,7 +10841,7 @@ __Pyx_RefNannySetupContext("PyInit_bufferedreader", 0); * cdef tuple state * cdef object _dict */ - __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_20BufferedSocketReader_5__reduce_cython__, __Pyx_CYFUNCTION_CCLASS, __pyx_mstate_global->__pyx_n_u_BufferedSocketReader___reduce_cy, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[9])); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 1, __pyx_L1_error) + __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_20BufferedSocketReader_5__reduce_cython__, __Pyx_CYFUNCTION_CCLASS, __pyx_mstate_global->__pyx_n_u_BufferedSocketReader___reduce_cy, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[10])); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 1, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000 PyUnstable_Object_EnableDeferredRefcount(__pyx_t_2); @@ -10128,7 +10855,7 @@ __Pyx_RefNannySetupContext("PyInit_bufferedreader", 0); * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< * __pyx_unpickle_BufferedSocketReader__set_state(self, __pyx_state) */ - __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_20BufferedSocketReader_7__setstate_cython__, __Pyx_CYFUNCTION_CCLASS, __pyx_mstate_global->__pyx_n_u_BufferedSocketReader___setstate, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[10])); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 16, __pyx_L1_error) + __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_20BufferedSocketReader_7__setstate_cython__, __Pyx_CYFUNCTION_CCLASS, __pyx_mstate_global->__pyx_n_u_BufferedSocketReader___setstate, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[11])); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 16, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000 PyUnstable_Object_EnableDeferredRefcount(__pyx_t_2); @@ -10136,19 +10863,19 @@ __Pyx_RefNannySetupContext("PyInit_bufferedreader", 0); if (__Pyx_SetItemOnTypeDict(__pyx_mstate_global->__pyx_ptype_17clickhouse_driver_14bufferedreader_BufferedSocketReader, __pyx_mstate_global->__pyx_n_u_setstate_cython, __pyx_t_2) < (0)) __PYX_ERR(2, 16, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - /* "clickhouse_driver/bufferedreader.pyx":250 + /* "clickhouse_driver/bufferedreader.pyx":338 * super(CompressedBufferedReader, self).__init__(bufsize) * * def read_into_buffer(self): # <<<<<<<<<<<<<< * self.buffer = bytearray(self.read_block()) * self.current_buffer_size = len(self.buffer) */ - __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_24CompressedBufferedReader_3read_into_buffer, __Pyx_CYFUNCTION_CCLASS, __pyx_mstate_global->__pyx_n_u_CompressedBufferedReader_read_in, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[11])); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 250, __pyx_L1_error) + __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_24CompressedBufferedReader_3read_into_buffer, __Pyx_CYFUNCTION_CCLASS, __pyx_mstate_global->__pyx_n_u_CompressedBufferedReader_read_in, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[12])); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 338, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000 PyUnstable_Object_EnableDeferredRefcount(__pyx_t_2); #endif - if (__Pyx_SetItemOnTypeDict(__pyx_mstate_global->__pyx_ptype_17clickhouse_driver_14bufferedreader_CompressedBufferedReader, __pyx_mstate_global->__pyx_n_u_read_into_buffer, __pyx_t_2) < (0)) __PYX_ERR(0, 250, __pyx_L1_error) + if (__Pyx_SetItemOnTypeDict(__pyx_mstate_global->__pyx_ptype_17clickhouse_driver_14bufferedreader_CompressedBufferedReader, __pyx_mstate_global->__pyx_n_u_read_into_buffer, __pyx_t_2) < (0)) __PYX_ERR(0, 338, __pyx_L1_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "(tree fragment)":1 @@ -10156,7 +10883,7 @@ __Pyx_RefNannySetupContext("PyInit_bufferedreader", 0); * cdef tuple state * cdef object _dict */ - __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_24CompressedBufferedReader_5__reduce_cython__, __Pyx_CYFUNCTION_CCLASS, __pyx_mstate_global->__pyx_n_u_CompressedBufferedReader___reduc, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[12])); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 1, __pyx_L1_error) + __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_24CompressedBufferedReader_5__reduce_cython__, __Pyx_CYFUNCTION_CCLASS, __pyx_mstate_global->__pyx_n_u_CompressedBufferedReader___reduc, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[13])); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 1, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000 PyUnstable_Object_EnableDeferredRefcount(__pyx_t_2); @@ -10170,7 +10897,7 @@ __Pyx_RefNannySetupContext("PyInit_bufferedreader", 0); * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< * __pyx_unpickle_CompressedBufferedReader__set_state(self, __pyx_state) */ - __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_24CompressedBufferedReader_7__setstate_cython__, __Pyx_CYFUNCTION_CCLASS, __pyx_mstate_global->__pyx_n_u_CompressedBufferedReader___setst, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[13])); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 16, __pyx_L1_error) + __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_24CompressedBufferedReader_7__setstate_cython__, __Pyx_CYFUNCTION_CCLASS, __pyx_mstate_global->__pyx_n_u_CompressedBufferedReader___setst, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[14])); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 16, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000 PyUnstable_Object_EnableDeferredRefcount(__pyx_t_2); @@ -10185,7 +10912,7 @@ __Pyx_RefNannySetupContext("PyInit_bufferedreader", 0); * cdef object __pyx_result * __Pyx_CheckUnpickleChecksum(__pyx_checksum, 0x5e0d780, 0x07c78bc, 0x2a8a945, b'buffer, current_buffer_size, position') */ - __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_1__pyx_unpickle_BufferedReader, 0, __pyx_mstate_global->__pyx_n_u_pyx_unpickle_BufferedReader, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[14])); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 4, __pyx_L1_error) + __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_1__pyx_unpickle_BufferedReader, 0, __pyx_mstate_global->__pyx_n_u_pyx_unpickle_BufferedReader, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[15])); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 4, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000 PyUnstable_Object_EnableDeferredRefcount(__pyx_t_2); @@ -10198,7 +10925,7 @@ __Pyx_RefNannySetupContext("PyInit_bufferedreader", 0); * int __Pyx_CheckUnpickleChecksum(long, long, long, long, const char*) except -1 * int __Pyx_UpdateUnpickledDict(object, object, Py_ssize_t) except -1 */ - __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_3__pyx_unpickle_BufferedSocketReader, 0, __pyx_mstate_global->__pyx_n_u_pyx_unpickle_BufferedSocketRea, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[15])); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 4, __pyx_L1_error) + __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_3__pyx_unpickle_BufferedSocketReader, 0, __pyx_mstate_global->__pyx_n_u_pyx_unpickle_BufferedSocketRea, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[16])); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 4, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000 PyUnstable_Object_EnableDeferredRefcount(__pyx_t_2); @@ -10213,7 +10940,7 @@ __Pyx_RefNannySetupContext("PyInit_bufferedreader", 0); * cdef object __pyx_result * __Pyx_CheckUnpickleChecksum(__pyx_checksum, 0x69923fe, 0xfd1be99, 0x183c0eb, b'buffer, current_buffer_size, position, read_block') */ - __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_5__pyx_unpickle_CompressedBufferedReader, 0, __pyx_mstate_global->__pyx_n_u_pyx_unpickle_CompressedBuffere, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[16])); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 4, __pyx_L1_error) + __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_17clickhouse_driver_14bufferedreader_5__pyx_unpickle_CompressedBufferedReader, 0, __pyx_mstate_global->__pyx_n_u_pyx_unpickle_CompressedBuffere, NULL, __pyx_mstate_global->__pyx_n_u_clickhouse_driver_bufferedreader, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[17])); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 4, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000 PyUnstable_Object_EnableDeferredRefcount(__pyx_t_2); @@ -10223,7 +10950,7 @@ __Pyx_RefNannySetupContext("PyInit_bufferedreader", 0); /* "clickhouse_driver/bufferedreader.pyx":1 * from cpython cimport Py_INCREF, PyBytes_FromStringAndSize, PyBytes_AsString # <<<<<<<<<<<<<< - * from cpython.bytearray cimport PyByteArray_AsString + * from cpython.bytearray cimport PyByteArray_AsString, PyByteArray_Resize * # Using python's versions of pure c memory management functions for */ __pyx_t_2 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1, __pyx_L1_error) @@ -10338,31 +11065,31 @@ static int __Pyx_InitCachedConstants(__pyx_mstatetype *__pyx_mstate) { static int __Pyx_InitConstants(__pyx_mstatetype *__pyx_mstate) { CYTHON_UNUSED_VAR(__pyx_mstate); { - const struct { const unsigned int length: 10; } index[] = {{1},{179},{34},{8},{36},{7},{6},{2},{9},{23},{48},{54},{14},{5},{14},{32},{34},{19},{42},{33},{31},{23},{27},{20},{38},{40},{37},{24},{42},{44},{41},{20},{18},{1},{10},{7},{10},{10},{8},{13},{32},{18},{4},{8},{8},{5},{6},{8},{8},{12},{1},{8},{13},{4},{5},{1},{6},{8},{10},{7},{8},{7},{13},{6},{3},{14},{12},{11},{10},{29},{35},{39},{12},{4},{10},{10},{18},{27},{16},{8},{12},{9},{10},{17},{13},{5},{2},{4},{12},{10},{12},{19},{5},{4},{4},{5},{5},{1},{8},{6},{6},{12},{6},{613},{11},{11},{11},{183},{41},{55},{248},{52},{7},{94},{105},{107},{100},{57},{59},{58}}; - #if (CYTHON_COMPRESS_STRINGS) == 2 /* compression: bz2 (1893 bytes) */ -const char* const cstring = "BZh91AY&SY\361\265\251\003\000\001\232\377\377\377\377\377\377\376\357\377\375\377\377\377\316\277\377\377\364@@@@@@@@@@@@@\000@\000`\006\375\360z\355\347o[l\351\322\333\255\330d\360\007<\031$\322Hy\020\310=\032\236&F\247\206\231\024\365\000\3656\247\247\251=F\215\251\352h`\203\312zM4mOD\365\014z\223jfMOPdDS\332\247\244\305?\325O2jOm*zF\237\252z\236\220\000hd\000\000\000\000\000\0004h\000h\031&!\032\246!=M\017(<\247\250\000\000=A\240\000\000\000\000\000\000\323A\240\320\006\"\021O(\311\212\001\352{Jd\362\200\r\000\032\000\000\000\000\000\000\032\001\352i\352h\320A\200\023\000\000\000\230\000L\000\000\002`\004\320\300\000\000\000\000\001\"\2014\t\241\0315Oj#OSjz\231\0004\001\240\032h\000\000\000\032\000\000\001\243\"s5\n\263\260t\007l\034\037\2020\224W\3534\341\016\263\263\235@\300#\t9\317\004\0354\327N\351\025\272\271\327\374\006\244\026S\031\005\367\2661\203`\306\306\3066\333cLM\014\033\013\005\023\n\255\010-UW\225\2650m\003ch\036%\025\211\226\0251\302F\t\223\224\267\314w\225\r\267\201\004Ln\350\013\021b0m1\223\337\262v1\206&R\237\037\023D\3142nq\211\0354%\206\0304\325\205\205\025\266O\032\253\224G\246\333H\022\246M6\330\306P\244\264v\\T\005@\322\205o9\205\263}B\312\224\017\212^*\222\220i\003!\013\025\212fD\016N\355\212\352\225\247\tz\202\203 \\f\303te\327\005H]\312p\016:\340\0261\372\207\032L\273o\210\273\272\365&\010z\245\317\315\332L\335\017\004\376\262\0160\200\230\254\214K\357\202\275\205\204c\334\261\220q\215\341x\013\270/\201v\340\323\352fb&U\2440EB<\244\332Q\203n\"\211\330\305\234\ns\360\312,\n\337\254\033\250\345)_\226\3654\324\013\n`@\250Jg\212\0318\314\200\270t\236\202\330\242\351R2D7\327\243\001\264Hj\221\256\014X\225\215R\226\330\261O\230`g\364\274\253\312\326\232\017\023Z\313\022\245Qg\212k2\327\032\353\261c|\273,\247\271\213\300\335\221n%B\216E\325J\245\310\346\342\377\250\0068\262+4\335\270C]\265I\006\213,\221d\256\025\356lr\322\311d\236\305\267\212\203\010\251M\217\030\004\255\327\025\210\312i\303\231\314ohL\214G\241\324\261H\213suw\307y\250d\244""\210\355u|\001n\027\010s\326\246iA\210,\030\2329\242y\254\221-\336c\033C`\330\333\222\241\364+\346\212h\007x:}[\330\315\032\335\327\201\200\025\320\314\250F\232~v\200\025 \220Vs\334\234\260n08\036A$C\276\341\263\0271p\1773skqYL7\r\254-\0266\240(4B`B\t4\220\002\310\315\016a\022\017\245\020\205\255Z\342\241\375\343 -h\271\245k\334\215\345\242\225\322mB\350\325\333\321\270\002nm\002\317\316\347ej\325\305\317\304\327\376\233\324\322d\226\207\0066\031U\201\225Q\3138\000R\306\225c\003\0314\363\rL n\n\212\033\376\0062\345\013*\250\313\225\267{\253+\220\261\255'\230\223FHf\031\014\266\305\\\326\023c\010\200\344\325ZHi\027\262\r\246y&s\272\334:\252\r\006\206\337q\3632\241`u\213\001!\331\213\025\026\013y\026\243oj\224\260E\005\244\342\223\264,\240o\243).N}\220\232\014\244N\326\241y\005\272\222 Ealv\324\003\237r\257\245ED\341QV\256\217\355\223\000\224cD\322A\005 \306\333T\322\203X\344\233Ed\223\266t\247\022PM\003\326\327E|\252\312\002\270-.\r\237;\r\230V\224!\216\320\017R\005\222\022H\301\203\013I\271\273\326\273\2365\272L_\201o7\177C\00607y\203\305\347e\264g9\354tQ\341B@\356V\204\233\222\030\001\353Z\250`\252U?H\272\231\354$\201yQ\316s\275.\337\372\261\327\314EF@\372\006\005s\254i\355\276\013!\026\377\211\221\371&Z\336\2520\363*Js\207\2021\336\033}5\301e\317S,p\234r0>%\312\206\026p\373\221\366}QR\271\274\032IXr-T\226B\221\030\230\313t]\232\252?\252\2770\230R\026\356k2\2168o\002\373e\347\233bh\3654s\315vl\336\330M\\7%\322\301\2358W\266\n\205\327\032@A;NtG\270\243O\236Mm\002yC\022\201\r\013\231\351\370\030\234ZN+\301\371\326\025\237\303\376\030\324\013\"\022\254M\341G\312#\317\226\020\362p\013B\026\342x\326\367\326\375\242\226e+\347\333\367\222\224}\003\r\342U\344)\265i\351\225E\241\234C\220\027\251\016iV\332e\342(\254\326\304\265\225+^\244\214\224\224\322\266\010\341\215\227Z\3424t\376\270\335\3441TQ\240y\024\301-\346\232\274\255\204\244zy\222\010i\311P\334\201-v\345h\270\034\220\004\245$&u,\330\013\365;a~\270\366r{\212G(\350\nsj!#\244,\223\301\264\204X\345K\210\336\263=)Q4l\273(\0031Q\212xL<\333\305\312\364\r\2422`9\005\256\031\204\004`sXpey\324\003\302\030\ti\014q\020R\037\014\rT\213\223\033\340\223SP\305Ou1&\245\355:\016\345\312]$\267\304\317\320\271\262K\024\261l\034\215\331\316\350\036D`\241\333\233\262\233\212\354\323\207\022mm\211O\213bU;\226A\351HtBJ\021\n\025\234\tUB\016\007\312Gz2+sw\360o\336`^\261\251b\004\360\275S\n\271\246\360c\002\315\2137\234\262x0\224\034\213Z6S1l\021\006NG\226\245>\370Q\233\320\210\013\230\304\312\025\010N\350&XP*\213Qi\244\247B?\342\356H\247\n\022\037\305:\374 "; + PyObject *data = __Pyx_DecompressString(cstring, 2098, 2); if (unlikely(!data)) __PYX_ERR(0, 1, __pyx_L1_error) const char* const bytes = __Pyx_PyBytes_AsString(data); #if !CYTHON_ASSUME_SAFE_MACROS if (likely(bytes)); else { Py_DECREF(data); __PYX_ERR(0, 1, __pyx_L1_error) } #endif - #elif (CYTHON_COMPRESS_STRINGS) != 0 /* compression: zlib (1770 bytes) */ -const char* const cstring = "x\332\255U\317w\323V\026\306\035\317`\212\023\354D\020\233\206D\312\244\207\366\264ukj\010\320\036f\014\tL\351\224\301\220\002\347L{\336\221\245g[\304\221l\375\0106g\026,\275\324\362-\337RK-\265\364\222\245\226Z\352O\340O\230{%\033\022\307f\316\314\231\234Xz~\357\376\370\356w\277\373\374\227G\206ME\273#\333\342\275\241\3351tQ\263D\225v\265&5e\233v\207\242e\233\232bS\023\215t\361\361\336\343oj7k\242\254\253\242I_R\305\266D\313i*]\331\262\250%\032-\261\351h][\323E{\330\243VE\374\251%\016\rG\324)UE\333\020{`w\334\301\356P]\264\250\215\013\361\252\254\353\206-\333\232\241\023p\327\364\366UQ\325LH\242\035Q\364\276/w-Z\371U\247\203\036lB\304\275\177\334\027_u\264.\0050\262\n\016bshSKVU\002\221\250\322\325\224\203\216\341X\224\250&\3040\277m:\255\0265\251\212\346\324\254\364\206\003U\263\344f\227R\035\237mE\263\322\225j\321n\253\222\232#'\020N|d\350t\301\266h\230brd\031\312\301\177c\217@H\263;\343\365#\262\256\267-\3031\025z\307\261[\337\334\274;A\376$A~\362[\205\020X;\n%J\322DBN\235\003\307\026P\273\320\002q\314\331\"-m@U2\201Cd\213$\004\377G\313y\006\232n\033$\245b\3361\224=o{&\340S`\212\332'I8\276\267\230\212\031\253\205\204\234\260\233\005~\3178\354\231\024\244;C\326\242\375\323p>by\n\322B\333YX\204<\036\016\340\263\013\243J\036\321\001\300o\311\326PW4\243\242\030\246\341\300DR\25391\356\331&\254,\3555M\232I0\232B\250\256\0308B\312\204\362\351\233\240\341\251I\252\234\234$8\327) \"\266)+\264)+\007\252l\313\370\301l\204\250\010,}%y\3504\033!-GW\340\210\264\247\325\023\r\376u\r\3555\213\274\207\257\331\364\020?\326\313.\325\333v\207\220C\031\022\302\337\241\241:]\360\323Ir\016\013\371\220\342\201N_\341c`\223\236aix\257\030M\274\263zF\217\020\230}\242t\250r`9\207\3517\240\332\351\332\351z\002\005\227x\223\245+G\357\001\r\220\352d;\026\034\036\027\322\214\311\242\306\022\322w\344n\n\037\211\375p;\244+l\327\351a\373\310\240\316\ne:i\307G\013.\330\243\324f\252UrJ\265\3577\350\000\226Z\273c\233Gx\177%\242\235\360\r+\025d\227P\370^\312d\216\254\255\216\326\262QUxY&G\226\323""\243&\270\301\n\236\216\216\360\234\036\310\207\242\342\246\001\216\344\256C\2550\373\327q\346\335\247g\316\025\335\363\254\312\352\357rg\316I\241X\363\353\376~P|\267|\346\334&\223\243\334w~&\312\211\034\036\347G\325(\277\346\016\330+.\363~\224/\263b\234+\263K\254\037O\317\206|\311kx-\277\036\347\362\243=\367\242+\273`(\270\017X\365\335\237\316,-G\205U\267\346\276\346\253|\327\313DB),}\351\025cA\n\245\353~\303W\003\t\366X\236\327\343\202\340>d2\263y5\202\345/\274\030\027\312l\205]c\317\370\367\\\3060\327\334'\020[\270\210\007\305\030r\354\262O\371\026\270\346/\214\372hp\235}\302\266\330]\250A\330\346{\336\212W\215\204M6\364\226 \323\3131dG\270\177\200\004\245rT(\261\014+\361bT\270\302\032\300\311Rat\004\361mV\305H\340x\231I\300\321\337x\235\377\356K\376\355\240\021\250c)\372l3\334\254\371w\021x,\224\303\3625_\202h\3542\257&\365\225\326\303\365\252\277\342\327\374>T_\334`\373\241t\303o\006\331\000\n\274\344\036\000\r\365\264\340\004^<\207\017\330c\027\200\354\322:\373\231\333h\263\006U\2276\240\252\365+\354\005o\360C\377\307\300\036#\275\345\315pc\307\357G\353_xY\257\036\013[|\233\313\230X\230Vp\033\354_\372\031_\360\177\033\027O#\316\373\t\361\177\347\231\t\211\305H(\003-+\374\272w\326\353\203\020\326J\321\304\0139\210\363\027\335\206+G\371uVg\317\371=>\025\302%\354{\234\203\030o2Q\026\255o\004E\\\336\360e\377(h\340\362k\257\356=\363\253o\352\200\360\\\325?\353\233\201\0204Pew\240\3215\006\272)\270Y\267\216\257<\203\027v4\303\004HT\347O\022.r\342{\271\306\271\245\321\257\256\024\347\226G\355D\030P\200\355\336fOy\0268.\010\241\3609o@w\303+U\277\350o\373r4-\024\261\277\340\373\341\227w\202\3468;\206D+\341\312W \226B\321\275\014=\337\345y \023@,\261FRYZW=\312\345\303\374\237y\215;\336C\250\312\016\252X|-\274\260\215D@\024\367\013\324\014\032\302\366\3505[\205P\031\250&,H \264\264*\204\275\357\256%uA\355\371\321/\254\030M\342o\177\216\236\267\334{X\r\214M\270\366\275_\365\177\n\032H\230\340\336d;\\\002\365\246\263\211\325\"=k\374\023.E\271\215p\243\342\311\036\364`\203u""x\027\032\260\023l\005\023(\020n)\312\025\334\014\326\027\303\"\031\377\350\370\304\256\270\022\220\327\000_\231\233\240\315[>\266i\251\350\236uM@\010\347[\200\313\004\324\373\274\344\025=)*\200\024b\210[\300\013\302\004\311\\\203&\275B\014\321\252\000\273\341\032\\$\376\345\000\324qZ4\230\256\372\201\327\321CWc}\350\334\317\340\235\322\014C\237\266|\001\305\313#9URa\021\021\363\312\\\rWQ\206\r\257\003\0354\203\225\340\026\366\177\026_\332\220\014\334\217\177\\\206n\225\331v\270Q\363w\203\363\343\332\270\037e\363\243\007n\325\275\317\276\206{){\366\315\321\350\271\273\227\266\023\312\212rk8\tp\275\340\031\206\n/\\G\301\006W\307\237\275}\020>\335\217On\325\377\217\211n\341D\005\355\361?\303\307\317\303\347/\342\231\275\306\234T\231\377!\315\267\236\r\302|\020\3740n\277m\304'w\3447\2318\273\311\372\241\370\235\177\036\276\037\204\215'Qv\325\2753\221\r\004\371\227\273\303\244\344w&\254\336\035W\000W\224\205[d\276c\270\372\225w\023b\327\217y\336\016\244\360\207g\34135T\351G]\257\362Ar\213}p\205\373(\334y\364V\017\177\373=\361\3747\257\223h\346"; - PyObject *data = __Pyx_DecompressString(cstring, 1770, 1); + #elif (CYTHON_COMPRESS_STRINGS) != 0 /* compression: zlib (1978 bytes) */ +const char* const cstring = "x\332\275U\317S\333X\022\306Y\357\306L\014\330\340\304&! \263\314fR\311\220qb \311Le\327\004\302Nf&\033\023&\241vg\352\225,=c\201\221l\375\000\234\332\003G\037u|\307w\324QG\035}\314QG\035\365'\360'l\267l\363\303\340l\315\324\326R\330z~\257\273_\367\327\337\327\372\353\033\315\244\202Y\023M\341e\313\254i\252\240\030\202L\353J\205\352\242I\353-\3010uE2\251\216F\252\360v\375\355\327\305\247EATeA\247\273T2\r\301\260*R]4\014j\010ZU\250XJ\335TT\301l5\250\261(|_\025Z\232%\250\224\312\202\251\t\r\260;\357`\326\250*\030\324\304\205pOTU\315\024MES\t\270+\352\316=AVt\270D9\240\350\375J\254\033t\361g\225\0365`\023\"\256\377\343\225pXS\352\024\222\021ep\020*-\223\032\242,\023\210D\245\272\"\355\3254\313\240D\326!\206\376\250bU\253T\2472\232S}\261\321:\222\025C\254\324)U\361{GR\214\356J6h\275\272\3305GL \234\360FS\351\220mA\323\205\350\310\320\244\275\337b\217\211\220J}\300\353;D]\33514K\227\350\013\313\254~\375t\265\227\371f\224\371\305_\213\204\300\332\222(\221\242&\022r\351\03406\000\332\241\026\230\307\025[\244\252\034Q\231\364\322!\242A\"\200\377\253\345U\006\212jj\244\013\305U\307P\366U\333\237\tx\232\225\256k\207}\203w\000%5/\242t~o8V\003VC\021\273`7X\331Km\277\241S\340\366\000\232\303\366/\247\363\031\313K)\r\265\035L\213\220\267\255#\370\254\201\226\311\033z\004\351WE\243\245J\212\266(i\272f\201d\251Q\351\0317L\035V\206\362\221F\335&\030M\"T\2254\324\230\324\003\276\377$hxIj\213\027\245\006\347*\205\214\210\251\213\022\255\210\322\236,\232\"~\210$6DI1[\321\017\270:zbLBdL\267\373\210n\247\375\034\010\251Z\252\004Gd\247\217\tQ\340_U\320^1\310iQ\212I\367\361c\354\326\251\272c\326\010\331\027!\r\370\333\327d\253\016~*\211\316a!\356S\031\037\031\235cb\220\370\306\215\005\t\201\303\327\215v!Hf\355#v\310E\336\014\222\323,\035&\246\331-\326\014\373g->\346\224\235\252[\n\023\311\366\272}\323\026m0\314\330\033\254p\362\247\221\261\361 5e\027\355\217|\212\2579\261 \223\363s\367\235t\230\311\373\371%\267\354\312^\036\366X\222\227\302T\306~\315Df\362B\000\313\237x:LM\263I\366\230\275\347O\270\210a\036\333\233\020;s\023\017\322!\334\261\306\276\340\363\340\232\234h7\321`\211]c\363l\025j\310,\360ug\322)\004\2319\326r\306\340\246\335\016\334\216\351\376\001.\310M\007\251\034\213\261\034O\007\251\273\254\014\230\214\245\332\007\020\337d\005\214\004\216\267Y\0360\372;/\361_\335\274\373\334+{r'\037\334\231\363\347\212\356*&\036f\246\375\351\307n\036\242\261\333\274\020\325\227\233\361g\n\356\244[t\233P}z\226m\371\371e\267\342\305=(\360\226\275\0070\224\272\005G\351\205W\340\001{l\002\300\316\315\260\037\270\2116Y\250:7\013U\315\334e\333\274\314\367\335\357<\263\203\360N\317\371\263+n3\230\371\312\211;\24503\317\027\270\210\027g\372\025<\007\373]7\346f\334_:\351\313\031'\335\010\370\037y\254\007b:\310L\003,\223|\311\271\3564\201\010\331\\\320\363B\014\302\344M\273l\213Ar\206\225\330\007\376\222\367\211p\013\373\036& \306q,\210\243\365\262\227\306\345\262+\272\007^\031\227\017\235\222\363\336-\034\227 \303\321\202{\335\325\275\214WF\226\275\200F\027\031\360&e\307\355\022>\222\014\036\330\321\030\313\300E%\276\031a\221\020N\351\032&\306\332?\333\37101\336\336\211\210\001\005\230\366s\366\216\307\001\343T\306\317|\311\313\320]\377n\301M\273\013\256\030\364\013\305\334\267\371\226\177\377\205W\351\304;p\321\244?\371\000\310\222J\333\267\241\347k<\t`B\022c\254\034U\326\255\253tr\353\202\\\222#\243S\366} \3506$g8\363N)H\374\205\357\373O6:\220\314X\230\000\032\331\353\250\230\207x\204\252\002\316\256\332\025`\351""\003\276\355l:\315\000\002\267\240\304t\220\230\365g\021\265\302\377]F\023\355\217p\276\304\257\361|\000\024U\371*\020\346\032\220\244\213\337<\317\363e\007dr\307\277\363\010\0311 \274\236hB\220\321\031\3271\020\024\300\022<\306g`<\354z\261\250\325\331\334\357W\301\231\036\377\351\350\356]O\004-\002e\3168\237\035r\345i\337\241\\\234X\315hJ\254\243U\230\300\250\3130\005\272\2158\206>%\375\344\237y\221[\316k`\256\351\025\220\340E\177b\001\311\016L\261\277\302<\320\020\266\001\272)\240\01346\345\247\362\020\246\313\\\244\346\226\235\215\270\013\374N\266\177b\321\r\300\241`\341K\364|f\277\304\376BO\375\354\023\267\340~\357\225Q\024\031\373)[\001\300\013\275\371\213\214F\td\243\356 G\026\035\321\001\235\315\262\032\257\003]V\274y\257\227\nr.H\244\354\030r8\204E4\342\203\363t\232\264\363 \2202\370\212\\\007\344\237\271(\305\261\264}\335\326\021\233I{\036\362\322!\353-\236s\322\016\020\002\344\036B\334\024\276\004t\030\013\217\201\353\207\230C0\225\201]?\013\264vo{0\001.\017\006\274\256\320\323\016\346\361\332VX\023\324\371\003\022?\202\031\030\331\225\365\020\210\307\333bwZ\244\206\001qU\231S\376\024\216\232\262S\203\016\352\336\244\367\0145>\230_\267!1x\007\376q\034\2725\315\026\374\331\242\273\346\335\350\024A\277\361d{\003\344\373\212=\004\321\304\257\037\037\264?\200\226\243vBYA\"\213\323\016^!x\206\241\374\211%\034\n\336\275\316\235O\033\376\273\255\360\342V\351\177x\3213\344\265\267\323\371\227\377\366\203\377a;\034\330+_qU\354w\\\363\3101\201\230\033\336\267\235\235O\345\360\342\216x\034\013\343\240>_\370\306\275\001\277\367\374\362f\020\237\262_\364h\003A\376m\257\260|4\365\374\302jg\021\362\n\342\360\246\270\332\321\237z\340<\205\330\245s\236\317\275\274\377\355{\377\275\354\313\364\263\256\367\370Q\364\246:s\205w\216\277\362\346\223\352\377\362k\344\371\037R\367K("; + PyObject *data = __Pyx_DecompressString(cstring, 1978, 1); if (unlikely(!data)) __PYX_ERR(0, 1, __pyx_L1_error) const char* const bytes = __Pyx_PyBytes_AsString(data); #if !CYTHON_ASSUME_SAFE_MACROS if (likely(bytes)); else { Py_DECREF(data); __PYX_ERR(0, 1, __pyx_L1_error) } #endif - #else /* compression: none (3527 bytes) */ -const char* const bytes = "?Note that Cython is deliberately stricter than PEP-484 and rejects subclasses of builtin types. If you need to pass subclasses then set the 'annotation_typing' directive to False.Unexpected EOF while reading bytesadd_noteclickhouse_driver/bufferedreader.pyxdisableenablegcisenabledself.buffer is not Noneself.buffer is not None or self.sock is not Noneself.buffer is not None or self.read_block is not Noneutf-8BufferedReaderBufferedReader.__reduce_cython__BufferedReader.__setstate_cython__BufferedReader.readBufferedReader.read_fixed_strings_as_bytesBufferedReader.read_fixed_stringsBufferedReader.read_into_bufferBufferedReader.read_oneBufferedReader.read_stringsBufferedSocketReaderBufferedSocketReader.__reduce_cython__BufferedSocketReader.__setstate_cython__BufferedSocketReader.read_into_bufferCompressedBufferedReaderCompressedBufferedReader.__reduce_cython__CompressedBufferedReader.__setstate_cython__CompressedBufferedReader.read_into_buffer__Pyx_PyDict_NextRefasyncio.coroutinesbbuffer_ptrbufsizebytes_readc_encodingc_stringc_string_sizeclickhouse_driver.bufferedreadercline_in_tracebackdatadata_ptr__dict___dictencodeencoding__func____getstate__i__init___is_coroutineitemitemsjlength__main____module__n_items__name____new__next_positionobjectpop__pyx_checksum__pyx_result__pyx_state__pyx_type__pyx_unpickle_BufferedReader__pyx_unpickle_BufferedSocketReader__pyx_unpickle_CompressedBufferedReader__qualname__readread_blockread_bytesread_fixed_stringsread_fixed_strings_as_bytesread_into_bufferread_oneread_stringsrecv_into__reduce____reduce_cython____reduce_ex__rightrvself__set_name__setdefault__setstate____setstate_cython__shiftsizesockstatesupert__test__unreadupdateuse_setstatevalues\320\004@\300\001\360\n\000\t\021\220\013\2301\230A\360\010\000\t!\320 4\260A\260T\270\021\360\016\000\t\037\230a\330\0100\260\001\330\010 \240\001\330\010\013\2101\330\014\027\220x\230w\240a\240q\330\014\031\230\021\340\010\031\230\026\230q\340\010\013\2101\330\014\027\220y\240\r""\250Q\250f\260A\340\010\014\210E\220\025\220a\220q\330\014\024\220G\2301\360\006\000\r\016\330\020\023\2204\220z\240\023\240D\250\001\330\024\030\320\030)\250\021\340\024!\320!5\260Q\260d\270!\330\024\030\230\014\240A\340\020\024\220J\230a\230t\2401\330\020\024\220M\240\021\340\020\031\230\022\2302\230V\2403\240a\330\020\023\2202\220R\220q\330\024\025\340\020\031\230\021\340\014\024\220D\230\n\240\"\240A\340\014\017\210q\330\020\023\2205\230\002\230\"\230B\230a\330\024$\240E\250\022\2501\330\024\037\230y\250\r\260Q\260j\300\001\330\024\027\220y\240\003\2401\330\030\031\330\020\030\230\001\230\030\240\021\330\020\035\230Q\360\n\000\r\020\210v\220R\220t\2301\330\020\023\2201\330\024\032\230!\2301\230H\240A\240]\260!\260:\270Q\270d\300!\330\033\037\320\0374\260B\260d\270!\340\024\031\320\0312\260!\330\030\031\230\032\2401\240D\250\001\330\030\034\320\0341\260\022\2604\260q\360\006\000\021\036\230T\320!6\260b\270\004\270A\340\020\026\220k\240\023\240A\330\024\030\230\014\240E\250\022\2501\340\024\030\320\030)\250\021\340\024!\320!5\260Q\260d\270!\340\024\030\230\017\240q\330\030\034\230K\240t\2501\340\024\027\220q\330\030\036\230a\330\034\035\230X\240Q\240m\260<\270t\3001\360\006\000\031\037\320\0367\260q\330\034(\250\004\250A\340\024\"\240$\240a\360\006\000\021\024\2201\330\024\032\230!\230:\240Q\240j\260\001\260\024\260\\\300\021\340\024\031\320\0312\260!\330\030\031\230\032\2401\240D\250\014\260A\340\020\024\220L\240\001\340\014\017\210q\330\020\021\330\024\031\230\030\240\022\2405\250\007\250q\260\001\330\027\030\330\024\031\320\0312\260!\260:\270Q\340\014\025\220Q\220a\330\014\034\230A\230W\240C\240q\340\010\013\2101\330\014\026\220a\220q\340\010\017\210q\200\001\330\0042\260!\2606\270\021\200\001\330\0046\260a\260v\270Q\200\001\330\004,\250A\250V\2601\200A\360\006\000\t1\260\007\260r\270\024\270Q\330\010\013\210>\230\022\2304\230q\330\014\020\220\004\220A\330\014\020\220\014\230A\330\014\023\2205\230\001\230\024\230W\240A\240R\240t\2501\340\010 \320 4\260A\260T""\270\021\340\010\r\210U\220!\340\010\016\210g\220R\220q\330\014\017\210t\220:\230S\240\004\240A\330\020\024\320\024%\240Q\330\020\035\320\0351\260\021\260$\260a\330\020\024\220L\240\001\340\014\034\230A\230X\240T\320)>\270b\300\004\300A\330\014\022\320\022+\2501\330\020\021\220\032\2301\230D\240\014\250A\340\014\020\220\r\230Q\330\014\026\220a\340\010\017\210q\200A\330\010\014\320\014#\2404\240u\250J\260a\260t\2701\340\010\013\2104\320\017$\240C\240q\330\014\022\220(\230!\2301\200A\330\010\013\2104\210z\230\023\230D\240\001\330\014\020\320\020!\240\021\330\014\020\220\014\230A\340\010\r\210T\220\027\230\001\230\024\230Q\330\010\014\210M\230\021\330\010\017\210q\200A\330$%\330\010\013\2109\220C\220q\330\014\023\2204\320\0273\2601\260I\270Q\360\006\000\t\024\2208\2307\240!\2401\330\010 \240\001\330\010\017\210t\2205\230\001\230\027\240\002\240!\330\010\036\320\036.\250a\250q\340\010\036\230h\240l\260!\2607\270\"\270A\330\010\013\2104\210q\330\014\r\330\010\020\220\001\220\032\2301\340\010\020\220\013\2301\230A\330\010\014\210E\220\025\220a\220q\330\014\022\220!\220:\230Q\230h\240a\240r\250\022\2509\260A\360\006\000\r\021\220\007\220r\230\021\330\014\022\220\"\220C\220r\230\024\230T\240\030\250\021\250!\330\020\025\220Q\340\014\r\330\020\027\220x\230r\240\022\2402\240R\240w\250a\250q\330\023\024\330\020\027\320\0270\260\001\260\032\2701\330\014\025\220Q\220a\330\014\034\230A\230W\240C\240q\340\010\022\220!\2201\340\010\017\210q\200A\330\010\014\210J\220i\230q\240\004\240K\250q\330\010\014\320\014#\2403\240a\240t\2501\340\010\013\2104\320\017$\240C\240q\330\014\022\220(\230!\2301\200A\330\010\016\210a\200A\360\006\000\t\020\210t\2205\230\001\230\027\240\002\240!\330\010\036\320\036.\250a\250q\340\010\020\220\013\2301\230A\330\010\014\210E\220\025\220a\220q\330\014\023\320\023,\250A\250Q\250h\260a\260r\270\022\2709\300A\330\014\025\220Q\220a\330\014\034\230A\230W\240C\240q\330\010\017\210q\200\001\360\010\000\005\016\210T\220\031\230$\320\0364\260D\270\013\3004\300q\330""\004\014\210G\2201\220F\230,\240a\330\004\007\200v\210W\220E\230\024\230Q\330\010\022\220!\330\010\027\220q\340\010\030\230\001\330\004\007\200q\330\010\017\320\0175\260T\270\021\270'\300\033\310G\320ST\340\010\017\320\0175\260T\270\021\270'\300\033\310A\200\001\360\010\000\005\016\210T\220\031\230$\320\0364\260D\270\013\3004\300q\330\004\014\210G\2201\220F\230,\240a\330\004\007\200v\210W\220E\230\024\230Q\330\010\022\220!\330\010\027\220q\340\010\030\230\001\330\004\007\200q\330\010\017\320\0179\270\024\270Q\270g\300[\320PW\320WX\340\010\017\320\0179\270\024\270Q\270g\300[\320PQ\200\001\360\010\000\005\016\210T\220\031\230$\320\0364\260D\270\001\330\004\014\210G\2201\220F\230,\240a\330\004\007\200v\210W\220E\230\024\230Q\330\010\022\220!\330\010\027\220q\340\010\030\230\001\330\004\007\200q\330\010\017\320\017/\250t\2601\260G\270;\300g\310Q\340\010\017\320\017/\250t\2601\260G\270;\300a\200\001\340\004\037\230q\320 0\260\013\270;\300k\320QR\330\004\023\220>\240\030\250\021\250!\330\004\007\200|\2207\230!\330\0100\260\001\3201B\300.\320PQ\330\004\013\2101\200\001\340\004\037\230q\320 0\260\013\270;\300k\320QR\330\004\023\320\023+\2508\2601\260A\330\004\007\200|\2207\230!\330\010:\270!\320;V\320Vd\320de\330\004\013\2101\200\001\340\004\037\230q\320 0\260\013\270;\300k\320QR\330\004\023\320\023'\240x\250q\260\001\330\004\007\200|\2207\230!\330\0106\260a\3207N\310n\320\\]\330\004\013\2101"; + #else /* compression: none (4102 bytes) */ +const char* const bytes = "?Note that Cython is deliberately stricter than PEP-484 and rejects subclasses of builtin types. If you need to pass subclasses then set the 'annotation_typing' directive to False.Unexpected EOF while reading bytesadd_noteclickhouse_driver/bufferedreader.pyxdisableenablegcisenabledself.buffer is not Noneself.buffer is not None or self.sock is not Noneself.buffer is not None or self.read_block is not Noneutf-8BufferedReaderBufferedReader.__reduce_cython__BufferedReader.__setstate_cython__BufferedReader.readBufferedReader.read_fixed_strings_as_bytesBufferedReader.read_fixed_stringsBufferedReader.read_into_bufferBufferedReader.read_oneBufferedReader.read_stringsBufferedReader.read_strings_arrowBufferedSocketReaderBufferedSocketReader.__reduce_cython__BufferedSocketReader.__setstate_cython__BufferedSocketReader.read_into_bufferCompressedBufferedReaderCompressedBufferedReader.__reduce_cython__CompressedBufferedReader.__setstate_cython__CompressedBufferedReader.read_into_buffer__Pyx_PyDict_NextRefasyncio.coroutinesbbuffer_ptrbufsizebytes_readc_encodingc_stringc_string_sizeclickhouse_driver.bufferedreadercline_in_tracebackdatadata_capacitydata_ptrdata_size__dict___dictencodeencoding__func____getstate__i__init___is_coroutineitemitemsjlength__main____module__n_items__name____new__next_positionobjectoffsetsoffsets_ptrpop__pyx_checksum__pyx_result__pyx_state__pyx_type__pyx_unpickle_BufferedReader__pyx_unpickle_BufferedSocketReader__pyx_unpickle_CompressedBufferedReader__qualname__readread_blockread_bytesread_fixed_stringsread_fixed_strings_as_bytesread_into_bufferread_oneread_stringsread_strings_arrowrecv_into__reduce____reduce_cython____reduce_ex__rightrvself__set_name__setdefault__setstate____setstate_cython__shiftsizesockstatesupert__test__unreadupdateuse_setstatevalues\320\004@\300\001\360\n\000\t\021\220\013\2301\230A\360\010\000\t!\320 4\260A\260T\270\021\360\016\000\t\037\230a\330\0100\260\001\330\010 \240\001\330\010\013\2101\330\014\027\220x\230w\240a""\240q\330\014\031\230\021\340\010\031\230\026\230q\340\010\013\2101\330\014\027\220y\240\r\250Q\250f\260A\340\010\014\210E\220\025\220a\220q\330\014\024\220G\2301\360\006\000\r\016\330\020\023\2204\220z\240\023\240D\250\001\330\024\030\320\030)\250\021\340\024!\320!5\260Q\260d\270!\330\024\030\230\014\240A\340\020\024\220J\230a\230t\2401\330\020\024\220M\240\021\340\020\031\230\022\2302\230V\2403\240a\330\020\023\2202\220R\220q\330\024\025\340\020\031\230\021\340\014\024\220D\230\n\240\"\240A\340\014\017\210q\330\020\023\2205\230\002\230\"\230B\230a\330\024$\240E\250\022\2501\330\024\037\230y\250\r\260Q\260j\300\001\330\024\027\220y\240\003\2401\330\030\031\330\020\030\230\001\230\030\240\021\330\020\035\230Q\360\n\000\r\020\210v\220R\220t\2301\330\020\023\2201\330\024\032\230!\2301\230H\240A\240]\260!\260:\270Q\270d\300!\330\033\037\320\0374\260B\260d\270!\340\024\031\320\0312\260!\330\030\031\230\032\2401\240D\250\001\330\030\034\320\0341\260\022\2604\260q\360\006\000\021\036\230T\320!6\260b\270\004\270A\340\020\026\220k\240\023\240A\330\024\030\230\014\240E\250\022\2501\340\024\030\320\030)\250\021\340\024!\320!5\260Q\260d\270!\340\024\030\230\017\240q\330\030\034\230K\240t\2501\340\024\027\220q\330\030\036\230a\330\034\035\230X\240Q\240m\260<\270t\3001\360\006\000\031\037\320\0367\260q\330\034(\250\004\250A\340\024\"\240$\240a\360\006\000\021\024\2201\330\024\032\230!\230:\240Q\240j\260\001\260\024\260\\\300\021\340\024\031\320\0312\260!\330\030\031\230\032\2401\240D\250\014\260A\340\020\024\220L\240\001\340\014\017\210q\330\020\021\330\024\031\230\030\240\022\2405\250\007\250q\260\001\330\027\030\330\024\031\320\0312\260!\260:\270Q\340\014\025\220Q\220a\330\014\034\230A\230W\240C\240q\340\010\013\2101\330\014\026\220a\220q\340\010\017\210q\200\001\330\0042\260!\2606\270\021\200\001\330\0046\260a\260v\270Q\200\001\330\004,\250A\250V\2601\200A\360\006\000\t1\260\007\260r\270\024\270Q\330\010\013\210>\230\022\2304\230q\330\014\020\220\004\220A\330\014\020\220\014""\230A\330\014\023\2205\230\001\230\024\230W\240A\240R\240t\2501\340\010 \320 4\260A\260T\270\021\340\010\r\210U\220!\340\010\016\210g\220R\220q\330\014\017\210t\220:\230S\240\004\240A\330\020\024\320\024%\240Q\330\020\035\320\0351\260\021\260$\260a\330\020\024\220L\240\001\340\014\034\230A\230X\240T\320)>\270b\300\004\300A\330\014\022\320\022+\2501\330\020\021\220\032\2301\230D\240\014\250A\340\014\020\220\r\230Q\330\014\026\220a\340\010\017\210q\200A\360\026\000\t!\320 4\260A\260T\270\021\360\014\000\t\023\220)\2302\230X\240R\240s\250\"\250A\330\010&\240m\3203G\300q\330\014\r\340\010\023\2201\220E\230\021\340\010,\250A\330\0100\260\001\330\014\024\220B\220b\230\002\230+\240X\250R\250q\330\010\017\210y\230\001\230\021\330\010\036\320\0362\260!\2601\340\010\014\210E\220\025\220a\220q\330\014\024\220G\2301\360\006\000\r\016\330\020\023\2204\220z\240\023\240D\250\001\330\024\030\320\030)\250\021\340\024!\320!5\260Q\260d\270!\330\024\030\230\014\240A\340\020\024\220J\230a\230t\2401\330\020\024\220M\240\021\340\020\031\230\022\2302\230V\2403\240a\330\020\023\2202\220R\220q\330\024\025\340\020\031\230\021\340\014\017\210z\230\022\2305\240\002\240!\330\020\026\220n\240B\240j\260\002\260!\330\024%\240Q\330\020\"\240!\2406\250\021\330\020\033\320\033/\250q\260\001\340\014\024\220D\230\n\240\"\240A\340\014\017\210v\220R\220t\2301\340\020\035\230T\320!6\260b\270\004\270A\330\020\026\220a\220q\230\010\240\001\240\034\250Q\250j\270\001\270\024\270Q\330\027\030\340\020\026\220k\240\023\240A\330\024\030\230\014\240E\250\022\2501\340\024\030\320\030)\250\021\340\024!\320!5\260Q\260d\270!\340\024\030\230\017\240q\330\030\034\230K\240t\2501\340\024\032\230!\2301\230H\240A\240Z\250r\260\035\270a\330\033\037\230q\330\024\"\240$\240a\360\006\000\021\027\220a\220q\230\010\240\001\240\034\250Q\250j\270\001\270\024\270Q\330\027\030\330\020\024\220L\240\001\340\014\031\230\021\330\014\027\220q\230\002\230\"\230E\240\034\250Q\340\010\032\230!\2306\240\021\330\010\017\210y\230\001\200A\330""\010\014\320\014#\2404\240u\250J\260a\260t\2701\340\010\013\2104\320\017$\240C\240q\330\014\022\220(\230!\2301\200A\330\010\013\2104\210z\230\023\230D\240\001\330\014\020\320\020!\240\021\330\014\020\220\014\230A\340\010\r\210T\220\027\230\001\230\024\230Q\330\010\014\210M\230\021\330\010\017\210q\200A\330$%\330\010\013\2109\220C\220q\330\014\023\2204\320\0273\2601\260I\270Q\360\006\000\t\024\2208\2307\240!\2401\330\010 \240\001\330\010\017\210t\2205\230\001\230\027\240\002\240!\330\010\036\320\036.\250a\250q\340\010\036\230h\240l\260!\2607\270\"\270A\330\010\013\2104\210q\330\014\r\330\010\020\220\001\220\032\2301\340\010\020\220\013\2301\230A\330\010\014\210E\220\025\220a\220q\330\014\022\220!\220:\230Q\230h\240a\240r\250\022\2509\260A\360\006\000\r\021\220\007\220r\230\021\330\014\022\220\"\220C\220r\230\024\230T\240\030\250\021\250!\330\020\025\220Q\340\014\r\330\020\027\220x\230r\240\022\2402\240R\240w\250a\250q\330\023\024\330\020\027\320\0270\260\001\260\032\2701\330\014\025\220Q\220a\330\014\034\230A\230W\240C\240q\340\010\022\220!\2201\340\010\017\210q\200A\330\010\014\210J\220i\230q\240\004\240K\250q\330\010\014\320\014#\2403\240a\240t\2501\340\010\013\2104\320\017$\240C\240q\330\014\022\220(\230!\2301\200A\330\010\016\210a\200A\360\006\000\t\020\210t\2205\230\001\230\027\240\002\240!\330\010\036\320\036.\250a\250q\340\010\020\220\013\2301\230A\330\010\014\210E\220\025\220a\220q\330\014\023\320\023,\250A\250Q\250h\260a\260r\270\022\2709\300A\330\014\025\220Q\220a\330\014\034\230A\230W\240C\240q\330\010\017\210q\200\001\360\010\000\005\016\210T\220\031\230$\320\0364\260D\270\013\3004\300q\330\004\014\210G\2201\220F\230,\240a\330\004\007\200v\210W\220E\230\024\230Q\330\010\022\220!\330\010\027\220q\340\010\030\230\001\330\004\007\200q\330\010\017\320\0175\260T\270\021\270'\300\033\310G\320ST\340\010\017\320\0175\260T\270\021\270'\300\033\310A\200\001\360\010\000\005\016\210T\220\031\230$\320\0364\260D\270\013\3004\300q\330\004\014\210G\2201\220F\230,\240a""\330\004\007\200v\210W\220E\230\024\230Q\330\010\022\220!\330\010\027\220q\340\010\030\230\001\330\004\007\200q\330\010\017\320\0179\270\024\270Q\270g\300[\320PW\320WX\340\010\017\320\0179\270\024\270Q\270g\300[\320PQ\200\001\360\010\000\005\016\210T\220\031\230$\320\0364\260D\270\001\330\004\014\210G\2201\220F\230,\240a\330\004\007\200v\210W\220E\230\024\230Q\330\010\022\220!\330\010\027\220q\340\010\030\230\001\330\004\007\200q\330\010\017\320\017/\250t\2601\260G\270;\300g\310Q\340\010\017\320\017/\250t\2601\260G\270;\300a\200\001\340\004\037\230q\320 0\260\013\270;\300k\320QR\330\004\023\220>\240\030\250\021\250!\330\004\007\200|\2207\230!\330\0100\260\001\3201B\300.\320PQ\330\004\013\2101\200\001\340\004\037\230q\320 0\260\013\270;\300k\320QR\330\004\023\320\023+\2508\2601\260A\330\004\007\200|\2207\230!\330\010:\270!\320;V\320Vd\320de\330\004\013\2101\200\001\340\004\037\230q\320 0\260\013\270;\300k\320QR\330\004\023\320\023'\240x\250q\260\001\330\004\007\200|\2207\230!\330\0106\260a\3207N\310n\320\\]\330\004\013\2101"; PyObject *data = NULL; CYTHON_UNUSED_VAR(__Pyx_DecompressString); #endif PyObject **stringtab = __pyx_mstate->__pyx_string_tab; Py_ssize_t pos = 0; - for (int i = 0; i < 103; i++) { + for (int i = 0; i < 109; i++) { Py_ssize_t bytes_length = index[i].length; PyObject *string = PyUnicode_DecodeUTF8(bytes + pos, bytes_length, NULL); if (likely(string) && i >= 14) PyUnicode_InternInPlace(&string); @@ -10373,7 +11100,7 @@ const char* const bytes = "?Note that Cython is deliberately stricter than PEP-4 stringtab[i] = string; pos += bytes_length; } - for (int i = 103; i < 120; i++) { + for (int i = 109; i < 127; i++) { Py_ssize_t bytes_length = index[i].length; PyObject *string = PyBytes_FromStringAndSize(bytes + pos, bytes_length); stringtab[i] = string; @@ -10384,15 +11111,15 @@ const char* const bytes = "?Note that Cython is deliberately stricter than PEP-4 } } Py_XDECREF(data); - for (Py_ssize_t i = 0; i < 120; i++) { + for (Py_ssize_t i = 0; i < 127; i++) { if (unlikely(PyObject_Hash(stringtab[i]) == -1)) { __PYX_ERR(0, 1, __pyx_L1_error) } } #if CYTHON_IMMORTAL_CONSTANTS { - PyObject **table = stringtab + 103; - for (Py_ssize_t i=0; i<17; ++i) { + PyObject **table = stringtab + 109; + for (Py_ssize_t i=0; i<18; ++i) { #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING Py_SET_REFCNT(table[i], _Py_IMMORTAL_REFCNT_LOCAL); #else @@ -10433,7 +11160,7 @@ typedef struct { unsigned int num_kwonly_args : 1; unsigned int nlocals : 4; unsigned int flags : 10; - unsigned int first_line : 8; + unsigned int first_line : 9; } __Pyx_PyCode_New_function_description; /* NewCodeObj.proto */ static PyObject* __Pyx_PyCode_New( @@ -10470,69 +11197,74 @@ static int __Pyx_CreateCodeObjects(__pyx_mstatetype *__pyx_mstate) { __pyx_mstate_global->__pyx_codeobj_tab[3] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_clickhouse_driver_bufferedreader_2, __pyx_mstate->__pyx_n_u_read_strings, __pyx_mstate->__pyx_kp_b_iso88591_1A_4AT_a_0_1_xwaq_q_1_y_QfA_E_a, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[3])) goto bad; } { - const __Pyx_PyCode_New_function_description descr = {3, 0, 0, 8, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 179}; + const __Pyx_PyCode_New_function_description descr = {2, 0, 0, 15, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 179}; + PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_self, __pyx_mstate->__pyx_n_u_n_items, __pyx_mstate->__pyx_n_u_i, __pyx_mstate->__pyx_n_u_buffer_ptr, __pyx_mstate->__pyx_n_u_right, __pyx_mstate->__pyx_n_u_size, __pyx_mstate->__pyx_n_u_shift, __pyx_mstate->__pyx_n_u_bytes_read, __pyx_mstate->__pyx_n_u_b, __pyx_mstate->__pyx_n_u_offsets, __pyx_mstate->__pyx_n_u_offsets_ptr, __pyx_mstate->__pyx_n_u_data_size, __pyx_mstate->__pyx_n_u_data_capacity, __pyx_mstate->__pyx_n_u_data, __pyx_mstate->__pyx_n_u_data_ptr}; + __pyx_mstate_global->__pyx_codeobj_tab[4] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_clickhouse_driver_bufferedreader_2, __pyx_mstate->__pyx_n_u_read_strings_arrow, __pyx_mstate->__pyx_kp_b_iso88591_A_4AT_2XRs_A_m3Gq_1E_A_0_Bb_XRq, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[4])) goto bad; + } + { + const __Pyx_PyCode_New_function_description descr = {3, 0, 0, 8, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 267}; PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_self, __pyx_mstate->__pyx_n_u_n_items, __pyx_mstate->__pyx_n_u_length, __pyx_mstate->__pyx_n_u_i, __pyx_mstate->__pyx_n_u_data, __pyx_mstate->__pyx_n_u_data_ptr, __pyx_mstate->__pyx_n_u_items, __pyx_mstate->__pyx_n_u_item}; - __pyx_mstate_global->__pyx_codeobj_tab[4] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_clickhouse_driver_bufferedreader_2, __pyx_mstate->__pyx_n_u_read_fixed_strings_as_bytes, __pyx_mstate->__pyx_kp_b_iso88591_A_t5_aq_1A_E_aq_AQhar_9A_Qa_AWCq, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[4])) goto bad; + __pyx_mstate_global->__pyx_codeobj_tab[5] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_clickhouse_driver_bufferedreader_2, __pyx_mstate->__pyx_n_u_read_fixed_strings_as_bytes, __pyx_mstate->__pyx_kp_b_iso88591_A_t5_aq_1A_E_aq_AQhar_9A_Qa_AWCq, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[5])) goto bad; } { - const __Pyx_PyCode_New_function_description descr = {4, 0, 0, 12, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 192}; + const __Pyx_PyCode_New_function_description descr = {4, 0, 0, 12, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 280}; PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_self, __pyx_mstate->__pyx_n_u_n_items, __pyx_mstate->__pyx_n_u_length, __pyx_mstate->__pyx_n_u_encoding, __pyx_mstate->__pyx_n_u_i, __pyx_mstate->__pyx_n_u_j, __pyx_mstate->__pyx_n_u_c_encoding, __pyx_mstate->__pyx_n_u_data, __pyx_mstate->__pyx_n_u_data_ptr, __pyx_mstate->__pyx_n_u_c_string, __pyx_mstate->__pyx_n_u_items, __pyx_mstate->__pyx_n_u_item}; - __pyx_mstate_global->__pyx_codeobj_tab[5] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_clickhouse_driver_bufferedreader_2, __pyx_mstate->__pyx_n_u_read_fixed_strings, __pyx_mstate->__pyx_kp_b_iso88591_A_9Cq_4_31IQ_87_1_t5_aq_hl_7_A_4, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[5])) goto bad; + __pyx_mstate_global->__pyx_codeobj_tab[6] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_clickhouse_driver_bufferedreader_2, __pyx_mstate->__pyx_n_u_read_fixed_strings, __pyx_mstate->__pyx_kp_b_iso88591_A_9Cq_4_31IQ_87_1_t5_aq_hl_7_A_4, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[6])) goto bad; } { const __Pyx_PyCode_New_function_description descr = {1, 0, 0, 4, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 1}; PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_self, __pyx_mstate->__pyx_n_u_state, __pyx_mstate->__pyx_n_u_dict_2, __pyx_mstate->__pyx_n_u_use_setstate}; - __pyx_mstate_global->__pyx_codeobj_tab[6] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_stringsource, __pyx_mstate->__pyx_n_u_reduce_cython, __pyx_mstate->__pyx_kp_b_iso88591_T_4D_G1F_a_vWE_Q_q_q_t1G_gQ_t1G, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[6])) goto bad; + __pyx_mstate_global->__pyx_codeobj_tab[7] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_stringsource, __pyx_mstate->__pyx_n_u_reduce_cython, __pyx_mstate->__pyx_kp_b_iso88591_T_4D_G1F_a_vWE_Q_q_q_t1G_gQ_t1G, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[7])) goto bad; } { const __Pyx_PyCode_New_function_description descr = {2, 0, 0, 2, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 16}; PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_self, __pyx_mstate->__pyx_n_u_pyx_state}; - __pyx_mstate_global->__pyx_codeobj_tab[7] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_stringsource, __pyx_mstate->__pyx_n_u_setstate_cython, __pyx_mstate->__pyx_kp_b_iso88591_AV1, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[7])) goto bad; + __pyx_mstate_global->__pyx_codeobj_tab[8] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_stringsource, __pyx_mstate->__pyx_n_u_setstate_cython, __pyx_mstate->__pyx_kp_b_iso88591_AV1, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[8])) goto bad; } { - const __Pyx_PyCode_New_function_description descr = {1, 0, 0, 1, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 236}; + const __Pyx_PyCode_New_function_description descr = {1, 0, 0, 1, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 324}; PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_self}; - __pyx_mstate_global->__pyx_codeobj_tab[8] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_clickhouse_driver_bufferedreader_2, __pyx_mstate->__pyx_n_u_read_into_buffer, __pyx_mstate->__pyx_kp_b_iso88591_A_4uJat1_4_Cq_1, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[8])) goto bad; + __pyx_mstate_global->__pyx_codeobj_tab[9] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_clickhouse_driver_bufferedreader_2, __pyx_mstate->__pyx_n_u_read_into_buffer, __pyx_mstate->__pyx_kp_b_iso88591_A_4uJat1_4_Cq_1, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[9])) goto bad; } { const __Pyx_PyCode_New_function_description descr = {1, 0, 0, 4, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 1}; PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_self, __pyx_mstate->__pyx_n_u_state, __pyx_mstate->__pyx_n_u_dict_2, __pyx_mstate->__pyx_n_u_use_setstate}; - __pyx_mstate_global->__pyx_codeobj_tab[9] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_stringsource, __pyx_mstate->__pyx_n_u_reduce_cython, __pyx_mstate->__pyx_kp_b_iso88591_T_4D_4q_G1F_a_vWE_Q_q_q_5T_GST, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[9])) goto bad; + __pyx_mstate_global->__pyx_codeobj_tab[10] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_stringsource, __pyx_mstate->__pyx_n_u_reduce_cython, __pyx_mstate->__pyx_kp_b_iso88591_T_4D_4q_G1F_a_vWE_Q_q_q_5T_GST, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[10])) goto bad; } { const __Pyx_PyCode_New_function_description descr = {2, 0, 0, 2, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 16}; PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_self, __pyx_mstate->__pyx_n_u_pyx_state}; - __pyx_mstate_global->__pyx_codeobj_tab[10] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_stringsource, __pyx_mstate->__pyx_n_u_setstate_cython, __pyx_mstate->__pyx_kp_b_iso88591_2_6, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[10])) goto bad; + __pyx_mstate_global->__pyx_codeobj_tab[11] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_stringsource, __pyx_mstate->__pyx_n_u_setstate_cython, __pyx_mstate->__pyx_kp_b_iso88591_2_6, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[11])) goto bad; } { - const __Pyx_PyCode_New_function_description descr = {1, 0, 0, 1, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 250}; + const __Pyx_PyCode_New_function_description descr = {1, 0, 0, 1, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 338}; PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_self}; - __pyx_mstate_global->__pyx_codeobj_tab[11] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_clickhouse_driver_bufferedreader_2, __pyx_mstate->__pyx_n_u_read_into_buffer, __pyx_mstate->__pyx_kp_b_iso88591_A_Jiq_Kq_3at1_4_Cq_1, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[11])) goto bad; + __pyx_mstate_global->__pyx_codeobj_tab[12] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_clickhouse_driver_bufferedreader_2, __pyx_mstate->__pyx_n_u_read_into_buffer, __pyx_mstate->__pyx_kp_b_iso88591_A_Jiq_Kq_3at1_4_Cq_1, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[12])) goto bad; } { const __Pyx_PyCode_New_function_description descr = {1, 0, 0, 4, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 1}; PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_self, __pyx_mstate->__pyx_n_u_state, __pyx_mstate->__pyx_n_u_dict_2, __pyx_mstate->__pyx_n_u_use_setstate}; - __pyx_mstate_global->__pyx_codeobj_tab[12] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_stringsource, __pyx_mstate->__pyx_n_u_reduce_cython, __pyx_mstate->__pyx_kp_b_iso88591_T_4D_4q_G1F_a_vWE_Q_q_q_9_Qg_PW, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[12])) goto bad; + __pyx_mstate_global->__pyx_codeobj_tab[13] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_stringsource, __pyx_mstate->__pyx_n_u_reduce_cython, __pyx_mstate->__pyx_kp_b_iso88591_T_4D_4q_G1F_a_vWE_Q_q_q_9_Qg_PW, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[13])) goto bad; } { const __Pyx_PyCode_New_function_description descr = {2, 0, 0, 2, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 16}; PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_self, __pyx_mstate->__pyx_n_u_pyx_state}; - __pyx_mstate_global->__pyx_codeobj_tab[13] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_stringsource, __pyx_mstate->__pyx_n_u_setstate_cython, __pyx_mstate->__pyx_kp_b_iso88591_6avQ, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[13])) goto bad; + __pyx_mstate_global->__pyx_codeobj_tab[14] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_stringsource, __pyx_mstate->__pyx_n_u_setstate_cython, __pyx_mstate->__pyx_kp_b_iso88591_6avQ, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[14])) goto bad; } { const __Pyx_PyCode_New_function_description descr = {3, 0, 0, 4, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 4}; PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_pyx_type, __pyx_mstate->__pyx_n_u_pyx_checksum, __pyx_mstate->__pyx_n_u_pyx_state, __pyx_mstate->__pyx_n_u_pyx_result}; - __pyx_mstate_global->__pyx_codeobj_tab[14] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_stringsource, __pyx_mstate->__pyx_n_u_pyx_unpickle_BufferedReader, __pyx_mstate->__pyx_kp_b_iso88591_q_0_kQR_7_0_1B_PQ_1, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[14])) goto bad; + __pyx_mstate_global->__pyx_codeobj_tab[15] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_stringsource, __pyx_mstate->__pyx_n_u_pyx_unpickle_BufferedReader, __pyx_mstate->__pyx_kp_b_iso88591_q_0_kQR_7_0_1B_PQ_1, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[15])) goto bad; } { const __Pyx_PyCode_New_function_description descr = {3, 0, 0, 4, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 4}; PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_pyx_type, __pyx_mstate->__pyx_n_u_pyx_checksum, __pyx_mstate->__pyx_n_u_pyx_state, __pyx_mstate->__pyx_n_u_pyx_result}; - __pyx_mstate_global->__pyx_codeobj_tab[15] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_stringsource, __pyx_mstate->__pyx_n_u_pyx_unpickle_BufferedSocketRea, __pyx_mstate->__pyx_kp_b_iso88591_q_0_kQR_xq_7_6a7Nn_1, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[15])) goto bad; + __pyx_mstate_global->__pyx_codeobj_tab[16] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_stringsource, __pyx_mstate->__pyx_n_u_pyx_unpickle_BufferedSocketRea, __pyx_mstate->__pyx_kp_b_iso88591_q_0_kQR_xq_7_6a7Nn_1, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[16])) goto bad; } { const __Pyx_PyCode_New_function_description descr = {3, 0, 0, 4, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 4}; PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_pyx_type, __pyx_mstate->__pyx_n_u_pyx_checksum, __pyx_mstate->__pyx_n_u_pyx_state, __pyx_mstate->__pyx_n_u_pyx_result}; - __pyx_mstate_global->__pyx_codeobj_tab[16] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_stringsource, __pyx_mstate->__pyx_n_u_pyx_unpickle_CompressedBuffere, __pyx_mstate->__pyx_kp_b_iso88591_q_0_kQR_81A_7_VVdde_1, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[16])) goto bad; + __pyx_mstate_global->__pyx_codeobj_tab[17] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_stringsource, __pyx_mstate->__pyx_n_u_pyx_unpickle_CompressedBuffere, __pyx_mstate->__pyx_kp_b_iso88591_q_0_kQR_81A_7_VVdde_1, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[17])) goto bad; } Py_DECREF(tuple_dedup_map); return 0; diff --git a/clickhouse_driver/bufferedreader.pyx b/clickhouse_driver/bufferedreader.pyx index c02c6984..8253f58c 100644 --- a/clickhouse_driver/bufferedreader.pyx +++ b/clickhouse_driver/bufferedreader.pyx @@ -1,5 +1,5 @@ from cpython cimport Py_INCREF, PyBytes_FromStringAndSize, PyBytes_AsString -from cpython.bytearray cimport PyByteArray_AsString +from cpython.bytearray cimport PyByteArray_AsString, PyByteArray_Resize # Using python's versions of pure c memory management functions for # proper memory statistics count. from cpython.mem cimport PyMem_Malloc, PyMem_Realloc, PyMem_Free @@ -176,6 +176,94 @@ cdef class BufferedReader(object): return items + def read_strings_arrow(self, unsigned long long n_items): + """ + Reads ``n_items`` varint-prefixed strings into Arrow-style + buffers without creating per-string Python objects. + + Returns (offsets, data) pair of bytearrays: ``offsets`` holds + ``n_items + 1`` little-endian int64 values, ``data`` holds + concatenated string bytes. + """ + cdef unsigned long long i + # Buffer vars + cdef char* buffer_ptr = PyByteArray_AsString(self.buffer) + cdef unsigned long long right + # String length vars + cdef unsigned long long size, shift, bytes_read + cdef unsigned long long b + + offsets = bytearray((n_items + 1) * 8) + cdef long long* offsets_ptr = PyByteArray_AsString( + offsets + ) + offsets_ptr[0] = 0 + + cdef unsigned long long data_size = 0 + cdef unsigned long long data_capacity = 65536 if \ + n_items * 8 < 65536 else n_items * 8 + data = bytearray(data_capacity) + cdef char* data_ptr = PyByteArray_AsString(data) + + for i in range(n_items): + shift = size = 0 + + # Read string size + while True: + if self.position == self.current_buffer_size: + self.read_into_buffer() + # `read_into_buffer` can override buffer + buffer_ptr = PyByteArray_AsString(self.buffer) + self.position = 0 + + b = buffer_ptr[self.position] + self.position += 1 + + size |= (b & 0x7f) << shift + if b < 0x80: + break + + shift += 7 + + if data_size + size > data_capacity: + while data_capacity < data_size + size: + data_capacity *= 2 + PyByteArray_Resize(data, data_capacity) + data_ptr = PyByteArray_AsString(data) + + right = self.position + size + + if right > self.current_buffer_size: + # String spans multiple reader buffers. + bytes_read = self.current_buffer_size - self.position + memcpy(&data_ptr[data_size], &buffer_ptr[self.position], + bytes_read) + + while bytes_read != size: + self.position = size - bytes_read + + self.read_into_buffer() + # `read_into_buffer` can override buffer + buffer_ptr = PyByteArray_AsString(self.buffer) + # There can be not enough data in buffer. + self.position = min( + self.position, self.current_buffer_size + ) + memcpy(&data_ptr[data_size + bytes_read], buffer_ptr, + self.position) + bytes_read += self.position + + else: + memcpy(&data_ptr[data_size], &buffer_ptr[self.position], + size) + self.position = right + + data_size += size + offsets_ptr[i + 1] = data_size + + PyByteArray_Resize(data, data_size) + return offsets, data + def read_fixed_strings_as_bytes(self, Py_ssize_t n_items, Py_ssize_t length): cdef Py_ssize_t i diff --git a/clickhouse_driver/client.py b/clickhouse_driver/client.py index 0e573384..1d1466ae 100644 --- a/clickhouse_driver/client.py +++ b/clickhouse_driver/client.py @@ -136,6 +136,7 @@ def __init__(self, *args, **kwargs): round_robin = kwargs.pop('round_robin', False) self.connections = deque([Connection(*args, **kwargs)]) + self._pending_arrow_stream = None if round_robin and 'alt_hosts' in kwargs: alt_hosts = kwargs.pop('alt_hosts') @@ -307,9 +308,47 @@ def establish_connection(self, settings): return + def _reset_pending_arrow_stream(self): + """ + Cancels the previous streamed Arrow query if it wasn't consumed + to the end. RecordBatchReader.close() doesn't reach the + underlying generator, so cleanup happens on the next query: + drain the stream through END_OF_STREAM after Cancel, or reset + the connection. + """ + state = self._pending_arrow_stream + self._pending_arrow_stream = None + + if state is None or state.finished: + return + + state.cancelled = True + connection = state.connection + + if not connection.connected or not connection.is_query_executing: + return + + try: + connection.send_cancel() + terminal_packets = ( + ServerPacketTypes.END_OF_STREAM, ServerPacketTypes.EXCEPTION + ) + while True: + packet = connection.receive_packet() + if packet.type in terminal_packets: + break + + # Exception packet leaves the query marked as executing. + if connection.is_query_executing: + connection.disconnect() + + except (Exception, KeyboardInterrupt): + connection.disconnect() + @contextmanager def disconnect_on_error(self, query, settings): try: + self._reset_pending_arrow_stream() self.establish_connection(settings) self.connection.server_info.session_timezone = None @@ -549,6 +588,109 @@ def insert_dataframe( self.last_query.store_elapsed(time() - start_time) return rv + def query_arrow( + self, query, params=None, external_tables=None, query_id=None, + settings=None, field_metadata=True, arrow_types=None): + """ + *New in version 0.2.11.* + + Queries data as PyArrow Table with specified SELECT query. + + :param query: query that will be send to server. + :param params: substitution parameters. + Defaults to ``None`` (no parameters or data). + :param external_tables: external tables to send. + Defaults to ``None`` (no external tables). + :param query_id: the query identifier. If no query id specified + ClickHouse server will generate it. + :param settings: dictionary of query settings. + Defaults to ``None`` (no additional settings). + :param field_metadata: attach original ClickHouse column types + to Arrow fields as ``clickhouse_type`` + metadata. Defaults to ``True``. + :param arrow_types: dictionary mapping column names to Arrow + types, overriding the default mapping. + Required for columns without a default + Arrow representation (``JSON``). + Defaults to ``None``. + :return: pyarrow.Table. + """ + + return self.query_arrow_stream( + query, params=params, external_tables=external_tables, + query_id=query_id, settings=settings, + field_metadata=field_metadata, arrow_types=arrow_types + ).read_all() + + def query_arrow_stream( + self, query, params=None, external_tables=None, query_id=None, + settings=None, field_metadata=True, arrow_types=None): + """ + *New in version 0.2.11.* + + Queries data as PyArrow RecordBatchReader with specified SELECT + query. One record batch is yielded per ClickHouse block, so + arbitrarily large results can be processed with constant memory + usage. Block size can be controlled with ``max_block_size`` + setting. + + The reader doesn't have to be consumed to the end: the streamed + query is cancelled when the next query on this client starts. + + :param query: query that will be send to server. + :param params: substitution parameters. + Defaults to ``None`` (no parameters or data). + :param external_tables: external tables to send. + Defaults to ``None`` (no external tables). + :param query_id: the query identifier. If no query id specified + ClickHouse server will generate it. + :param settings: dictionary of query settings. + Defaults to ``None`` (no additional settings). + :param field_metadata: attach original ClickHouse column types + to Arrow fields as ``clickhouse_type`` + metadata. Defaults to ``True``. + :param arrow_types: dictionary mapping column names to Arrow + types, overriding the default mapping. + Required for columns without a default + Arrow representation (``JSON``). + Defaults to ``None``. + :return: pyarrow.RecordBatchReader. + """ + + try: + import pyarrow # noqa: F401 + except ImportError: + raise RuntimeError('Extras for PyArrow must be installed') + + from .arrow.convert import ArrowStreamState, \ + create_record_batch_reader + + with self.disconnect_on_error(query, settings): + # Let columns return Arrow-friendly forms (e.g. NumPy masked + # arrays for Nullable). Reset by the next query's + # make_query_settings. Context returns a copy of settings: + # assignment is required for the flag to stick. + client_settings = self.connection.context.client_settings + client_settings['use_arrow'] = True + self.connection.context.client_settings = client_settings + + if params is not None: + query = self.substitute_params( + query, params, self.connection.context + ) + + self.connection.send_query(query, query_id=query_id, + params=params) + self.connection.send_external_tables(external_tables) + + state = ArrowStreamState(self.connection) + self._pending_arrow_stream = state + return create_record_batch_reader( + self.packet_generator(), self.connection.context, + state=state, field_metadata=field_metadata, + arrow_types=arrow_types + ) + def process_ordinary_query_with_progress( self, query, params=None, with_column_types=False, external_tables=None, query_id=None, @@ -713,12 +855,23 @@ def receive_end_of_insert_query(self): elif packet.type == ServerPacketTypes.PROGRESS: self.last_query.store_progress(packet.progress) + elif packet.type == ServerPacketTypes.PROFILE_EVENTS: # noqa: E501 pragma: requires-clickhouse-25.0 + # When ``receive_profile_events`` exited early (e.g. on + # a ``TimezoneUpdate``), the actual ``ProfileEvents`` + # packet can land in this loop instead. + self.last_query.store_profile(packet.profile_info) + + elif packet.type == ServerPacketTypes.TIMEZONE_UPDATE: # noqa: E501 pragma: requires-clickhouse-25.0 + pass + elif packet.type == ServerPacketTypes.EXCEPTION: raise packet.exception else: message = self.connection.unexpected_packet_message( - 'EndOfStream, Log, Progress or Exception', packet.type + 'EndOfStream, Log, Progress, ProfileEvents, ' + 'TimezoneUpdate or Exception', + packet.type ) raise errors.UnexpectedPacketFromServerError(message) @@ -746,8 +899,17 @@ def receive_profile_events(self): elif packet.type == ServerPacketTypes.EXCEPTION: raise packet.exception - elif packet.type == ServerPacketTypes.TIMEZONE_UPDATE: - pass + elif packet.type == ServerPacketTypes.TIMEZONE_UPDATE: # noqa: E501 pragma: requires-clickhouse-25.0 + # ClickHouse 25.x sends ``TimezoneUpdate`` in the slot + # where 24.x sent ``ProfileEvents`` between blocks of + # ``INSERT ... SELECT FROM input(...)``. The server then + # waits for the next data block, so looping for a + # ``ProfileEvents`` we are never going to get would + # deadlock. Treat the timezone packet as "no profile + # events for this block" and let the caller continue. + # The ``receive_packet`` machinery has already applied + # the new session timezone. + break else: message = self.connection.unexpected_packet_message( diff --git a/clickhouse_driver/columns/arraycolumn.py b/clickhouse_driver/columns/arraycolumn.py index 0ce336e7..931323c8 100644 --- a/clickhouse_driver/columns/arraycolumn.py +++ b/clickhouse_driver/columns/arraycolumn.py @@ -34,6 +34,7 @@ def __init__(self, nested_column, **kwargs): self._write_depth_0_size = True super(ArrayColumn, self).__init__(**kwargs) self.null_value = [] + self.prefix_needs_items = nested_column.prefix_needs_items def write_data(self, data, buf): # Column of Array(T) is stored in "compact" format and passed to server @@ -115,10 +116,17 @@ def read_state_prefix(self, buf): self.nested_column.read_state_prefix(buf) - def write_state_prefix(self, buf): + def write_state_prefix(self, buf, items=None): super(ArrayColumn, self).write_state_prefix(buf) - self.nested_column.write_state_prefix(buf) + nested_items = None + if items is not None and self.nested_column.prefix_needs_items: + # One level of flattening per Array level, so the leaf + # column sees the same flat item list its data writer will + # receive. + nested_items = [x for item in items if item is not None + for x in item] + self.nested_column.write_state_prefix(buf, nested_items) def _read(self, size, buf): slices_series = [[0, size]] diff --git a/clickhouse_driver/columns/arrow/__init__.py b/clickhouse_driver/columns/arrow/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/clickhouse_driver/columns/arrow/base.py b/clickhouse_driver/columns/arrow/base.py new file mode 100644 index 00000000..992d8727 --- /dev/null +++ b/clickhouse_driver/columns/arrow/base.py @@ -0,0 +1,24 @@ +import numpy as np + + +class ArrowColumnMixin(object): + """ + Read-path override for Arrow result queries + (``query_arrow``/``query_arrow_stream``). Values are kept in + wire-friendly form and assembled into pyarrow arrays by + ``clickhouse_driver.arrow.convert``. + """ + + def _read_data(self, n_items, buf, nulls_map=None): + items = self.read_items(n_items, buf) + + if self.after_read_items: + return self.after_read_items(items, nulls_map) + elif nulls_map is not None: + # Arrow stores nullable columns the same way the wire + # sends them: raw values plus a validity mask. No need to + # convert to an object ndarray with None like the NumPy + # family does. + return np.ma.MaskedArray(items, mask=nulls_map) + + return items diff --git a/clickhouse_driver/columns/arrow/boolcolumn.py b/clickhouse_driver/columns/arrow/boolcolumn.py new file mode 100644 index 00000000..47efd3bd --- /dev/null +++ b/clickhouse_driver/columns/arrow/boolcolumn.py @@ -0,0 +1,6 @@ +from ..numpy.boolcolumn import NumpyBoolColumn +from .base import ArrowColumnMixin + + +class ArrowBoolColumn(ArrowColumnMixin, NumpyBoolColumn): + pass diff --git a/clickhouse_driver/columns/arrow/datecolumn.py b/clickhouse_driver/columns/arrow/datecolumn.py new file mode 100644 index 00000000..0c87259c --- /dev/null +++ b/clickhouse_driver/columns/arrow/datecolumn.py @@ -0,0 +1,6 @@ +from ..numpy.datecolumn import NumpyDateColumn +from .base import ArrowColumnMixin + + +class ArrowDateColumn(ArrowColumnMixin, NumpyDateColumn): + pass diff --git a/clickhouse_driver/columns/arrow/datetimecolumn.py b/clickhouse_driver/columns/arrow/datetimecolumn.py new file mode 100644 index 00000000..3508baea --- /dev/null +++ b/clickhouse_driver/columns/arrow/datetimecolumn.py @@ -0,0 +1,19 @@ +from ..numpy.datetimecolumn import ( + NumpyDateTime64Column, NumpyDateTimeColumn, create_numpy_datetime_column +) +from .base import ArrowColumnMixin + + +class ArrowDateTimeColumn(ArrowColumnMixin, NumpyDateTimeColumn): + pass + + +class ArrowDateTime64Column(ArrowColumnMixin, NumpyDateTime64Column): + pass + + +def create_arrow_datetime_column(spec, column_options): + return create_numpy_datetime_column( + spec, column_options, + column_classes=(ArrowDateTimeColumn, ArrowDateTime64Column) + ) diff --git a/clickhouse_driver/columns/arrow/floatcolumn.py b/clickhouse_driver/columns/arrow/floatcolumn.py new file mode 100644 index 00000000..057d49d1 --- /dev/null +++ b/clickhouse_driver/columns/arrow/floatcolumn.py @@ -0,0 +1,10 @@ +from ..numpy.floatcolumn import NumpyFloat32Column, NumpyFloat64Column +from .base import ArrowColumnMixin + + +class ArrowFloat32Column(ArrowColumnMixin, NumpyFloat32Column): + pass + + +class ArrowFloat64Column(ArrowColumnMixin, NumpyFloat64Column): + pass diff --git a/clickhouse_driver/columns/arrow/intcolumn.py b/clickhouse_driver/columns/arrow/intcolumn.py new file mode 100644 index 00000000..d5b2087d --- /dev/null +++ b/clickhouse_driver/columns/arrow/intcolumn.py @@ -0,0 +1,37 @@ +from ..numpy.intcolumn import ( + NumpyInt8Column, NumpyInt16Column, NumpyInt32Column, NumpyInt64Column, + NumpyUInt8Column, NumpyUInt16Column, NumpyUInt32Column, NumpyUInt64Column +) +from .base import ArrowColumnMixin + + +class ArrowInt8Column(ArrowColumnMixin, NumpyInt8Column): + pass + + +class ArrowInt16Column(ArrowColumnMixin, NumpyInt16Column): + pass + + +class ArrowInt32Column(ArrowColumnMixin, NumpyInt32Column): + pass + + +class ArrowInt64Column(ArrowColumnMixin, NumpyInt64Column): + pass + + +class ArrowUInt8Column(ArrowColumnMixin, NumpyUInt8Column): + pass + + +class ArrowUInt16Column(ArrowColumnMixin, NumpyUInt16Column): + pass + + +class ArrowUInt32Column(ArrowColumnMixin, NumpyUInt32Column): + pass + + +class ArrowUInt64Column(ArrowColumnMixin, NumpyUInt64Column): + pass diff --git a/clickhouse_driver/columns/arrow/service.py b/clickhouse_driver/columns/arrow/service.py new file mode 100644 index 00000000..116c44de --- /dev/null +++ b/clickhouse_driver/columns/arrow/service.py @@ -0,0 +1,65 @@ +from ... import errors +from ..nullablecolumn import create_nullable_column +from ..numpy.lowcardinalitycolumn import create_numpy_low_cardinality_column +from ..numpy.tuplecolumn import create_tuple_column +from ..service import aliases +from .boolcolumn import ArrowBoolColumn +from .datecolumn import ArrowDateColumn +from .datetimecolumn import create_arrow_datetime_column +from .floatcolumn import ArrowFloat32Column, ArrowFloat64Column +from .intcolumn import ( + ArrowInt8Column, ArrowInt16Column, ArrowInt32Column, ArrowInt64Column, + ArrowUInt8Column, ArrowUInt16Column, ArrowUInt32Column, ArrowUInt64Column +) +from .stringcolumn import create_arrow_string_column + +# Fixed-width types differ from their NumPy counterparts only in +# nullable reads: ArrowColumnMixin keeps the values and the nulls map +# intact instead of converting to an object ndarray. +column_by_type = {c.ch_type: c for c in [ + ArrowDateColumn, + ArrowFloat32Column, ArrowFloat64Column, + ArrowInt8Column, ArrowInt16Column, ArrowInt32Column, ArrowInt64Column, + ArrowUInt8Column, ArrowUInt16Column, ArrowUInt32Column, ArrowUInt64Column, + ArrowBoolColumn +]} + + +def get_arrow_column_by_spec(spec, column_options): + def create_column_with_options(x): + return get_arrow_column_by_spec(x, column_options) + + if spec == 'String' or spec.startswith('FixedString'): + return create_arrow_string_column(spec, column_options) + + elif spec.startswith('DateTime'): + return create_arrow_datetime_column(spec, column_options) + + elif spec.startswith('Tuple'): + return create_tuple_column( + spec, create_column_with_options, column_options + ) + + elif spec.startswith('Nullable'): + return create_nullable_column(spec, create_column_with_options) + + elif spec.startswith('LowCardinality'): + column = create_numpy_low_cardinality_column( + spec, create_column_with_options, column_options + ) + # Dictionary values are consumed by pd.Categorical: real items + # are needed, not Arrow buffers. + column.nested_column.arrow_buffers_allowed = False + return column + else: + for alias, primitive in aliases: + if spec.startswith(alias): + return create_column_with_options( + primitive + spec[len(alias):] + ) + + if spec in column_by_type: + cls = column_by_type[spec] + return cls(**column_options) + + raise errors.UnknownTypeError('Unknown type {}'.format(spec)) diff --git a/clickhouse_driver/columns/arrow/stringcolumn.py b/clickhouse_driver/columns/arrow/stringcolumn.py new file mode 100644 index 00000000..9da492cb --- /dev/null +++ b/clickhouse_driver/columns/arrow/stringcolumn.py @@ -0,0 +1,116 @@ +import numpy as np + +from ..base import CommonSerialization +from ..numpy.stringcolumn import ( + NumpyByteFixedString, NumpyByteStringColumn, NumpyFixedString, + NumpyStringColumn +) +from .base import ArrowColumnMixin + + +class ArrowStringBuffers(object): + """ + String column read into Arrow-style buffers: concatenated bytes + plus int64 offsets, no per-string Python objects. Assembled into + a pyarrow array by ``clickhouse_driver.arrow.convert``. + """ + __slots__ = ('offsets', 'data', 'nulls_map') + + def __init__(self, offsets, data, nulls_map=None): + self.offsets = offsets + self.data = data + self.nulls_map = nulls_map + + def __len__(self): + return len(self.offsets) // 8 - 1 + + +class ArrowStringMixin(ArrowColumnMixin): + # Reset for columns whose consumers need real items, e.g. + # LowCardinality dictionaries. + arrow_buffers_allowed = True + + def _buffers_encoding_ok(self): + return self.encoding.lower() in ('utf-8', 'utf8') + + def _use_arrow_buffers(self, buf): + return ( + self.arrow_buffers_allowed and + self._buffers_encoding_ok() and + type(self.serialization) is CommonSerialization and + hasattr(buf, 'read_strings_arrow') + ) + + def _read_data(self, n_items, buf, nulls_map=None): + if self._use_arrow_buffers(buf): + offsets, data = buf.read_strings_arrow(n_items) + return ArrowStringBuffers(offsets, data, nulls_map=nulls_map) + + return super(ArrowStringMixin, self)._read_data( + n_items, buf, nulls_map=nulls_map + ) + + def _wrap_items(self, items): + # Wrapping strings into an ndarray re-encodes them (unicode + # dtype). Arrow consumes the raw tuple directly; the ndarray + # is only needed for the nullable masked path. + if self.nullable: + return np.array(items, dtype=self.dtype) + return items + + +class ArrowStringColumn(ArrowStringMixin, NumpyStringColumn): + def read_items(self, n_items, buf): + return self._wrap_items( + buf.read_strings(n_items, encoding=self.encoding) + ) + + +class ArrowByteStringColumn(ArrowStringMixin, NumpyByteStringColumn): + def _buffers_encoding_ok(self): + # No decoding happens for byte strings: buffers can be used + # regardless of encoding. + return True + + def read_items(self, n_items, buf): + return self._wrap_items(buf.read_strings(n_items)) + + +class ArrowFixedString(ArrowStringMixin, NumpyFixedString): + def _use_arrow_buffers(self, buf): + # Fixed strings are trimmed of zero bytes on read: buffers + # would keep the padding. + return False + + def read_items(self, n_items, buf): + return self._wrap_items(buf.read_fixed_strings( + n_items, self.length, encoding=self.encoding + )) + + +class ArrowByteFixedString(ArrowStringMixin, NumpyByteFixedString): + def _use_arrow_buffers(self, buf): + return False + + def read_items(self, n_items, buf): + return self._wrap_items( + buf.read_fixed_strings(n_items, self.length) + ) + + +def create_arrow_string_column(spec, column_options): + client_settings = column_options['context'].client_settings + strings_as_bytes = client_settings['strings_as_bytes'] + encoding = client_settings.get( + 'strings_encoding', NumpyStringColumn.default_encoding + ) + + if spec == 'String': + cls = ArrowByteStringColumn if strings_as_bytes \ + else ArrowStringColumn + return cls(encoding=encoding, **column_options) + else: + length = int(spec[12:-1]) + cls = ArrowByteFixedString if strings_as_bytes \ + else ArrowFixedString + return cls(length, encoding=encoding, **column_options) diff --git a/clickhouse_driver/columns/base.py b/clickhouse_driver/columns/base.py index fba3fd2e..868a4dcb 100644 --- a/clickhouse_driver/columns/base.py +++ b/clickhouse_driver/columns/base.py @@ -70,6 +70,12 @@ class Column(object): null_value = 0 + # True when ``write_state_prefix`` needs the block's items to emit + # the prefix (JSON: the path list is data-dependent). Container + # columns propagate the flag and thread flattened items through so + # ordinary columns never pay for the flattening. + prefix_needs_items = False + def __init__(self, types_check=False, has_custom_serialization=False, **kwargs): self.nullable = False @@ -183,7 +189,7 @@ def read_state_prefix(self, buf): if use_custom_serialization: self.serialization = SparseSerialization(self) - def write_state_prefix(self, buf): + def write_state_prefix(self, buf, items=None): pass diff --git a/clickhouse_driver/columns/dynamiccolumn.py b/clickhouse_driver/columns/dynamiccolumn.py new file mode 100644 index 00000000..ce718d18 --- /dev/null +++ b/clickhouse_driver/columns/dynamiccolumn.py @@ -0,0 +1,563 @@ +""" +Reader for ClickHouse's Dynamic / Variant column families. + +These are not exposed as user-facing types in clickhouse-driver yet — they +exist here so the JSON column reader can compose them instead of +hand-rolling Variant deserialization. The byte layout mirrors +``SerializationDynamic`` and ``SerializationVariant`` in ClickHouse 25.5. +""" + +from .base import Column +from .stringcolumn import ByteString +from ..reader import ( + read_binary_str, + read_binary_uint64, +) +from ..varint import read_varint + + +__all__ = [ + 'DynamicColumn', + 'SharedValueDecoder', + 'DYNAMIC_V1', + 'DYNAMIC_V2', + 'VARIANT_MODE_BASIC', + 'VARIANT_MODE_COMPACT', + 'NULL_DISCRIMINATOR', + 'SHARED_VARIANT_NAME', +] + + +# DynamicSerializationVersion enum (ClickHouse 25.5). Note these +# numeric values differ from ObjectSerializationVersion in +# newjsoncolumn — each enum is independent on the server side. +DYNAMIC_V1 = 1 +DYNAMIC_V2 = 2 + +# VariantDiscriminatorsSerializationMode. +VARIANT_MODE_BASIC = 0 +VARIANT_MODE_COMPACT = 1 + +# ColumnVariant::NULL_DISCRIMINATOR — the global discriminator value used +# to mark a NULL row. +NULL_DISCRIMINATOR = 0xFF + +# SHARED_VARIANT_TYPE_NAME from ClickHouse src/Columns/ColumnDynamic.h. +# Participates in the alphabetical sort of variant names alongside +# user-declared variants. +SHARED_VARIANT_NAME = "SharedVariant" + + +class DynamicColumn(Column): + """ + Reader for a ClickHouse ``Dynamic`` column. + + Construction does not know the inner variant types yet — those come + from the wire in ``read_state_prefix``. The variant list always ends + with an implicit ``SharedVariant`` (a ``ByteString`` carrying + ``encodeDataType + serializeBinary`` blobs) that catches values + whose type does not match any of the declared variants. + """ + + py_types = (object,) + + def __init__(self, column_by_spec_getter, shared_value_decoder=None, + **kwargs): + self.column_by_spec_getter = column_by_spec_getter + # Pre-built decoder for the implicit SharedVariant. Sharing one + # across all DynamicColumns of a block (plus the JSON column + # itself) lets the handler/column caches accumulate across + # every overflow value in the block. + if shared_value_decoder is None: + shared_value_decoder = SharedValueDecoder( + column_by_spec_getter) + self.shared_value_decoder = shared_value_decoder + self._column_kwargs = kwargs + self.variant_specs = [] + self.variant_columns = [] + self.discriminators_mode = VARIANT_MODE_BASIC + super(DynamicColumn, self).__init__(**kwargs) + + def read_state_prefix(self, buf): + # ObjectStructure stream: + # UInt64 LE structure_version (V1 = 1, V2 = 2) + # if V1: VarUInt num_dynamic_types (legacy max_dynamic_types + # slot, value reused for the + # variant count — discarded + # by the server too) + # VarUInt num_dynamic_types (excludes the implicit + # SharedVariant) + # N × String variant type spec + # SerializationVariant prefix: + # UInt64 LE discriminators_mode (BASIC = 0, COMPACT = 1) + structure_version = read_binary_uint64(buf) + if structure_version not in (DYNAMIC_V1, DYNAMIC_V2): + raise NotImplementedError( + "Unsupported Dynamic serialization version {}".format( + structure_version)) + if structure_version == DYNAMIC_V1: + read_varint(buf) # legacy slot + num_dynamic_types = read_varint(buf) + declared_specs = [ + read_binary_str(buf) for _ in range(num_dynamic_types) + ] + + # SerializationVariant / DataTypeVariant sort their global + # discriminators by ``DataType::getName()`` alphabetically. The + # SharedVariant type name ("SharedVariant") participates in the + # sort, so we have to interleave it back in to know which + # discriminator index it claims. + all_names = list(declared_specs) + [SHARED_VARIANT_NAME] + sorted_names = sorted(all_names) + self.variant_specs = list(declared_specs) + self.variant_columns = [] + self._shared_variant_index = None + for i, name in enumerate(sorted_names): + if name == SHARED_VARIANT_NAME: + self.variant_columns.append( + ByteString(**self._column_kwargs)) + self._shared_variant_index = i + else: + self.variant_columns.append( + self.column_by_spec_getter(name)) + + self.discriminators_mode = read_binary_uint64(buf) + if self.discriminators_mode not in ( + VARIANT_MODE_BASIC, VARIANT_MODE_COMPACT): + raise NotImplementedError( + "Unsupported Variant discriminators mode {}".format( + self.discriminators_mode)) + # Variant element state prefixes — most primitives are no-ops but + # any composed type (LowCardinality, etc.) needs to consume its + # own bytes. The SharedVariant String has no prefix. + for i, column in enumerate(self.variant_columns): + if i == self._shared_variant_index: + continue + column.read_state_prefix(buf) + + def read_items(self, n_items, buf): + """ + Read ``n_items`` rows of the SerializationVariant body in BASIC + mode. Wire layout per ClickHouse 25.5: + + * ``n_items × UInt8`` global discriminators (``255`` for + NULL). + * For each variant in global discriminator order, the + per-variant column data sized by how many rows landed in + that variant. + + Rows that hit the SharedVariant slot are passed through + ``self.shared_value_decoder`` to recover their Python form. + """ + if self.discriminators_mode == VARIANT_MODE_COMPACT: + raise NotImplementedError( + "Compact Variant discriminators are not supported yet") + + variant_columns = self.variant_columns + shared_variant_index = self._shared_variant_index + shared_variant_decoder = self.shared_value_decoder.decode + + discriminators = buf.read(n_items) + if len(discriminators) != n_items: + raise EOFError( + "Variant discriminators truncated: got {} bytes, " + "want {}".format(len(discriminators), n_items)) + + # Count rows per variant (preserving wire-order row appearance). + per_variant_indices = [[] for _ in range(len(variant_columns))] + for row, disc in enumerate(discriminators): + if disc == NULL_DISCRIMINATOR: + continue + if disc >= len(variant_columns): + raise ValueError( + "Variant discriminator {} out of range " + "(have {} variants)".format( + disc, len(variant_columns))) + per_variant_indices[disc].append(row) + + values_by_row = [None] * n_items + for variant_idx, rows in enumerate(per_variant_indices): + if not rows: + continue + column = variant_columns[variant_idx] + # ``read_data`` handles nulls maps / nested column wiring; + # ``read_items`` is a thinner low-level API. Pick whichever + # the underlying column exposes — most primitives implement + # both. + if hasattr(column, 'read_data'): + chunk = column.read_data(len(rows), buf) + else: + chunk = column.read_items(len(rows), buf) + chunk = list(chunk) + if variant_idx == shared_variant_index: + chunk = [shared_variant_decoder(b) for b in chunk] + for row, value in zip(rows, chunk): + values_by_row[row] = value + + return values_by_row + + +# ---------------------------------------------------------------------- +# encodeDataType / serializeBinary decoder for SharedVariant blobs +# ---------------------------------------------------------------------- + +# BinaryTypeIndex tags from ClickHouse 25.5 +# (src/DataTypes/DataTypesBinaryEncoding.cpp). Only the tags reachable +# from values that fit in a JSON document are mapped; unmapped tags +# raise on read so we surface gaps loudly instead of silently dropping +# data. +_TAG_NOTHING = 0x00 +_TAG_UINT8 = 0x01 +_TAG_UINT16 = 0x02 +_TAG_UINT32 = 0x03 +_TAG_UINT64 = 0x04 +_TAG_UINT128 = 0x05 +_TAG_UINT256 = 0x06 +_TAG_INT8 = 0x07 +_TAG_INT16 = 0x08 +_TAG_INT32 = 0x09 +_TAG_INT64 = 0x0A +_TAG_INT128 = 0x0B +_TAG_INT256 = 0x0C +_TAG_FLOAT32 = 0x0D +_TAG_FLOAT64 = 0x0E +_TAG_DATE = 0x0F +_TAG_DATE32 = 0x10 +_TAG_DATETIME_UTC = 0x11 +_TAG_DATETIME_TZ = 0x12 +_TAG_DATETIME64_UTC = 0x13 +_TAG_DATETIME64_TZ = 0x14 +_TAG_STRING = 0x15 +_TAG_FIXED_STRING = 0x16 +_TAG_ARRAY = 0x1E +_TAG_TUPLE_UNNAMED = 0x1F +_TAG_TUPLE_NAMED = 0x20 +_TAG_NULLABLE = 0x23 +_TAG_BOOL = 0x2D +_TAG_JSON = 0x30 + + +def _read_varint(reader): + """LEB128 decoder for any reader exposing ``read_one`` returning an + ``int`` byte. The Cython ``read_varint`` in ``..varint`` only works + against the driver's buffered reader; shared-value decoding works + against an in-memory blob, so we re-implement the trivial loop here + to keep the hot path free of adapter layers.""" + shift = 0 + result = 0 + while True: + b = reader.read_one() + result |= (b & 0x7F) << shift + shift += 7 + if b < 0x80: + return result + + +def _read_binary_string(reader): + length = _read_varint(reader) + return reader.read(length) + + +_PRIMITIVE_TYPE_NAMES = { + _TAG_NOTHING: "Nothing", + _TAG_UINT8: "UInt8", + _TAG_UINT16: "UInt16", + _TAG_UINT32: "UInt32", + _TAG_UINT64: "UInt64", + _TAG_UINT128: "UInt128", + _TAG_UINT256: "UInt256", + _TAG_INT8: "Int8", + _TAG_INT16: "Int16", + _TAG_INT32: "Int32", + _TAG_INT64: "Int64", + _TAG_INT128: "Int128", + _TAG_INT256: "Int256", + _TAG_FLOAT32: "Float32", + _TAG_FLOAT64: "Float64", + _TAG_DATE: "Date", + _TAG_DATE32: "Date32", + _TAG_DATETIME_UTC: "DateTime", + _TAG_STRING: "String", + _TAG_BOOL: "Bool", +} + + +def _decode_type_spec(buf): + """ + Parse the ``encodeDataType`` byte stream into a ClickHouse type + string suitable for ``column_by_spec_getter``. The string form is + intentional: it keeps the SharedVariant handler cache keyable by a + single hash and lets us reuse the driver's existing column-by-spec + machinery instead of reimplementing it on a parallel AST. + """ + tag = buf.read(1) + if not tag: + raise EOFError("Unexpected end of encoded type stream") + tag = tag[0] + + name = _PRIMITIVE_TYPE_NAMES.get(tag) + if name is not None: + return name + + if tag == _TAG_FIXED_STRING: + n = _read_varint(buf) + return "FixedString({})".format(n) + + if tag == _TAG_DATETIME_TZ: + tz = _read_binary_string(buf).decode('utf-8') + return "DateTime('{}')".format(tz) + + if tag == _TAG_DATETIME64_UTC: + scale = _read_varint(buf) + return "DateTime64({})".format(scale) + + if tag == _TAG_DATETIME64_TZ: + scale = _read_varint(buf) + tz = _read_binary_string(buf).decode('utf-8') + return "DateTime64({}, '{}')".format(scale, tz) + + if tag == _TAG_NULLABLE: + inner = _decode_type_spec(buf) + return "Nullable({})".format(inner) + + if tag == _TAG_ARRAY: + inner = _decode_type_spec(buf) + return "Array({})".format(inner) + + if tag == _TAG_TUPLE_UNNAMED: + size = _read_varint(buf) + elems = [_decode_type_spec(buf) for _ in range(size)] + return "Tuple({})".format(", ".join(elems)) + + if tag == _TAG_TUPLE_NAMED: + size = _read_varint(buf) + parts = [] + for _ in range(size): + element_name = _read_binary_string(buf).decode('utf-8') + element_type = _decode_type_spec(buf) + parts.append("{} {}".format(element_name, element_type)) + return "Tuple({})".format(", ".join(parts)) + + if tag == _TAG_JSON: + # encodeDataType layout for JSON (ClickHouse 25.5): + # UInt8 serialization version + # VarUInt max_dynamic_paths + # UInt8 max_dynamic_types + # VarUInt typed_paths_count, then per path: String + type + # VarUInt paths_to_skip_count, then per path: String + # VarUInt path_regexps_count, then per regexp: String + # None of these parameters change how a JSON value is laid out on + # the wire (every path is dynamic), so the spec collapses to the + # bare "JSON" handler once the bytes are consumed. + buf.read_one() # serialization version + _read_varint(buf) # max_dynamic_paths + buf.read_one() # max_dynamic_types + for _ in range(_read_varint(buf)): # typed paths + _read_binary_string(buf) + _decode_type_spec(buf) + for _ in range(_read_varint(buf)): # paths to skip + _read_binary_string(buf) + for _ in range(_read_varint(buf)): # path regexps to skip + _read_binary_string(buf) + return "JSON" + + raise NotImplementedError( + "Cannot decode binary type tag 0x{:02x} in shared JSON value" + .format(tag)) + + +def _nothing_handler(reader): + return None + + +def _insert_dotted_path(obj, dotted, value): + """Place ``value`` into ``obj`` under a dotted JSON path, creating the + intermediate dicts. ``{"a.b": 1}`` becomes ``{"a": {"b": 1}}`` so a + nested JSON value read out of a SharedVariant matches the shape the + top-level reader produces.""" + parts = dotted.split('.') + cursor = obj + for part in parts[:-1]: + child = cursor.get(part) + if not isinstance(child, dict): + child = {} + cursor[part] = child + cursor = child + cursor[parts[-1]] = value + + +def _split_tuple_elements(inner): + """Split a ``Tuple(...)`` body on top-level commas.""" + parts = [] + depth = 0 + start = 0 + for i, ch in enumerate(inner): + if ch == '(': + depth += 1 + elif ch == ')': + depth -= 1 + elif ch == ',' and depth == 0: + parts.append(inner[start:i].strip()) + start = i + 1 + last = inner[start:].strip() + if last: + parts.append(last) + return parts + + +class SharedValueDecoder: + """ + Per-block decoder for the ``encodeDataType + serializeBinary`` + payloads found in a SharedVariant's underlying String column. + + Two caches keep the hot path tight: + * ``_handler_cache`` maps a decoded type spec (e.g. ``"Int64"``, + ``"Array(Nullable(String))"``) to a precompiled callable that + reads only the value bytes — no per-value ``startswith`` chain + or recursive ``_decode_value_by_spec`` walk. + * ``_column_cache`` keeps the scalar column readers alive across + values so we don't reconstruct ``Int64Column`` / ``String`` + for every overflow entry. + + A single ``_SharedValueReader`` is reused for every value rather + than allocating an ``io.BytesIO`` + adapter pair per call. + """ + + __slots__ = ( + '_column_by_spec_getter', + '_column_cache', + '_handler_cache', + '_reader', + ) + + def __init__(self, column_by_spec_getter): + self._column_by_spec_getter = column_by_spec_getter + self._column_cache = {} + self._handler_cache = {} + self._reader = _SharedValueReader() + + def decode(self, blob): + if not blob: + return None + reader = self._reader + reader.reset(blob) + return self._decode_dynamic_value(reader) + + def _decode_dynamic_value(self, reader): + """Decode one ``encodeDataType + serializeBinary`` value from the + current reader position. Used both for a top-level SharedVariant + blob and, recursively, for each dynamic path of a nested JSON + value.""" + type_spec = _decode_type_spec(reader) + handler = self._handler_cache.get(type_spec) + if handler is None: + handler = self._build_handler(type_spec) + self._handler_cache[type_spec] = handler + return handler(reader) + + def _build_handler(self, type_spec): + if type_spec == "Nothing": + return _nothing_handler + + if type_spec == "JSON": + def json_handler(reader, _decode=self._decode_dynamic_value): + # VarUInt path count, then per path: String name + a + # dynamic value. Absent paths arrive as Nothing-typed + # values; drop them so the object matches its input. + obj = {} + for _ in range(_read_varint(reader)): + path = _read_binary_string(reader).decode('utf-8') + value = _decode(reader) + if value is not None: + _insert_dotted_path(obj, path, value) + return obj + return json_handler + + if type_spec.startswith("Nullable("): + inner_spec = type_spec[len("Nullable("):-1] + inner_handler = self._lookup_handler(inner_spec) + + def nullable_handler(reader, _inner=inner_handler): + if reader.read_one(): + return None + return _inner(reader) + return nullable_handler + + if type_spec.startswith("Array("): + inner_spec = type_spec[len("Array("):-1] + inner_handler = self._lookup_handler(inner_spec) + + def array_handler(reader, _inner=inner_handler): + size = _read_varint(reader) + return [_inner(reader) for _ in range(size)] + return array_handler + + if type_spec.startswith("Tuple("): + elements = _split_tuple_elements( + type_spec[len("Tuple("):-1]) + element_handlers = tuple( + self._lookup_handler(e) for e in elements) + + def tuple_handler(reader, _handlers=element_handlers): + return tuple(h(reader) for h in _handlers) + return tuple_handler + + # Scalar — bind the column reader once and let it handle bytes. + column = self._column_cache.get(type_spec) + if column is None: + column = self._column_by_spec_getter(type_spec) + self._column_cache[type_spec] = column + + def scalar_handler(reader, _column=column): + return _column.read_items(1, reader)[0] + return scalar_handler + + def _lookup_handler(self, type_spec): + handler = self._handler_cache.get(type_spec) + if handler is None: + handler = self._build_handler(type_spec) + self._handler_cache[type_spec] = handler + return handler + + +class _SharedValueReader: + """ + Reusable reader over an in-memory bytes blob. Exposes the surface + the driver's column readers need (``read``, ``read_one``, + ``read_strings``) without allocating an ``io.BytesIO`` plus an + adapter every call — both are hot-loop overhead on the shared + path. The owning :class:`SharedValueDecoder` resets the underlying + bytes between values. + """ + + __slots__ = ('_blob', '_pos') + + def __init__(self): + self._blob = b'' + self._pos = 0 + + def reset(self, blob): + self._blob = blob + self._pos = 0 + + def read(self, n): + start = self._pos + end = start + n + self._pos = end + return self._blob[start:end] + + def read_one(self): + pos = self._pos + b = self._blob[pos] + self._pos = pos + 1 + return b + + def read_strings(self, n_items, encoding=None): + out = [] + for _ in range(n_items): + length = _read_varint(self) + chunk = self.read(length) + if encoding is not None: + chunk = chunk.decode(encoding) + out.append(chunk) + return out diff --git a/clickhouse_driver/columns/ipcolumn.py b/clickhouse_driver/columns/ipcolumn.py index d227f031..48074c74 100644 --- a/clickhouse_driver/columns/ipcolumn.py +++ b/clickhouse_driver/columns/ipcolumn.py @@ -67,6 +67,10 @@ def before_write_items(self, items, nulls_map=None): class IPv6Column(ByteFixedString): ch_type = "IPv6" py_types = (str, IPv6Address, bytes) + # Wire-format default: must be readable by after_read_items and + # writable by write_items as-is (sparse deserialization and + # LowCardinality pass it to both without conversion). + null_value = b'\x00' * 16 def __init__(self, types_check=False, **kwargs): super(IPv6Column, self).__init__(16, types_check=types_check, **kwargs) diff --git a/clickhouse_driver/columns/jsoncolumn.py b/clickhouse_driver/columns/jsoncolumn.py index 080b407c..37de1b72 100644 --- a/clickhouse_driver/columns/jsoncolumn.py +++ b/clickhouse_driver/columns/jsoncolumn.py @@ -16,7 +16,7 @@ def __init__(self, column_by_spec_getter, **kwargs): self.string_column = String(**kwargs) super(JsonColumn, self).__init__(**kwargs) - def write_state_prefix(self, buf): + def write_state_prefix(self, buf, items=None): # Read in binary format. # Write in text format. write_binary_uint8(1, buf) diff --git a/clickhouse_driver/columns/lowcardinalitycolumn.py b/clickhouse_driver/columns/lowcardinalitycolumn.py index 43134f72..20dcc520 100644 --- a/clickhouse_driver/columns/lowcardinalitycolumn.py +++ b/clickhouse_driver/columns/lowcardinalitycolumn.py @@ -44,7 +44,7 @@ def read_state_prefix(self, buf): read_binary_uint64(buf) - def write_state_prefix(self, buf): + def write_state_prefix(self, buf, items=None): super(LowCardinalityColumn, self).write_state_prefix(buf) # KeysSerializationVersion. See ClickHouse docs. diff --git a/clickhouse_driver/columns/mapcolumn.py b/clickhouse_driver/columns/mapcolumn.py index 67536f4c..33b14db7 100644 --- a/clickhouse_driver/columns/mapcolumn.py +++ b/clickhouse_driver/columns/mapcolumn.py @@ -17,6 +17,9 @@ def __init__(self, key_column, value_column, **kwargs): self.key_column = key_column self.value_column = value_column super(MapColumn, self).__init__(**kwargs) + # Map keys are restricted to scalar types, so only the value + # column can carry a data-dependent prefix. + self.prefix_needs_items = value_column.prefix_needs_items def read_state_prefix(self, buf): super(MapColumn, self).read_state_prefix(buf) @@ -24,11 +27,14 @@ def read_state_prefix(self, buf): self.key_column.read_state_prefix(buf) self.value_column.read_state_prefix(buf) - def write_state_prefix(self, buf): + def write_state_prefix(self, buf, items=None): super(MapColumn, self).write_state_prefix(buf) + value_items = None + if items is not None and self.value_column.prefix_needs_items: + value_items = [v for x in items for v in x.values()] self.key_column.write_state_prefix(buf) - self.value_column.write_state_prefix(buf) + self.value_column.write_state_prefix(buf, value_items) def read_items(self, n_items, buf): if not n_items: diff --git a/clickhouse_driver/columns/newjsoncolumn.py b/clickhouse_driver/columns/newjsoncolumn.py new file mode 100644 index 00000000..50a70d5f --- /dev/null +++ b/clickhouse_driver/columns/newjsoncolumn.py @@ -0,0 +1,616 @@ +""" +ClickHouse ``JSON`` (a.k.a. ``Object('json')``) column reader. + +The wire format is the one introduced in ClickHouse 24.8+ and stabilised +in 25.x. Both directions are composed out of the existing column +readers rather than hand-rolled: + + * ``DynamicColumn`` reads one dynamic path's body (a + SerializationVariant over the declared variant types plus an + implicit ``SharedVariant``). + * ``ArrayColumn`` + ``TupleColumn`` + ``String`` reads the shared + sub-column ``Array(Tuple(String, String))``. + * Shared-variant blobs are decoded by walking ``encodeDataType`` and + then delegating the value bytes to the appropriate column reader + obtained via ``column_by_spec_getter``. + +The write path emits an ``ObjectSerializationVersion::V2`` header +unconditionally; the server transparently falls back to V1 framing +when the client revision is too old for V2. +""" + +from .arraycolumn import ArrayColumn +from .base import Column +from .dynamiccolumn import ( + DYNAMIC_V2, + SHARED_VARIANT_NAME, + DynamicColumn, + SharedValueDecoder, + VARIANT_MODE_BASIC, + _split_tuple_elements, +) +from .stringcolumn import ByteString, String +from .tuplecolumn import TupleColumn +from ..reader import ( + read_binary_str, + read_binary_uint64, +) +from ..util.compat import json +from ..varint import read_varint, write_varint +from ..writer import write_binary_uint64 + + +# ObjectSerializationVersion values (ClickHouse 25.5). +OBJECT_V1 = 0 +OBJECT_STRING = 1 +OBJECT_V2 = 2 + + +class NewJsonColumn(Column): # pragma: requires-clickhouse-24.8 + """ + Reader/writer for the ClickHouse ``JSON`` type. SELECT returns + nested ``dict`` rows; INSERT accepts ``dict`` or JSON-text + ``str``. Wire framing is V1/V2 ``SerializationObject`` on read + and V2 on write; the format is composed from + :class:`DynamicColumn` + ``Array(Tuple(String, String))`` for + shared data rather than hand-rolled. + """ + + py_types = (dict, str) + + # JSON columns are non-nullable on the wire; supply an empty dict + # as the placeholder used by sparse/null helpers in the base + # column. + null_value = {} + + # The object prefix (path list + per-path SerializationDynamic + # prefixes) is data-dependent; ``write_column`` and the container + # columns (Array/Tuple/Map) thread the block's items into + # ``write_state_prefix`` so it lands in the prefix stream position + # the server expects for nested columns. + prefix_needs_items = True + + def __init__(self, column_by_spec_getter, **kwargs): + self.column_by_spec_getter = column_by_spec_getter + self._column_kwargs = kwargs + self.string_column = String(**kwargs) + + self.serialization_version = None + self._write_paths_state = None + self.sorted_dynamic_paths = [] + self.dynamic_columns = [] + self.shared_data_column = None + # One decoder per block. It owns the handler-per-type_spec + # cache, the scalar column-reader cache, and the reusable + # bytes reader. Both this column's top-level shared paths and + # every nested ``DynamicColumn``'s SharedVariant route their + # overflow values through the same decoder so all caches + # accumulate together. + self._shared_value_decoder = SharedValueDecoder( + column_by_spec_getter) + + super(NewJsonColumn, self).__init__(**kwargs) + + # ------------------------------------------------------------------ + # read path + # ------------------------------------------------------------------ + + def read_state_prefix(self, buf): + # ObjectStructure stream layout (V1/V2): + # UInt64 LE serialization_version + # if V1: VarUInt max_dynamic_paths (discarded) + # VarUInt dynamic_paths_count + # N × String dynamic path names (sorted) + # (optional statistics — disabled in native SELECT by default) + # Then, per dynamic path: SerializationDynamic state prefix. + # Then, shared_data state prefix (no bytes — Array/Tuple/String + # do not emit prefixes). + version = read_binary_uint64(buf) + if version not in (OBJECT_V1, OBJECT_STRING, OBJECT_V2): + raise NotImplementedError( + "Unsupported JSON serialization version {}".format(version)) + self.serialization_version = version + if version == OBJECT_STRING: + return + + if version == OBJECT_V1: + read_varint(buf) # legacy max_dynamic_paths + + num_paths = read_varint(buf) + self.sorted_dynamic_paths = [ + read_binary_str(buf) for _ in range(num_paths) + ] + + self.dynamic_columns = [] + for _ in range(num_paths): + col = DynamicColumn( + self.column_by_spec_getter, + shared_value_decoder=self._shared_value_decoder, + **self._column_kwargs) + col.read_state_prefix(buf) + self.dynamic_columns.append(col) + + self.shared_data_column = self._build_shared_data_column() + self.shared_data_column.read_state_prefix(buf) + + def read_items(self, n_items, buf): + if self.serialization_version == OBJECT_STRING: + return self._read_items_string(n_items, buf) + + # Typed paths declared in the JSON column spec (``JSON(name + # Int64)``) would be read here in spec order. The current PR + # does not parse typed paths out of the column-type string, so + # we emulate the original behaviour and skip straight to dynamic + # paths. + column_per_path_values = [] + for col in self.dynamic_columns: + column_per_path_values.append(col.read_items(n_items, buf)) + + shared_rows = self.shared_data_column.read_data(n_items, buf) + + return self._fold_rows( + n_items, column_per_path_values, shared_rows) + + def _read_items_string(self, n_items, buf): + # Each row is one String containing the JSON text. + strings = buf.read_strings(n_items, encoding='utf-8') + if (self.context.client_settings or {}).get('use_arrow'): + # Raw JSON text: the Arrow layer parses it or passes it + # through depending on the declared type. + return strings + return [json.loads(s) if s else {} for s in strings] + + def _build_shared_data_column(self): + kwargs = self._column_kwargs + key_column = String(**kwargs) + # SharedVariant values are raw bytes (``encodeDataType + + # serializeBinary``), not UTF-8 text. + value_column = ByteString(**kwargs) + tuple_column = TupleColumn( + ('path', 'value'), [key_column, value_column], **kwargs) + return ArrayColumn(tuple_column, **kwargs) + + def _fold_rows(self, n_items, per_path_values, shared_rows): + rows = [{} for _ in range(n_items)] + + for path, values in zip(self.sorted_dynamic_paths, per_path_values): + for row_idx, value in enumerate(values): + if value is not None: + rows[row_idx][path] = _tuples_to_lists(value) + + decode = self._shared_value_decoder.decode + for row_idx, entries in enumerate(shared_rows or []): + for path, encoded in entries: + rows[row_idx][path] = _tuples_to_lists(decode(encoded)) + + for row in rows: + self._denormalize_dotted_paths(row) + + return rows + + @staticmethod + def _denormalize_dotted_paths(obj): + # Convert dotted top-level keys (``"a.b.c"``) into nested dicts. + # A scalar already living at a prefix of a dotted key would be + # incompatible with the nested layout; the server should never + # emit such a conflict for a single JSON row, but raise loudly + # rather than silently overwriting if it ever does. + for key in list(obj.keys()): + parts = key.split('.') + if len(parts) <= 1: + continue + parent = obj + for part in parts[:-1]: + if part not in parent: + parent[part] = {} + elif not isinstance(parent[part], dict): + raise ValueError( + "Cannot denormalise dotted JSON path {!r}: " + "prefix {!r} already holds a non-dict value " + "{!r}".format(key, part, parent[part])) + parent = parent[part] + parent[parts[-1]] = obj[key] + del obj[key] + + # ------------------------------------------------------------------ + # write path + # ------------------------------------------------------------------ + + def write_state_prefix(self, buf, items=None): + if items is None: + raise NotImplementedError( + 'JSON columns can only be written when the block items ' + 'are threaded into write_state_prefix' + ) + items = [self._normalise_write_item(x) for x in items] + self._write_paths_state = self._unfold_json(items, depth=0) + self._write_object_state_prefix(self._write_paths_state, buf) + + def write_items(self, items, buf): + # The body is written from the paths computed over the same + # items in ``write_state_prefix``; ``items`` only supplies the + # row count here. For ``Nullable(JSON)`` the nulls map emitted + # by the callers lands between the prefix and this body, + # matching the on-wire order the server expects. + self._write_values(self._write_paths_state, len(items), buf) + + def _normalise_write_item(self, item): + if item is None: + return self.null_value + if isinstance(item, str): + return json.loads(item) + return item + + def _write_object_state_prefix(self, paths, buf, depth=0): + # UInt64 LE: ObjectSerializationVersion::V2 (the server falls + # back to V1 itself if its client revision is too old, so we + # write V2 unconditionally). + write_binary_uint64(OBJECT_V2, buf) + self._write_paths(paths, buf) + self._write_dynamic_state_prefixes(paths, buf, depth=depth) + + def _write_paths(self, paths, buf): + # VarUInt dynamic_paths_count + N × String path names. + write_varint(len(paths), buf) + self.string_column.write_items(paths.keys(), buf) + + def _write_dynamic_state_prefixes(self, paths, buf, depth=0): + # SerializationDynamic state prefix per dynamic path: + # UInt64 LE DynamicSerializationVersion::V2 + # VarUInt num_dynamic_types (excludes SharedVariant) + # N × String variant type spec + # SerializationVariant prefix: + # UInt64 LE discriminators_mode (BASIC) + for col in paths.values(): + write_binary_uint64(DYNAMIC_V2, buf) + write_varint(len(col), buf) + self.string_column.write_items(col.keys(), buf) + write_binary_uint64(VARIANT_MODE_BASIC, buf) + for spec in col: + if spec.startswith("Tuple") and "JSON" in spec: + self._write_complex_tuple_header( + col[spec]["values"], spec, depth + 1, buf) + elif spec.startswith("Array") and "JSON" in spec: + self._write_complex_array_header( + col[spec]["values"], spec, depth + 1, buf) + + def _write_values(self, paths, rows, buf, depth=0): + # SerializationVariant body per dynamic path: + # n_items × UInt8 global discriminators + # per declared variant in alphabetical order: column data + # Followed by the shared-data Array(Tuple(String, String))'s + # offsets — all zero because we never overflow into the + # SharedVariant on write. + for col in paths.values(): + buf.write(self._get_row_positions(col, rows)) + for spec in col: + if spec.startswith("Array"): + if "JSON" in spec: + self._write_complex_array_values( + col[spec]["values"], spec, depth + 1, buf) + else: + insert = self._preprocess_array( + col[spec]["values"], spec[6:-1]) + writer = self.column_by_spec_getter(spec) + writer.write_data(insert, buf) + elif spec.startswith("Tuple"): + if "JSON" in spec: + self._write_complex_tuple_values( + col[spec]["values"], spec, depth + 1, buf) + else: + writer = self.column_by_spec_getter(spec) + writer.write_items(col[spec]["values"], buf) + else: + writer = self.column_by_spec_getter(spec) + writer.write_items(col[spec]["values"], buf) + + # Write final padding. + buf.write(b"\x00" * rows * 8) + + def _write_complex_tuple_header(self, values, spec, depth, buf): + # ``spec`` is ``Tuple(e0, e1, ...)``; split the body on top-level + # commas (a naive ``split`` would break on the commas inside a + # nested ``Tuple``/``JSON`` element) and emit the state prefix for + # every element that contains a JSON sub-column. + for i, subspec in enumerate(_split_tuple_elements(spec[6:-1])): + if "JSON" not in subspec: + continue + sub_values = [row[i] for row in values] + if subspec.startswith("JSON"): + paths = self._unfold_json(sub_values, depth=depth) + self._write_object_state_prefix(paths, buf, depth=depth) + elif subspec.startswith("Tuple"): + self._write_complex_tuple_header( + sub_values, subspec, depth, buf) + elif subspec.startswith("Array"): + self._write_complex_array_header( + sub_values, subspec, depth, buf) + + def _write_complex_array_header(self, values, spec, depth, buf): + items = [] + for item in values: + items += item + inner = spec[6:-1] # strip "Array(" ... ")" + if inner.startswith("Tuple"): + self._write_complex_tuple_header(items, inner, depth, buf) + elif inner.startswith("Array"): + self._write_complex_array_header(items, inner, depth, buf) + else: # Array(JSON) + paths = self._unfold_json(items, depth=depth) + self._write_object_state_prefix(paths, buf, depth=depth) + + def _write_complex_tuple_values(self, values, spec, depth, buf): + for i, subspec in enumerate(_split_tuple_elements(spec[6:-1])): + sub_values = [row[i] for row in values] + if subspec.startswith("JSON"): + paths = self._unfold_json(sub_values, depth=depth) + self._write_values(paths, len(sub_values), buf, depth=depth) + elif subspec.startswith("Tuple"): + if "JSON" in subspec: + self._write_complex_tuple_values( + sub_values, subspec, depth, buf) + else: + writer = self.column_by_spec_getter(subspec) + writer.write_items(sub_values, buf) + elif subspec.startswith("Array"): + if "JSON" in subspec: + self._write_complex_array_values( + sub_values, subspec, depth, buf) + else: + insert = self._preprocess_array(sub_values, subspec[6:-1]) + writer = self.column_by_spec_getter(subspec) + writer.write_data(insert, buf) + else: + # Simple element, always wrapped in Nullable by + # _get_json_value_spec; its writer emits the null map and + # values columnar-style across every row. + writer = self.column_by_spec_getter(subspec) + writer.write_data(sub_values, buf) + + def _write_complex_array_values(self, values, spec, depth, buf): + bound = 0 + for v in values: + bound = bound + len(v) + write_binary_uint64(bound, buf) + items = [] + for item in values: + items += item + inner = spec[6:-1] # strip "Array(" ... ")" + if inner.startswith("Tuple"): + self._write_complex_tuple_values(items, inner, depth, buf) + elif inner.startswith("Array"): + self._write_complex_array_values(items, inner, depth, buf) + else: # Array(JSON) + paths = self._unfold_json(items, depth=depth) + self._write_values(paths, len(items), buf, depth=depth) + + def _get_json_value_spec(self, item, depth): + """Infer the ClickHouse column spec for a Python value being + inserted into a JSON column. ``depth`` shrinks the per-level + ``max_dynamic_types`` / ``max_dynamic_paths`` budgets so nested + dicts stay within server limits.""" + if isinstance(item, int) and not isinstance(item, bool): + return "Int64" + elif isinstance(item, float): + return "Float64" + elif isinstance(item, str): + return "String" + elif isinstance(item, bool): + return "Bool" + elif isinstance(item, dict): + max_types = int(2 ** (4 - depth)) + max_paths = int(4 ** (4 - depth)) + return ( + "JSON(max_dynamic_types={}, " + "max_dynamic_paths={})".format(max_types, max_paths) + ) + elif isinstance(item, list): + value_types = [] + for entry in item: + t = type(entry) + if t not in value_types: + value_types.append(t) + if dict in value_types or list in value_types: + result = "Tuple(" + unique_specs = [] + for entry in item: + spec = self._get_json_value_spec(entry, depth) + if (not spec.startswith("Array") + and not spec.startswith("Tuple") + and not spec.startswith("JSON")): + result += "Nullable({}), ".format(spec) + else: + result += "{}, ".format(spec) + if spec not in unique_specs: + unique_specs.append(spec) + + if len(unique_specs) == 1: + inner = self._get_json_value_spec(item[0], depth=depth) + return "Array({})".format(inner) + result = result[:-2] + ")" + return result + else: + if str in value_types: + return "Array(Nullable(String))" + elif float in value_types: + if bool not in value_types: + return "Array(Nullable(Float64))" + else: + return "Array(Nullable(String))" + elif int in value_types: + return "Array(Nullable(Int64))" + elif bool in value_types: + return "Array(Nullable(Bool))" + else: + return "Array(Nullable(String))" + elif item is None: + return "String" + + def _get_row_positions(self, col, row_count): + # Compute each row's global discriminator. ``DataTypeVariant`` + # sorts its variant list (which includes the implicit + # ``SharedVariant``) by ``getName()`` alphabetically; the global + # discriminator index is each variant's position in that sort. + sorted_with_shared = sorted( + list(col.keys()) + [SHARED_VARIANT_NAME]) + spec_to_discriminator = { + spec: i for i, spec in enumerate(sorted_with_shared) + } + result = [255] * row_count + for spec, data in col.items(): + disc = spec_to_discriminator[spec] + for pos in data["positions"]: + result[pos] = disc + return bytes(result) + + def _normalize_json(self, obj,): + """Flatten a nested dict into a dict of dotted-path leaves, e.g. + ``{"a": {"b": 1}}`` → ``{"a.b": 1}``. Each non-dict leaf is + returned as ``{"": leaf}`` so callers can compose keys.""" + if isinstance(obj, dict): + result = {} + for k in obj: + if obj[k] is not None: + obj_res = self._normalize_json(obj[k]) + for obj_k in obj_res: + result["{}.{}".format(k, obj_k)] = obj_res[obj_k] + return result + else: + return {"": obj} + + def _unfold_json_item(self, obj, depth, result=None, row_count=0): + """Fold one row into the intermediary + ``{path: {spec: {values: [...], positions: [...]}}}`` layout + that the write path emits to the wire.""" + if result is None: + result = {} + for k in obj: + if obj[k] is not None: + obj_res = self._normalize_json(obj[k]) + for obj_k in obj_res: + key = "{}.{}".format(k, obj_k) + if key not in result: + result[key] = {} + spec = self._get_json_value_spec(obj_res[obj_k], depth) + if spec not in result[key]: + result[key][spec] = { + "values": [], "positions": []} + result[key][spec]["values"].append(obj_res[obj_k]) + result[key][spec]["positions"].append(row_count) + return result + + def _unfold_json(self, items, depth): + """Build the intermediary layout for a whole INSERT block by + unfolding every input row and sorting paths/specs so the + on-wire order matches the server's alphabetical expectation.""" + result = {} + for row, obj in enumerate(items): + result = self._unfold_json_item(obj, depth, result, row) + for k in list(result.keys()): + result[k[:-1]] = dict(sorted(result[k].items())) + del result[k] + result = dict(sorted(result.items())) + return result + + def _preprocess_array(self, values, array_type): + insert = [] + if array_type.startswith("Array"): + for item in values: + insert.append( + self._preprocess_array(item, array_type[6:-1])) + return insert + + if "String" in array_type: + for item in values: + arr = [] + for elem in item: + if isinstance(elem, str): + arr.append(elem) + elif isinstance(elem, bool): + arr.append(str(elem).lower()) + elif elem is None: + arr.append(None) + else: + arr.append(str(elem)) + insert.append(arr) + elif "Int64" in array_type: + for item in values: + arr = [] + for elem in item: + if elem is None: + arr.append(0) + else: + arr.append(int(elem)) + insert.append(arr) + elif "Float64" in array_type: + for item in values: + arr = [] + for elem in item: + if elem is None: + arr.append(0) + else: + arr.append(float(elem)) + insert.append(arr) + elif "Bool" in array_type: + for item in values: + arr = [] + for elem in item: + if elem is not None: + arr.append(bool(elem)) + insert.append(arr) + else: + insert = values + + return insert + + +# Container types that need recursion in ``_tuples_to_lists``; scalars +# (most JSON leaves) short-circuit at the boundary. +_TUPLE_TO_LIST_CONTAINERS = (dict, tuple, list) + + +def _tuples_to_lists(value): + """ + Normalise the Python types a JSON value comes back as. ``Array`` + values arrive as lists already; ``Tuple`` values arrive as tuples + from :class:`TupleColumn`. The rule below preserves that + distinction except when a tuple contains a ``dict`` — those came + from a ``Tuple(..., JSON, ...)`` and the user-facing shape has + always been a list. Changing it would be an API break for anyone + relying on this column today. + """ + if not isinstance(value, _TUPLE_TO_LIST_CONTAINERS): + return value + return _tuples_to_lists_inner(value)[0] + + +def _tuples_to_lists_inner(value): + """Single-pass transform that also reports whether the result has + a ``dict`` anywhere inside, so callers can decide whether a parent + tuple should be coerced to a list without re-walking the tree.""" + if isinstance(value, dict): + out = {} + for k, v in value.items(): + if isinstance(v, _TUPLE_TO_LIST_CONTAINERS): + out[k] = _tuples_to_lists_inner(v)[0] + else: + out[k] = v + return out, True + if isinstance(value, (tuple, list)): + items = [] + has_dict = False + for v in value: + if isinstance(v, _TUPLE_TO_LIST_CONTAINERS): + sub, sub_has_dict = _tuples_to_lists_inner(v) + items.append(sub) + if sub_has_dict: + has_dict = True + else: + items.append(v) + if isinstance(value, list) or has_dict: + return items, has_dict + return tuple(items), False + + +def create_newjson_column(spec, column_by_spec_getter, column_options): + return NewJsonColumn(column_by_spec_getter, **column_options) diff --git a/clickhouse_driver/columns/numpy/base.py b/clickhouse_driver/columns/numpy/base.py index 4ca0097c..abc96d49 100644 --- a/clickhouse_driver/columns/numpy/base.py +++ b/clickhouse_driver/columns/numpy/base.py @@ -24,6 +24,12 @@ def _write_nulls_map(self, items, buf): def _get_nulls_map(self, items): return [bool(x) for x in pd.isnull(items)] + def _read_nulls_map(self, n_items, buf): + # One byte per item on the wire. Vectorized read: consumers + # (np.place, np.ma.MaskedArray) treat non-zero bytes as True. + return np.frombuffer(buf.read(n_items), dtype=np.uint8, + count=n_items) + def _read_data(self, n_items, buf, nulls_map=None): items = self.read_items(n_items, buf) diff --git a/clickhouse_driver/columns/numpy/datetimecolumn.py b/clickhouse_driver/columns/numpy/datetimecolumn.py index c7f3030b..b02fcbac 100644 --- a/clickhouse_driver/columns/numpy/datetimecolumn.py +++ b/clickhouse_driver/columns/numpy/datetimecolumn.py @@ -108,16 +108,20 @@ def write_items(self, items, buf): super(NumpyDateTime64Column, self).write_items(items, buf) -def create_numpy_datetime_column(spec, column_options): +def create_numpy_datetime_column(spec, column_options, column_classes=None): + datetime_column, datetime64_column = column_classes or ( + NumpyDateTimeColumn, NumpyDateTime64Column + ) + if spec.startswith('DateTime64'): - cls = NumpyDateTime64Column + cls = datetime64_column spec = spec[11:-1] params = spec.split(',', 1) column_options['scale'] = int(params[0]) if len(params) > 1: spec = params[1].strip() + ')' else: - cls = NumpyDateTimeColumn + cls = datetime_column spec = spec[9:] context = column_options['context'] diff --git a/clickhouse_driver/columns/service.py b/clickhouse_driver/columns/service.py index 5d8b78e4..a50ff3cc 100644 --- a/clickhouse_driver/columns/service.py +++ b/clickhouse_driver/columns/service.py @@ -16,6 +16,7 @@ ) from .lowcardinalitycolumn import create_low_cardinality_column from .jsoncolumn import create_json_column +from .newjsoncolumn import create_newjson_column from .mapcolumn import create_map_column from .nothingcolumn import NothingColumn from .nullcolumn import NullColumn @@ -66,9 +67,19 @@ def get_column_by_spec(spec, column_options, use_numpy=None): use_numpy = context.client_settings['use_numpy'] if context else False if use_numpy: - from .numpy.service import get_numpy_column_by_spec + # Arrow queries use NumPy-derived columns tuned for zero-copy + # Arrow assembly (see columns/arrow/). + use_arrow = context.client_settings.get('use_arrow', False) \ + if context else False try: + if use_arrow: + from .arrow.service import get_arrow_column_by_spec + + return get_arrow_column_by_spec(spec, column_options) + + from .numpy.service import get_numpy_column_by_spec + return get_numpy_column_by_spec(spec, column_options) except errors.UnknownTypeError: use_numpy = False @@ -128,6 +139,11 @@ def create_column_with_options(x): spec, create_column_with_options, column_options ) + elif spec.startswith("JSON"): + return create_newjson_column( + spec, create_column_with_options, column_options + ) + else: for alias, primitive in aliases: if spec.startswith(alias): @@ -163,7 +179,7 @@ def write_column(context, column_name, column_spec, items, buf, column = get_column_by_spec(column_spec, column_options) try: - column.write_state_prefix(buf) + column.write_state_prefix(buf, items) column.write_data(items, buf) except column_exceptions.ColumnTypeMismatchException as e: diff --git a/clickhouse_driver/columns/tuplecolumn.py b/clickhouse_driver/columns/tuplecolumn.py index 5ff46365..31847155 100644 --- a/clickhouse_driver/columns/tuplecolumn.py +++ b/clickhouse_driver/columns/tuplecolumn.py @@ -18,6 +18,9 @@ def __init__(self, names, nested_columns, **kwargs): super(TupleColumn, self).__init__(**kwargs) self.null_value = tuple(x.null_value for x in nested_columns) + self.prefix_needs_items = any( + x.prefix_needs_items for x in nested_columns + ) def write_data(self, items, buf): items = self.prepare_items(items) @@ -47,11 +50,14 @@ def read_state_prefix(self, buf): for x in self.nested_columns: x.read_state_prefix(buf) - def write_state_prefix(self, buf): + def write_state_prefix(self, buf, items=None): super(TupleColumn, self).write_state_prefix(buf) - for x in self.nested_columns: - x.write_state_prefix(buf) + for i, x in enumerate(self.nested_columns): + nested_items = None + if items is not None and x.prefix_needs_items: + nested_items = [item[i] for item in items] + x.write_state_prefix(buf, nested_items) def create_tuple_column(spec, column_by_spec_getter, column_options): diff --git a/clickhouse_driver/compression/base.py b/clickhouse_driver/compression/base.py index 5dae0cdd..b9180b23 100644 --- a/clickhouse_driver/compression/base.py +++ b/clickhouse_driver/compression/base.py @@ -4,12 +4,7 @@ from ..writer import write_binary_uint8, write_binary_uint32 from .. import errors -try: - from clickhouse_cityhash.cityhash import CityHash128 -except ImportError: - raise RuntimeError( - 'Package clickhouse-cityhash is required to use compression' - ) +from .._cityhash.cityhash import CityHash128 class BaseCompressor(object): diff --git a/clickhouse_driver/streams/compressed.py b/clickhouse_driver/streams/compressed.py index 68cef4ef..bb6b11f9 100644 --- a/clickhouse_driver/streams/compressed.py +++ b/clickhouse_driver/streams/compressed.py @@ -1,12 +1,6 @@ from io import BytesIO -try: - from clickhouse_cityhash.cityhash import CityHash128 -except ImportError: - raise RuntimeError( - 'Package clickhouse-cityhash is required to use compression' - ) - +from .._cityhash.cityhash import CityHash128 from .native import BlockOutputStream, BlockInputStream from ..bufferedreader import CompressedBufferedReader from ..bufferedwriter import CompressedBufferedWriter diff --git a/clickhouse_driver/util/escape.py b/clickhouse_driver/util/escape.py index 465c42fc..5d5d5916 100644 --- a/clickhouse_driver/util/escape.py +++ b/clickhouse_driver/util/escape.py @@ -65,15 +65,16 @@ def escape_param(item, context, for_server=False): item = ''.join(escape_chars_map.get(c, c) for c in item) return "'%s'" % ''.join(escape_chars_map.get(c, c) for c in item) - elif isinstance(item, list): - return "[%s]" % ', '.join( - str(escape_param(x, context, for_server=for_server)) for x in item - ) - - elif isinstance(item, tuple): - return "(%s)" % ', '.join( - str(escape_param(x, context, for_server=for_server)) for x in item + elif isinstance(item, (list, tuple)): + brackets = '[%s]' if isinstance(item, list) else '(%s)' + rv = brackets % ', '.join( + str(escape_param(x, context)) for x in item ) + # Server expects the whole collection literal as an escaped + # string (Field dump format), not a bare [...] or (...). + if for_server: # pragma: requires-clickhouse-22.8 + rv = "'%s'" % ''.join(escape_chars_map.get(c, c) for c in rv) + return rv elif isinstance(item, Enum): return escape_param(item.value, context, for_server=for_server) diff --git a/coverage_excludes.py b/coverage_excludes.py new file mode 100644 index 00000000..1240328f --- /dev/null +++ b/coverage_excludes.py @@ -0,0 +1,50 @@ +""" +Coverage.py plugin: exclude version-gated lines that the current +matrix entry cannot reach. + +Lines tagged ``# pragma: requires-clickhouse-X.Y`` are excluded when +``$CLICKHOUSE_VERSION`` is older than ``X.Y``. Both ``coverage run`` +and ``coveralls`` reload ``.coveragerc`` in separate processes; placing +the logic in a plugin lets the same exclusion list reach both. With +``$CLICKHOUSE_VERSION`` unset the plugin is a no-op, so local runs +measure every line. +""" +import os +import pathlib +import re + +from coverage import CoveragePlugin + + +_PRAGMA = re.compile(r'pragma: requires-clickhouse-(\d+\.\d+)') + + +def _tuple(version): + return tuple(int(part) for part in version.split('.')) + + +class VersionGatedExcludes(CoveragePlugin): + def configure(self, config): + target = os.getenv('CLICKHOUSE_VERSION', '') + if not target: + return + target_t = _tuple(target) + root = pathlib.Path(__file__).parent / 'clickhouse_driver' + if not root.exists(): + return + versions = set() + for path in root.rglob('*.py'): + versions.update( + _PRAGMA.findall(path.read_text(encoding='utf-8'))) + excludes = list(config.get_option('report:exclude_lines') or []) + for version in sorted(versions, key=_tuple): + if _tuple(version) > target_t: + pattern = 'pragma: requires-clickhouse-{}'.format( + re.escape(version)) + if pattern not in excludes: + excludes.append(pattern) + config.set_option('report:exclude_lines', excludes) + + +def coverage_init(reg, options): + reg.add_configurer(VersionGatedExcludes()) diff --git a/docs/features.rst b/docs/features.rst index 3d841aca..338de7d9 100644 --- a/docs/features.rst +++ b/docs/features.rst @@ -84,8 +84,10 @@ CityHash algorithm notes ~~~~~~~~~~~~~~~~~~~~~~~~ Unfortunately ClickHouse server comes with built-in old version of CityHash algorithm (1.0.2). -That's why we can't use original `CityHash `_ package. -An older version is published separately at `PyPI `_. +That's why we can't use the current `CityHash `_ package. +The matching 1.0.2 implementation is bundled with the driver (vendored from the +`clickhouse-cityhash `_ package), so +compression works out of the box without any extra dependency. Secure connection @@ -540,6 +542,153 @@ As you can see float column ``b`` in ``bad_df`` has two ``NaN`` values. But ``NaN`` and ``None`` is not the same for float point numbers. ``NaN`` is ``float('nan')`` where ``None`` is representing ``NULL``. +PyArrow support +--------------- + +*New in version 0.2.11.* + +Package can SELECT data as PyArrow objects. Additional packages are required +for :ref:`installation-pyarrow-support`. + +`query_arrow` returns the whole result as a ``pyarrow.Table``: + + .. code-block:: python + + >>> client = Client('localhost') + >>> table = client.query_arrow( + ... 'SELECT number AS x, toString(number) AS y ' + ... 'FROM system.numbers LIMIT 10000' + ... ) + >>> table + pyarrow.Table + x: uint64 + y: string + ... + +`query_arrow_stream` returns a ``pyarrow.RecordBatchReader`` that yields one +``pyarrow.RecordBatch`` per ClickHouse block, so arbitrarily large results +can be processed with constant memory usage: + + .. code-block:: python + + >>> client = Client('localhost') + >>> reader = client.query_arrow_stream( + ... 'SELECT number FROM system.numbers LIMIT 1000000' + ... ) + >>> for batch in reader: + ... process(batch) + +Block size can be controlled with the ``max_block_size`` setting: + + .. code-block:: python + + >>> reader = client.query_arrow_stream( + ... 'SELECT number FROM system.numbers LIMIT 1000000', + ... settings={'max_block_size': 100000} + ... ) + +The reader doesn't have to be consumed to the end: the streamed query +is cancelled when the next query starts. + +``NULL`` values in ``Nullable(T)`` columns are returned as proper Arrow +nulls (validity bitmap) and the column keeps its original type. For +example ``Nullable(Int64)`` is returned as a nullable ``int64`` Arrow +column, unlike pandas where such column is converted to ``object`` or +``float64`` dtype. + +ClickHouse types are mapped to Arrow types as follows: + + +--------------------------------+------------------------------------+ + | ClickHouse type | Arrow type | + +================================+====================================+ + | [U]Int8/16/32/64 | [u]int8/16/32/64 | + +--------------------------------+------------------------------------+ + | Float32/64 | float32/64 | + +--------------------------------+------------------------------------+ + | Bool | bool | + +--------------------------------+------------------------------------+ + | String/FixedString(N) | string (binary with | + | | ``strings_as_bytes``) | + +--------------------------------+------------------------------------+ + | Date/Date32 | date32 | + +--------------------------------+------------------------------------+ + | DateTime([tz]) | timestamp('s'[, tz]) | + +--------------------------------+------------------------------------+ + | DateTime64(P[, tz]) | timestamp(unit[, tz]) | + +--------------------------------+------------------------------------+ + | Decimal(P, S) | decimal128(P, S) | + +--------------------------------+------------------------------------+ + | Enum8/16 | string | + +--------------------------------+------------------------------------+ + | UUID | string | + +--------------------------------+------------------------------------+ + | IPv4/IPv6 | string | + +--------------------------------+------------------------------------+ + | LowCardinality(T) | same as T | + +--------------------------------+------------------------------------+ + | Nullable(T) | same as T with validity bitmap | + +--------------------------------+------------------------------------+ + | Array(T) | list | + +--------------------------------+------------------------------------+ + | Map(K, V) | map | + +--------------------------------+------------------------------------+ + +Values of other types are converted with Arrow's type inference on a +best-effort basis: their Arrow representation may change in future +versions. + +The default mapping can be overridden per column with ``arrow_types``. +For most types the declared Arrow type is used as the conversion +target: + + .. code-block:: python + + >>> client.query_arrow( + ... 'SELECT number FROM system.numbers LIMIT 10', + ... arrow_types={'number': pa.int32()} + ... ) + +``JSON`` columns have no default Arrow representation. +Declare ``pyarrow.string()`` to get JSON text. Text output requires +server-side JSON serialization with the +``output_format_native_write_json_as_string`` setting (ClickHouse +24.10 and newer): the text is passed through to Arrow without parsing. + + .. code-block:: python + + >>> client.query_arrow( + ... 'SELECT j FROM test', arrow_types={'j': pa.string()}, + ... settings={'output_format_native_write_json_as_string': 1} + ... ) + +Without the setting the query raises ``ValueError``: there is +deliberately no client-side serialization fallback, as it is an order +of magnitude slower. On servers without the setting transform the +column in the query instead: ``SELECT toJSONString(j)`` returns a +plain ``String`` column and needs no ``arrow_types`` at all. + +Alternatively declare a struct type for structured output. With a +declared struct, paths missing in a row become nulls, paths not +declared in the struct are dropped and paths of varying types raise +an error. Struct output works with or without the setting. + +The declared type is followed into nested containers: e.g. an +``Array(JSON)`` column declared as ``pa.list_(pa.string())`` yields +JSON text per array element. + +The original ClickHouse type of every column is attached to its Arrow +field as ``clickhouse_type`` metadata. + +Pass ``field_metadata=False`` to skip metadata generation. + +When the client is created with ``use_numpy=True`` (see +:ref:`installation-numpy-support`), columns are converted to Arrow +without copying where possible: numeric and datetime columns are passed +as NumPy arrays, ``String`` columns are read from the wire directly +into Arrow offset/data buffers without creating intermediate Python +strings. This is significantly faster than the plain client for most +column types. + Automatic disposal ------------------ diff --git a/docs/installation.rst b/docs/installation.rst index 9d5df0c0..ad89b504 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -44,11 +44,12 @@ Optional dependencies These distributions will not be installed automatically. Clickhouse-driver will detect and use them if you install them. -* `clickhouse-cityhash`_ provides CityHash algorithm of specific version, see :ref:`compression-cityhash-notes`. * `lz4`_ enables `LZ4/LZ4HC compression `_ support. * `zstd`_ enables `ZSTD compression `_ support. -.. _clickhouse-cityhash: https://pythonhosted.org/blinker/ +The CityHash algorithm used for compressed block checksums is bundled with the +driver, so no extra package is required, see :ref:`compression-cityhash-notes`. + .. _lz4: https://python-lz4.readthedocs.io/ .. _zstd: https://pypi.org/project/zstd/ @@ -93,6 +94,19 @@ You can install additional packages (NumPy and Pandas) if you need NumPy support NumPy supported versions are limited by ``numpy`` package python support. +.. _installation-pyarrow-support: + +PyArrow support +--------------- + +You can install additional PyArrow package if you need to query data as +``pyarrow.Table`` or ``pyarrow.RecordBatchReader``: + + .. code-block:: bash + + pip install clickhouse-driver[arrow] + + Installation from github ------------------------ diff --git a/docs/performance.rst b/docs/performance.rst index be240e48..b9fa3385 100644 --- a/docs/performance.rst +++ b/docs/performance.rst @@ -370,6 +370,28 @@ Iteration over int rows with ``clickhouse-connect`` (16) :language: python +PyArrow tables +^^^^^^^^^^^^^^ + +*New in version 0.2.11.* + +Get query result as PyArrow Table with ``clickhouse-driver`` in Native +format (18) + +.. literalinclude:: ../perf/script_18.py + :language: python + +The same with NumPy fast paths enabled (19) + +.. literalinclude:: ../perf/script_19.py + :language: python + +Get query result as PyArrow Table with ``clickhouse-connect`` (20) + +.. literalinclude:: ../perf/script_20.py + :language: python + + Results ------- diff --git a/docs/types.rst b/docs/types.rst index e4ab287f..475f2351 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -500,3 +500,18 @@ SELECT type: :class:`dict`, :class:`str`. json during ``INSERT``. Set ``allow_experimental_object_type=1`` for to enable json support. + +JSON +-------------- + +*New in version 0.2.11.* + +INSERT types: :class:`dict`, :class:`str` (JSON text). + +SELECT type: :class:`dict`, :class:`str`. + +Set ``enable_json_type=1`` for to enable json support. + +``JSON`` columns nested in container columns, e.g. ``Array(JSON)``, +``Tuple(String, JSON)``, ``Map(String, JSON)`` and their compositions, can +be written and read as well. diff --git a/perf/script_18.py b/perf/script_18.py new file mode 100644 index 00000000..f8b5770c --- /dev/null +++ b/perf/script_18.py @@ -0,0 +1,12 @@ +# /// script +# dependencies = [ +# "clickhouse-driver[arrow]", +# ] +# /// +import sys +from clickhouse_driver import Client + +query = "SELECT * FROM perftest.ontime WHERE FlightDate < '{}'".format(sys.argv[1]) +client = Client('localhost') + +table = client.query_arrow(query) diff --git a/perf/script_19.py b/perf/script_19.py new file mode 100644 index 00000000..cc0a684f --- /dev/null +++ b/perf/script_19.py @@ -0,0 +1,12 @@ +# /// script +# dependencies = [ +# "clickhouse-driver[arrow,numpy]", +# ] +# /// +import sys +from clickhouse_driver import Client + +query = "SELECT * FROM perftest.ontime WHERE FlightDate < '{}'".format(sys.argv[1]) +client = Client('localhost', settings={'use_numpy': True}) + +table = client.query_arrow(query) diff --git a/perf/script_20.py b/perf/script_20.py new file mode 100644 index 00000000..df253ce1 --- /dev/null +++ b/perf/script_20.py @@ -0,0 +1,13 @@ +# /// script +# dependencies = [ +# "clickhouse-connect", +# "pyarrow", +# ] +# /// +import sys +import clickhouse_connect + +query = "SELECT * FROM perftest.ontime WHERE FlightDate < '{}'".format(sys.argv[1]) +client = clickhouse_connect.get_client(host='localhost', query_limit=None, compress=False) + +table = client.query_arrow(query, settings={'output_format_arrow_string_as_string': 1}) diff --git a/setup.py b/setup.py index b9526f42..d90ca77e 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,6 @@ import os import re +import sys from codecs import open from setuptools import setup, find_packages @@ -55,6 +56,31 @@ def read_version(): ) ] +# Vendored CityHash 1.0.2 (used for block checksums). This is a C++ extension, +# so it uses a .cpp fallback instead of the .c one the pure-C modules use. +# Built unconditionally; a C++ compiler is required to build from source. +cityhash_dir = 'clickhouse_driver/_cityhash' +cityhash_ext = '.pyx' if USE_CYTHON else '.cpp' +cityhash_compile_args = [] +if sys.platform != 'win32': + # We only need CityHash128, so SSE4.2 (-msse4.2) is intentionally omitted. + cityhash_compile_args = [ + '-O3', '-Wno-unused-value', '-Wno-unused-function' + ] + +extensions.append( + Extension( + 'clickhouse_driver._cityhash.cityhash', + [ + cityhash_dir + '/cityhash' + cityhash_ext, + cityhash_dir + '/city.cc', + ], + language='c++', + include_dirs=[cityhash_dir], + extra_compile_args=cityhash_compile_args, + ) +) + if USE_CYTHON: compiler_directives = {'language_level': '3'} if CYTHON_TRACE: @@ -129,11 +155,11 @@ def read_version(): extras_require={ 'lz4': [ 'lz4<=3.0.1; implementation_name=="pypy"', - 'lz4; implementation_name!="pypy"', - 'clickhouse-cityhash>=1.0.2.1' + 'lz4; implementation_name!="pypy"' ], - 'zstd': ['zstd', 'clickhouse-cityhash>=1.0.2.1'], - 'numpy': ['numpy>=1.12.0', 'pandas>=0.24.0'] + 'zstd': ['zstd'], + 'numpy': ['numpy>=1.12.0', 'pandas>=0.24.0'], + 'arrow': ['pyarrow>=8.0.0'] }, test_suite='pytest' ) diff --git a/tests/arrow/__init__.py b/tests/arrow/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/arrow/test_generic.py b/tests/arrow/test_generic.py new file mode 100644 index 00000000..36216c67 --- /dev/null +++ b/tests/arrow/test_generic.py @@ -0,0 +1,332 @@ +try: + import pyarrow as pa +except ImportError: + pa = None + +from clickhouse_driver import errors +from tests.testcase import BaseTestCase +from tests.arrow.testcase import ArrowBaseTestCase + + +class QueryArrowTestCase(ArrowBaseTestCase): + def test_simple(self): + table = self.client.query_arrow( + 'SELECT number FROM system.numbers LIMIT 100' + ) + + self.assertIsInstance(table, pa.Table) + self.assertEqual(table.num_rows, 100) + self.assertEqual(table.column_names, ['number']) + self.assertEqual(table.schema.field('number').type, pa.uint64()) + self.assertEqual(table.column('number').to_pylist(), list(range(100))) + + def test_column_names_preserved(self): + table = self.client.query_arrow('SELECT 1 AS "my col"') + + self.assertEqual(table.column_names, ['my col']) + + def test_multiple_columns(self): + table = self.client.query_arrow( + 'SELECT ' + 'CAST(number AS Int32) AS x, ' + 'toString(number) AS y ' + 'FROM system.numbers LIMIT 3' + ) + + self.assertEqual(table.column_names, ['x', 'y']) + self.assertEqual(table.column('x').to_pylist(), [0, 1, 2]) + self.assertEqual(table.column('y').to_pylist(), ['0', '1', '2']) + + def test_empty_result_keeps_schema(self): + table = self.client.query_arrow( + 'SELECT CAST(number AS Int32) AS x, toString(number) AS y ' + 'FROM system.numbers LIMIT 0' + ) + + self.assertEqual(table.num_rows, 0) + self.assertEqual(table.schema.field('x').type, pa.int32()) + self.assertEqual(table.schema.field('y').type, pa.string()) + + def test_params_substitution(self): + table = self.client.query_arrow( + 'SELECT CAST(%(x)s AS Int64) AS x', params={'x': 42} + ) + + self.assertEqual(table.column('x').to_pylist(), [42]) + + def test_settings(self): + table = self.client.query_arrow( + 'SELECT number FROM system.numbers LIMIT 1000', + settings={'max_block_size': 100} + ) + + self.assertEqual(table.num_rows, 1000) + + def test_external_tables(self): + table = self.client.query_arrow( + 'SELECT * FROM ext ORDER BY x', + external_tables=[{ + 'name': 'ext', + 'structure': [('x', 'Int32')], + 'data': [{'x': 1}, {'x': 2}] + }] + ) + + self.assertEqual(table.column('x').to_pylist(), [1, 2]) + + def test_field_metadata(self): + table = self.client.query_arrow( + 'SELECT CAST(1 AS Nullable(Int32)) AS x, ' + 'toLowCardinality(toString(1)) AS lc' + ) + + self.assertEqual( + table.schema.field('x').metadata, + {b'clickhouse_type': b'Nullable(Int32)'} + ) + self.assertEqual( + table.schema.field('lc').metadata, + {b'clickhouse_type': b'LowCardinality(String)'} + ) + + def test_field_metadata_opt_out(self): + table = self.client.query_arrow( + 'SELECT 1 AS x', field_metadata=False + ) + + self.assertIsNone(table.schema.field('x').metadata) + + def test_several_blocks_concatenated(self): + table = self.client.query_arrow( + 'SELECT number FROM system.numbers LIMIT 1000', + settings={'max_block_size': 100} + ) + + self.assertEqual(table.column('number').to_pylist(), + list(range(1000))) + + +class QueryArrowStreamTestCase(ArrowBaseTestCase): + def test_returns_record_batch_reader(self): + reader = self.client.query_arrow_stream( + 'SELECT number FROM system.numbers LIMIT 10' + ) + + self.assertIsInstance(reader, pa.RecordBatchReader) + reader.close() + + def test_schema_available_before_consumption(self): + reader = self.client.query_arrow_stream( + 'SELECT CAST(number AS Int32) AS x ' + 'FROM system.numbers LIMIT 10' + ) + + self.assertEqual(reader.schema.field('x').type, pa.int32()) + reader.close() + + def test_stream_field_metadata(self): + reader = self.client.query_arrow_stream( + 'SELECT number FROM system.numbers LIMIT 10' + ) + + self.assertEqual( + reader.schema.field('number').metadata, + {b'clickhouse_type': b'UInt64'} + ) + reader.read_all() + + def test_multiple_batches(self): + reader = self.client.query_arrow_stream( + 'SELECT number FROM system.numbers LIMIT 1000', + settings={'max_block_size': 100} + ) + + batches = list(reader) + self.assertGreater(len(batches), 1) + for batch in batches: + self.assertIsInstance(batch, pa.RecordBatch) + + total_rows = sum(batch.num_rows for batch in batches) + self.assertEqual(total_rows, 1000) + + def test_read_all_equals_query_arrow(self): + query = ('SELECT number, toString(number) AS s ' + 'FROM system.numbers LIMIT 1000') + settings = {'max_block_size': 100} + + reader = self.client.query_arrow_stream(query, settings=settings) + streamed = reader.read_all() + + table = self.client.query_arrow(query, settings=settings) + self.assertTrue(streamed.equals(table)) + + def test_empty_result(self): + reader = self.client.query_arrow_stream( + 'SELECT CAST(number AS Int32) AS x FROM system.numbers LIMIT 0' + ) + + table = reader.read_all() + self.assertEqual(table.num_rows, 0) + self.assertEqual(table.schema.field('x').type, pa.int32()) + + def test_client_usable_after_stream_consumed(self): + reader = self.client.query_arrow_stream( + 'SELECT number FROM system.numbers LIMIT 10' + ) + reader.read_all() + + rv = self.client.execute('SELECT 1') + self.assertEqual(rv, [(1, )]) + + def test_client_usable_after_close_before_consuming(self): + reader = self.client.query_arrow_stream( + 'SELECT number FROM system.numbers LIMIT 100000', + settings={'max_block_size': 100} + ) + reader.close() + + rv = self.client.execute('SELECT 1') + self.assertEqual(rv, [(1, )]) + + def test_client_usable_after_close_after_one_batch(self): + reader = self.client.query_arrow_stream( + 'SELECT number FROM system.numbers LIMIT 100000', + settings={'max_block_size': 100} + ) + batch = reader.read_next_batch() + self.assertEqual(batch.num_rows, 100) + reader.close() + + rv = self.client.execute('SELECT 1') + self.assertEqual(rv, [(1, )]) + + def test_arrow_query_after_close_after_one_batch(self): + reader = self.client.query_arrow_stream( + 'SELECT number FROM system.numbers LIMIT 100000', + settings={'max_block_size': 100} + ) + reader.read_next_batch() + reader.close() + + table = self.client.query_arrow( + 'SELECT number FROM system.numbers LIMIT 10' + ) + self.assertEqual(table.column('number').to_pylist(), list(range(10))) + + def test_abandoned_reader_raises_after_next_query(self): + reader = self.client.query_arrow_stream( + 'SELECT number FROM system.numbers LIMIT 100000', + settings={'max_block_size': 100} + ) + reader.read_next_batch() + + self.client.execute('SELECT 1') + + # The streamed query was cancelled by the query above: reading + # further must fail loudly instead of consuming its packets. + with self.assertRaises(errors.PartiallyConsumedQueryError): + reader.read_all() + + +class ArrowNumpyPathTestCase(ArrowBaseTestCase): + """ + query_arrow must return identical results with and without + use_numpy fast path. + """ + + def setUp(self): + super(ArrowNumpyPathTestCase, self).setUp() + + try: + import numpy # noqa: F401 + import pandas # noqa: F401 + except ImportError: + self.skipTest('NumPy package is not installed') + + def test_results_equal_with_use_numpy(self): + query = ( + 'SELECT ' + 'CAST(number AS Int64) AS x, ' + 'toString(number) AS y, ' + 'CAST(number AS Float64) / 3 AS z, ' + "toDateTime(number, 'UTC') AS dt, " + "toDateTime64(number + 0.123, 3, 'UTC') AS dt64, " + 'toLowCardinality(toString(number % 3)) AS lc ' + 'FROM system.numbers LIMIT 1000' + ) + + table = self.client.query_arrow(query) + + with self.created_client(settings={'use_numpy': True}) as client: + numpy_table = client.query_arrow(query) + + self.assertTrue(table.equals(numpy_table)) + + def test_long_strings_equal_with_use_numpy(self): + # Strings longer than the reader buffer exercise the + # buffer-spanning path of the Arrow string reader. + query = ( + "SELECT concat('привет', repeat('x', 1000000), " + "repeat('y', 1000000), toString(number)) AS s " + 'FROM system.numbers LIMIT 3' + ) + + table = self.client.query_arrow(query) + + with self.created_client(settings={'use_numpy': True}) as client: + numpy_table = client.query_arrow(query) + + self.assertTrue(table.equals(numpy_table)) + + def test_nullable_results_equal_with_use_numpy(self): + query = ( + 'SELECT ' + 'CAST(if(number % 2 = 0, NULL, number) AS Nullable(Int64)) ' + 'AS x, ' + 'CAST(if(number % 3 = 0, NULL, number / 7) ' + 'AS Nullable(Float64)) AS f, ' + 'CAST(if(number % 4 = 0, NULL, toString(number)) ' + 'AS Nullable(String)) AS s, ' + 'CAST(if(number % 6 = 0, NULL, toString(number % 10)) ' + 'AS Nullable(FixedString(2))) AS fs, ' + "CAST(if(number % 5 = 0, NULL, toDateTime(number, 'UTC')) " + "AS Nullable(DateTime('UTC'))) AS dt " + 'FROM system.numbers LIMIT 10' + ) + + table = self.client.query_arrow(query) + + with self.created_client(settings={'use_numpy': True}) as client: + numpy_table = client.query_arrow(query) + + self.assertTrue(table.equals(numpy_table)) + self.assertEqual(table.column('x').null_count, 5) + + +class NoPyArrowTestCase(BaseTestCase): + def setUp(self): + super(NoPyArrowTestCase, self).setUp() + + try: + import pyarrow # noqa: F401 + except ImportError: + pass + + else: + self.skipTest('PyArrow extras are installed') + + def test_query_arrow(self): + with self.assertRaises(RuntimeError) as e: + self.client.query_arrow('SELECT 1 AS x') + + self.assertEqual( + 'Extras for PyArrow must be installed', str(e.exception) + ) + + def test_query_arrow_stream(self): + with self.assertRaises(RuntimeError) as e: + self.client.query_arrow_stream('SELECT 1 AS x') + + self.assertEqual( + 'Extras for PyArrow must be installed', str(e.exception) + ) diff --git a/tests/arrow/test_mapping.py b/tests/arrow/test_mapping.py new file mode 100644 index 00000000..af709497 --- /dev/null +++ b/tests/arrow/test_mapping.py @@ -0,0 +1,113 @@ +from unittest import TestCase +from uuid import UUID + +from clickhouse_driver.context import Context + +try: + import pyarrow as pa + + from clickhouse_driver.arrow import mapping + from clickhouse_driver.arrow.convert import ( + ArrowStreamState, _json_declared_converter, + create_record_batch_reader + ) +except ImportError: + pa = None + mapping = None + + +class MappingTestCase(TestCase): + """ + Unit tests for the spec -> Arrow type mapping. No server needed. + """ + + def setUp(self): + if pa is None: + self.skipTest('PyArrow package is not installed') + + def get(self, spec, **kwargs): + return mapping.get_type_and_converter(spec, **kwargs) + + def test_object_json_unsupported(self): + # Legacy JSON type: only served by pre-25 servers. + type_, _ = self.get("Object('json')") + self.assertIs(type_, mapping.UNSUPPORTED) + + def test_decimal_prefixed_specs(self): + self.assertEqual(self.get('Decimal32(2)')[0], pa.decimal128(9, 2)) + self.assertEqual(self.get('Decimal64(4)')[0], pa.decimal128(18, 4)) + self.assertEqual(self.get('Decimal128(6)')[0], pa.decimal128(38, 6)) + self.assertEqual(self.get('Decimal256(8)')[0], pa.decimal256(76, 8)) + + def test_unknown_decimal_prefix_falls_back_to_inference(self): + self.assertEqual(self.get('Decimal512(2)'), (None, None)) + + def test_decimal_high_precision_is_decimal256(self): + self.assertEqual(self.get('Decimal(76, 10)')[0], + pa.decimal256(76, 10)) + + def test_datetime64_units(self): + self.assertEqual(self.get('DateTime64(0)')[0], pa.timestamp('s')) + self.assertEqual(self.get('DateTime64(9)')[0], pa.timestamp('ns')) + + def test_tuple_without_json_falls_back_to_inference(self): + self.assertEqual(self.get('Tuple(UInt8, String)'), (None, None)) + + def test_unknown_spec_falls_back_to_inference(self): + self.assertEqual(self.get('Int128'), (None, None)) + + def test_simple_aggregate_function_unwraps(self): + type_, converter = self.get('SimpleAggregateFunction(anyLast, Int64)') + self.assertEqual(type_, pa.int64()) + self.assertIsNone(converter) + + def test_array_of_uuid_converter(self): + type_, converter = self.get('Array(UUID)') + self.assertEqual(type_, pa.list_(pa.string())) + + uid = UUID('c0fcbba9-0752-44ed-a5d6-4dfb4342b89d') + self.assertEqual(converter([uid, None]), [str(uid), None]) + + def test_map_with_value_converter(self): + type_, converter = self.get('Map(String, UUID)') + self.assertEqual(type_, pa.map_(pa.string(), pa.string())) + + uid = UUID('c0fcbba9-0752-44ed-a5d6-4dfb4342b89d') + self.assertEqual(converter({'k': uid}), [('k', str(uid))]) + + def test_json_as_object_parses_wire_strings(self): + self.assertEqual(mapping.json_as_object('{"a": 1}'), {'a': 1}) + self.assertEqual(mapping.json_as_object(''), {}) + self.assertEqual(mapping.json_as_object({'a': 1}), {'a': 1}) + + +class ConvertTestCase(TestCase): + """ + Unit tests for reader creation edge cases. No server needed. + """ + + def setUp(self): + if pa is None: + self.skipTest('PyArrow package is not installed') + + def make_context(self): + context = Context() + context.client_settings = {'strings_as_bytes': False} + return context + + def test_empty_packet_stream(self): + state = ArrowStreamState(connection=None) + reader = create_record_batch_reader( + iter([]), self.make_context(), state=state + ) + + self.assertEqual(reader.read_all().num_rows, 0) + self.assertTrue(state.finished) + + def test_declared_converter_none_for_json_free_containers(self): + self.assertIsNone(_json_declared_converter( + 'Array(Int32)', pa.list_(pa.int32()), 'x' + )) + self.assertIsNone(_json_declared_converter( + 'Map(String, Int32)', pa.map_(pa.string(), pa.int32()), 'x' + )) diff --git a/tests/arrow/test_types.py b/tests/arrow/test_types.py new file mode 100644 index 00000000..4cbc461b --- /dev/null +++ b/tests/arrow/test_types.py @@ -0,0 +1,603 @@ +import json +from datetime import date, datetime, timezone +from decimal import Decimal +from uuid import UUID + +try: + import pyarrow as pa +except ImportError: + pa = None + +from tests.arrow.testcase import ArrowBaseTestCase +from tests.util import require_server_version + + +class IntTestCase(ArrowBaseTestCase): + def test_int8(self): + self.assert_arrow_column('Int8', pa.int8(), [-128, 0, 127]) + + def test_int16(self): + self.assert_arrow_column('Int16', pa.int16(), [-32768, 0, 32767]) + + def test_int32(self): + self.assert_arrow_column( + 'Int32', pa.int32(), [-2147483648, 0, 2147483647] + ) + + def test_int64(self): + self.assert_arrow_column( + 'Int64', pa.int64(), [-9223372036854775808, 0, + 9223372036854775807] + ) + + def test_uint8(self): + self.assert_arrow_column('UInt8', pa.uint8(), [0, 255]) + + def test_uint16(self): + self.assert_arrow_column('UInt16', pa.uint16(), [0, 65535]) + + def test_uint32(self): + self.assert_arrow_column('UInt32', pa.uint32(), [0, 4294967295]) + + def test_uint64(self): + self.assert_arrow_column( + 'UInt64', pa.uint64(), [0, 18446744073709551615] + ) + + +class FloatTestCase(ArrowBaseTestCase): + def test_float32(self): + self.assert_arrow_column('Float32', pa.float32(), [-0.5, 0.0, 0.5]) + + def test_float64(self): + self.assert_arrow_column('Float64', pa.float64(), [-1.5, 0.0, 1.5]) + + +class BoolTestCase(ArrowBaseTestCase): + required_server_version = (21, 12) + + def test_bool(self): + self.assert_arrow_column('Bool', pa.bool_(), [True, False]) + + +class StringTestCase(ArrowBaseTestCase): + def test_string(self): + self.assert_arrow_column('String', pa.string(), ['a', 'b', 'привет']) + + def test_fixed_string(self): + self.assert_arrow_column('FixedString(3)', pa.string(), ['abc', + 'def']) + + def test_strings_as_bytes(self): + with self.create_table('a String'): + self.client.execute( + 'INSERT INTO test (a) VALUES', [(b'ab', ), (b'cd', )] + ) + + with self.created_client( + settings={'strings_as_bytes': True}) as client: + table = client.query_arrow('SELECT a FROM test') + + self.assertEqual(table.schema.field('a').type, pa.binary()) + self.assertEqual(table.column('a').to_pylist(), [b'ab', b'cd']) + + def test_strings_as_bytes_with_numpy(self): + try: + import numpy # noqa: F401 + import pandas # noqa: F401 + except ImportError: + self.skipTest('NumPy package is not installed') + + with self.create_table('a String'): + self.client.execute( + 'INSERT INTO test (a) VALUES', [(b'ab', ), (b'cd', )] + ) + + with self.created_client( + settings={'strings_as_bytes': True, + 'use_numpy': True}) as client: + table = client.query_arrow('SELECT a FROM test') + + self.assertEqual(table.schema.field('a').type, pa.binary()) + self.assertEqual(table.column('a').to_pylist(), [b'ab', b'cd']) + + +class NullableTestCase(ArrowBaseTestCase): + def test_nullable_int(self): + self.assert_arrow_column( + 'Nullable(Int32)', pa.int32(), [1, None, 3] + ) + + def test_nullable_float(self): + self.assert_arrow_column( + 'Nullable(Float64)', pa.float64(), [1.5, None, 3.5] + ) + + def test_nullable_string(self): + self.assert_arrow_column( + 'Nullable(String)', pa.string(), ['a', None, 'c'] + ) + + def test_null_count(self): + with self.create_table('a Nullable(Int64)'): + self.client.execute( + 'INSERT INTO test (a) VALUES', + [(1, ), (None, ), (None, ), (4, )] + ) + table = self.client.query_arrow('SELECT a FROM test') + + self.assertEqual(table.column('a').null_count, 2) + + def test_all_null(self): + self.assert_arrow_column( + 'Nullable(Int32)', pa.int32(), [None, None] + ) + + +class DateTestCase(ArrowBaseTestCase): + def test_date(self): + self.assert_arrow_column( + 'Date', pa.date32(), [date(1970, 1, 2), date(2024, 2, 29)] + ) + + +class Date32TestCase(ArrowBaseTestCase): + required_server_version = (21, 9) + + def test_date32(self): + self.assert_arrow_column( + 'Date32', pa.date32(), [date(1925, 1, 2), date(2024, 2, 29)] + ) + + +class DateTimeTestCase(ArrowBaseTestCase): + def test_datetime_with_timezone(self): + self.assert_arrow_column( + "DateTime('UTC')", pa.timestamp('s', tz='UTC'), + [ + datetime(2024, 1, 1, 12, 30, 45, tzinfo=timezone.utc), + datetime(1970, 1, 2, 0, 0, 1, tzinfo=timezone.utc) + ] + ) + + def test_datetime_naive(self): + # Expected values are taken from plain execute to stay + # independent of local/server timezone conversions. + with self.create_table('a DateTime'): + self.client.execute( + 'INSERT INTO test (a) VALUES', + [(datetime(2024, 1, 1, 12, 30, 45), )] + ) + table = self.client.query_arrow('SELECT a FROM test') + expected = [x[0] for x in self.client.execute( + 'SELECT a FROM test' + )] + + self.assertEqual(table.schema.field('a').type, pa.timestamp('s')) + self.assertEqual(table.column('a').to_pylist(), expected) + + +class DateTime64TestCase(ArrowBaseTestCase): + required_server_version = (20, 1, 2) + + def test_datetime64_millisecond(self): + self.assert_arrow_column( + "DateTime64(3, 'UTC')", pa.timestamp('ms', tz='UTC'), + [datetime(2024, 1, 1, 12, 30, 45, 123000, tzinfo=timezone.utc)] + ) + + def test_datetime64_microsecond(self): + self.assert_arrow_column( + "DateTime64(6, 'UTC')", pa.timestamp('us', tz='UTC'), + [datetime(2024, 1, 1, 12, 30, 45, 123456, tzinfo=timezone.utc)] + ) + + +class DecimalTestCase(ArrowBaseTestCase): + required_server_version = (18, 12, 13) + + def test_decimal(self): + self.assert_arrow_column( + 'Decimal(9, 5)', pa.decimal128(9, 5), + [Decimal('123.45678'), Decimal('-123.45678')] + ) + + def test_decimal_high_precision(self): + self.assert_arrow_column( + 'Decimal(38, 10)', pa.decimal128(38, 10), + [Decimal('1234567890.1234567890')] + ) + + +class EnumTestCase(ArrowBaseTestCase): + def test_enum8(self): + self.assert_arrow_column( + "Enum8('hello' = 1, 'world' = 2)", pa.string(), + ['hello', 'world'] + ) + + def test_enum16(self): + self.assert_arrow_column( + "Enum16('hello' = 1000, 'world' = 2000)", pa.string(), + ['hello', 'world'] + ) + + +class UUIDTestCase(ArrowBaseTestCase): + def test_uuid(self): + self.assert_arrow_column( + 'UUID', pa.string(), + [UUID('c0fcbba9-0752-44ed-a5d6-4dfb4342b89d')], + expected=['c0fcbba9-0752-44ed-a5d6-4dfb4342b89d'] + ) + + +class IPTestCase(ArrowBaseTestCase): + required_server_version = (19, 3, 3) + + def test_ipv4(self): + self.assert_arrow_column( + 'IPv4', pa.string(), ['10.0.0.1', '192.168.1.1'] + ) + + def test_ipv6(self): + self.assert_arrow_column( + 'IPv6', pa.string(), ['2001:db8::1', '::1'] + ) + + +class LowCardinalityTestCase(ArrowBaseTestCase): + required_server_version = (19, 3, 3) + + def test_low_cardinality_string(self): + self.assert_arrow_column( + 'LowCardinality(String)', pa.string(), ['yes', 'no', 'yes'] + ) + + def test_low_cardinality_nullable_string(self): + self.assert_arrow_column( + 'LowCardinality(Nullable(String))', pa.string(), + ['yes', None, 'yes'] + ) + + +class ArrayTestCase(ArrowBaseTestCase): + def test_array_of_ints(self): + self.assert_arrow_column( + 'Array(UInt64)', pa.list_(pa.uint64()), + [[1, 2, 3], [], [4]] + ) + + def test_array_of_strings(self): + self.assert_arrow_column( + 'Array(String)', pa.list_(pa.string()), + [['a', 'b'], []] + ) + + def test_array_of_nullable(self): + self.assert_arrow_column( + 'Array(Nullable(Int32))', pa.list_(pa.int32()), + [[1, None], [3]] + ) + + def test_nested_arrays(self): + self.assert_arrow_column( + 'Array(Array(Int32))', pa.list_(pa.list_(pa.int32())), + [[[1, 2], [3]], [[]]] + ) + + +class JSONTestCase(ArrowBaseTestCase): + required_server_version = (24, 8, 0) + + def client_kwargs(self, version): + return {'settings': {'enable_json_type': True}} + + def cli_client_kwargs(self): + return {'enable_json_type': 1} + + def test_json_requires_arrow_types(self): + with self.create_table('a JSON'): + self.client.execute( + 'INSERT INTO test (a) VALUES', [({'k': 1}, )] + ) + with self.assertRaises(ValueError) as e: + self.client.query_arrow('SELECT a FROM test') + + self.assertIn('arrow_types', str(e.exception)) + # client is not broken by the rejected query + self.assertEqual(self.client.execute('SELECT 1'), [(1, )]) + + @require_server_version(24, 10) + def test_json_as_text(self): + # Memory engine returns blocks in nondeterministic order: + # an explicit ordering key is required. + with self.create_table('i UInt8, a JSON'): + self.client.execute( + 'INSERT INTO test (i, a) VALUES', + [(1, {'k': 1, 's': 'x'}), (2, {})] + ) + self.client.execute( + 'INSERT INTO test (i, a) VALUES', [(3, {'b': 'y'})] + ) + table = self.client.query_arrow( + 'SELECT a FROM test ORDER BY i', + arrow_types={'a': pa.string()}, + settings={ + 'output_format_native_write_json_as_string': 1, + # default differs across server versions + 'output_format_json_quote_64bit_integers': 0 + } + ) + + self.assertEqual(table.schema.field('a').type, pa.string()) + values = [json.loads(x) for x in table.column('a').to_pylist()] + self.assertEqual(values, [{'k': 1, 's': 'x'}, {}, {'b': 'y'}]) + + def test_json_as_text_without_server_serialization_raises(self): + # Client-side JSON serialization is deliberately not provided: + # it would be an order of magnitude slower than the server-side one. + with self.create_table('a JSON'): + self.client.execute( + 'INSERT INTO test (a) VALUES', [({'k': 1}, )] + ) + + with self.assertRaises(ValueError) as e: + self.client.query_arrow( + 'SELECT a FROM test', arrow_types={'a': pa.string()} + ) + + self.assertIn( + 'output_format_native_write_json_as_string', + str(e.exception) + ) + # raised mid-stream, after the reader was created: + # client must survive + self.assertEqual(self.client.execute('SELECT 1'), [(1, )]) + + def test_json_as_text_without_server_serialization_raises_stream(self): + with self.create_table('a JSON'): + self.client.execute( + 'INSERT INTO test (a) VALUES', [({'k': 1}, )] + ) + + reader = self.client.query_arrow_stream( + 'SELECT a FROM test', arrow_types={'a': pa.string()} + ) + with self.assertRaises(ValueError): + reader.read_all() + + self.assertEqual(self.client.execute('SELECT 1'), [(1, )]) + + @require_server_version(24, 10) + def test_json_as_struct_string_wire_format(self): + # Struct declaration must work whichever wire format arrives: + # with string serialization values are parsed on the client. + struct = pa.struct([('k', pa.int64())]) + + with self.create_table('a JSON'): + self.client.execute( + 'INSERT INTO test (a) VALUES', [({'k': 1}, )] + ) + table = self.client.query_arrow( + 'SELECT a FROM test', arrow_types={'a': struct}, + settings={ + 'output_format_native_write_json_as_string': 1, + # default differs across server versions + 'output_format_json_quote_64bit_integers': 0 + } + ) + + self.assertEqual(table.column('a').to_pylist(), [{'k': 1}]) + + def test_json_as_struct(self): + struct = pa.struct([('k', pa.int64()), ('s', pa.string())]) + + with self.create_table('i UInt8, a JSON'): + self.client.execute( + 'INSERT INTO test (i, a) VALUES', [(1, {'k': 1, 's': 'x'})] + ) + # declared schema contract: missing paths are null-filled + self.client.execute( + 'INSERT INTO test (i, a) VALUES', [(2, {'k': 2})] + ) + table = self.client.query_arrow( + 'SELECT a FROM test ORDER BY i', arrow_types={'a': struct} + ) + + self.assertEqual(table.schema.field('a').type, struct) + self.assertEqual(table.column('a').to_pylist(), [ + {'k': 1, 's': 'x'}, + {'k': 2, 's': None}, + ]) + + +class NestedJSONTestCase(ArrowBaseTestCase): + required_server_version = (24, 8, 0) + + def client_kwargs(self, version): + return {'settings': {'enable_json_type': True, + 'flatten_nested': 0}} + + def cli_client_kwargs(self): + return {'enable_json_type': 1, 'flatten_nested': 0} + + def test_array_json_requires_arrow_types(self): + with self.create_table('a Array(JSON)'): + with self.assertRaises(ValueError) as e: + self.client.query_arrow('SELECT a FROM test') + + self.assertIn('arrow_types', str(e.exception)) + + @require_server_version(24, 10) + def test_array_json_as_text_elements(self): + with self.create_table('a Array(JSON)'): + # nested JSON inserts are not supported by the driver: + # insert via CLI + self.emit_cli( + 'INSERT INTO test VALUES ' + '([CAST(\'{"k":1}\' AS JSON), ' + 'CAST(\'{"b":"x"}\' AS JSON)])', + enable_json_type=1 + ) + table = self.client.query_arrow( + 'SELECT a FROM test', + arrow_types={'a': pa.list_(pa.string())}, + settings={ + 'output_format_native_write_json_as_string': 1, + # default differs across server versions + 'output_format_json_quote_64bit_integers': 0 + } + ) + + values = [ + [json.loads(x) for x in row] + for row in table.column('a').to_pylist() + ] + self.assertEqual(values, [[{'k': 1}, {'b': 'x'}]]) + + @require_server_version(24, 10) + def test_nullable_json_as_text(self): + with self.create_table('i UInt8, a Nullable(JSON)'): + self.client.execute( + 'INSERT INTO test (i, a) VALUES', + [(1, {'k': 1}), (2, None)] + ) + table = self.client.query_arrow( + 'SELECT a FROM test ORDER BY i', + arrow_types={'a': pa.string()}, + settings={ + 'output_format_native_write_json_as_string': 1, + # default differs across server versions + 'output_format_json_quote_64bit_integers': 0 + } + ) + + values = [ + json.loads(x) if x is not None else None + for x in table.column('a').to_pylist() + ] + self.assertEqual(values, [{'k': 1}, None]) + + @require_server_version(24, 10) + def test_map_json_as_text_values(self): + with self.create_table('a Map(String, JSON)'): + self.emit_cli( + 'INSERT INTO test VALUES ' + '(map(\'k\', CAST(\'{"n":1}\' AS JSON)))', + enable_json_type=1 + ) + table = self.client.query_arrow( + 'SELECT a FROM test', + arrow_types={'a': pa.map_(pa.string(), pa.string())}, + settings={ + 'output_format_native_write_json_as_string': 1, + # default differs across server versions + 'output_format_json_quote_64bit_integers': 0 + } + ) + + values = [ + [(k, json.loads(v)) for k, v in row] + for row in table.column('a').to_pylist() + ] + self.assertEqual(values, [[('k', {'n': 1})]]) + + def test_nested_json_requires_arrow_types(self): + with self.create_table('a Nested(j JSON, n UInt8)'): + self.emit_cli( + 'INSERT INTO test VALUES ' + '([(CAST(\'{"k":1}\' AS JSON), 7)])', + enable_json_type=1, flatten_nested=0 + ) + with self.assertRaises(ValueError) as e: + self.client.query_arrow('SELECT a FROM test') + + self.assertIn('arrow_types', str(e.exception)) + + def test_tuple_json_requires_arrow_types(self): + # Tuple has no explicit mapping, but JSON inside it must not + # leak into type inference. + with self.create_table('a Tuple(JSON, UInt8)'): + self.client.execute( + 'INSERT INTO test (a) VALUES', [(({'k': 1}, 7), )] + ) + with self.assertRaises(ValueError) as e: + self.client.query_arrow('SELECT a FROM test') + + self.assertIn('arrow_types', str(e.exception)) + + +class InferenceTestCase(ArrowBaseTestCase): + # Int128 has no explicit mapping: Arrow type is inferred from the + # first non-empty block. + required_server_version = (21, 6) + + def test_unmapped_type_inferred_from_data(self): + table = self.client.query_arrow( + 'SELECT CAST(number AS Int128) AS x ' + 'FROM system.numbers LIMIT 3' + ) + + self.assertEqual(table.schema.field('x').type, pa.int64()) + self.assertEqual(table.column('x').to_pylist(), [0, 1, 2]) + + def test_unmapped_type_empty_result(self): + table = self.client.query_arrow( + 'SELECT CAST(number AS Int128) AS x ' + 'FROM system.numbers LIMIT 0' + ) + + self.assertEqual(table.num_rows, 0) + self.assertEqual(table.schema.field('x').type, pa.null()) + + +class ArrowTypesOverrideTestCase(ArrowBaseTestCase): + def test_general_type_override(self): + table = self.client.query_arrow( + 'SELECT CAST(number AS Int64) AS x ' + 'FROM system.numbers LIMIT 3', + arrow_types={'x': pa.int32()} + ) + + self.assertEqual(table.schema.field('x').type, pa.int32()) + self.assertEqual(table.column('x').to_pylist(), [0, 1, 2]) + + def test_stream_schema_uses_declared_type(self): + reader = self.client.query_arrow_stream( + 'SELECT CAST(number AS Int64) AS x ' + 'FROM system.numbers LIMIT 3', + arrow_types={'x': pa.float64()} + ) + + self.assertEqual(reader.schema.field('x').type, pa.float64()) + reader.read_all() + + +class MapTestCase(ArrowBaseTestCase): + required_server_version = (21, 1, 2) + + def client_kwargs(self, version): + if version < (21, 4): + return {'settings': {'allow_experimental_map_type': True}} + + def cli_client_kwargs(self): + if self.server_version < (21, 4): + return {'allow_experimental_map_type': 1} + + def test_map(self): + with self.create_table('a Map(String, UInt64)'): + self.client.execute( + 'INSERT INTO test (a) VALUES', + [({'a': 1, 'b': 2}, ), ({}, )] + ) + table = self.client.query_arrow('SELECT a FROM test') + + self.assertEqual( + table.schema.field('a').type, + pa.map_(pa.string(), pa.uint64()) + ) + self.assertEqual( + table.column('a').to_pylist(), + [[('a', 1), ('b', 2)], []] + ) diff --git a/tests/arrow/testcase.py b/tests/arrow/testcase.py new file mode 100644 index 00000000..c9bbba4f --- /dev/null +++ b/tests/arrow/testcase.py @@ -0,0 +1,33 @@ +try: + import pyarrow as pa +except ImportError: + pa = None + +from tests.testcase import BaseTestCase + + +class ArrowBaseTestCase(BaseTestCase): + def setUp(self): + if pa is None: + self.skipTest('PyArrow package is not installed') + super(ArrowBaseTestCase, self).setUp() + + def assert_arrow_column(self, ch_type, expected_pa_type, data, + expected=None): + """ + Creates a table with a single column of ``ch_type``, inserts + ``data`` into it and checks that ``query_arrow`` returns a table + with expected Arrow type and values. + """ + with self.create_table('a {}'.format(ch_type)): + self.client.execute( + 'INSERT INTO test (a) VALUES', [(x, ) for x in data] + ) + table = self.client.query_arrow('SELECT a FROM test') + + self.assertIsInstance(table, pa.Table) + self.assertEqual(table.schema.field('a').type, expected_pa_type) + self.assertEqual( + table.column('a').to_pylist(), + data if expected is None else expected + ) diff --git a/tests/clickhouse_server_config/clickhouse_users.xml b/tests/clickhouse_server_config/clickhouse_users.xml new file mode 100644 index 00000000..bb74c548 --- /dev/null +++ b/tests/clickhouse_server_config/clickhouse_users.xml @@ -0,0 +1,15 @@ + + + + + + + ::/0 + + default + default + 1 + + + diff --git a/tests/clickhouse_server_config/yandex_users.xml b/tests/clickhouse_server_config/yandex_users.xml new file mode 100644 index 00000000..112d3307 --- /dev/null +++ b/tests/clickhouse_server_config/yandex_users.xml @@ -0,0 +1,15 @@ + + + + + + + ::/0 + + default + default + 1 + + + diff --git a/tests/columns/test_dynamic_shared_value.py b/tests/columns/test_dynamic_shared_value.py new file mode 100644 index 00000000..23ee0483 --- /dev/null +++ b/tests/columns/test_dynamic_shared_value.py @@ -0,0 +1,433 @@ +from unittest import TestCase + +from clickhouse_driver.context import Context +from clickhouse_driver.columns.service import get_column_by_spec +from clickhouse_driver.columns.dynamiccolumn import ( + DynamicColumn, + SharedValueDecoder, + _decode_type_spec, + _split_tuple_elements, + _SharedValueReader, +) +from clickhouse_driver.columns.newjsoncolumn import ( + NewJsonColumn, + OBJECT_STRING, + _tuples_to_lists, +) + + +def _varint(value): + out = bytearray() + while True: + byte = value & 0x7F + value >>= 7 + if value: + out.append(byte | 0x80) + else: + out.append(byte) + return bytes(out) + + +def _binary_string(text): + raw = text.encode('utf-8') + return _varint(len(raw)) + raw + + +def _make_context(): + context = Context() + context.client_settings = { + 'use_numpy': False, + 'input_format_null_as_default': False, + 'strings_as_bytes': False, + 'strings_encoding': 'utf-8', + } + return context + + +def _make_getter(context=None): + """A column-by-spec getter matching the one the driver wires into the + JSON reader, but standing alone so SharedVariant decoding can be + tested without a live server.""" + context = context or _make_context() + options = {'context': context, 'has_custom_serialization': False} + + def getter(spec): + return get_column_by_spec(spec, options, use_numpy=False) + + return getter + + +class DecodeTypeSpecTestCase(TestCase): + """``_decode_type_spec`` turns an ``encodeDataType`` byte stream into a + ClickHouse type string. These tags are not reachable from JSON input + on the supported server versions, so they are exercised directly.""" + + def decode(self, blob): + return _decode_type_spec(_SharedValueReader_for(blob)) + + def test_primitives(self): + self.assertEqual(self.decode(bytes([0x0A])), "Int64") + self.assertEqual(self.decode(bytes([0x15])), "String") + self.assertEqual(self.decode(bytes([0x2D])), "Bool") + self.assertEqual(self.decode(bytes([0x00])), "Nothing") + + def test_fixed_string(self): + self.assertEqual( + self.decode(bytes([0x16]) + _varint(7)), "FixedString(7)") + + def test_datetime_with_timezone(self): + self.assertEqual( + self.decode(bytes([0x12]) + _binary_string("UTC")), + "DateTime('UTC')") + + def test_datetime64_utc(self): + self.assertEqual( + self.decode(bytes([0x13]) + _varint(3)), "DateTime64(3)") + + def test_datetime64_with_timezone(self): + self.assertEqual( + self.decode( + bytes([0x14]) + _varint(6) + _binary_string("Europe/Moscow")), + "DateTime64(6, 'Europe/Moscow')") + + def test_nullable_and_array(self): + self.assertEqual( + self.decode(bytes([0x23, 0x0A])), "Nullable(Int64)") + self.assertEqual( + self.decode(bytes([0x1E, 0x15])), "Array(String)") + + def test_unnamed_tuple(self): + self.assertEqual( + self.decode(bytes([0x1F]) + _varint(2) + bytes([0x0A, 0x15])), + "Tuple(Int64, String)") + + def test_named_tuple(self): + blob = ( + bytes([0x20]) + _varint(2) + + _binary_string("a") + bytes([0x0A]) + + _binary_string("b") + bytes([0x15]) + ) + self.assertEqual(self.decode(blob), "Tuple(a Int64, b String)") + + def test_json(self): + # JSON tag (0x30) followed by its encoded parameters: version, + # max_dynamic_paths, max_dynamic_types, and three empty path + # lists. The value layout does not depend on them, so the spec + # collapses to "JSON". + blob = bytes([0x30, 0x00]) + _varint(0) + bytes([0x00]) \ + + _varint(0) + _varint(0) + _varint(0) + self.assertEqual(self.decode(blob), "JSON") + + def test_json_with_typed_skip_and_regexp_paths(self): + # Non-empty typed paths (name + nested type), skip paths and skip + # regexps must all be consumed, and the spec still collapses to + # "JSON". + blob = ( + bytes([0x30, 0x00]) + _varint(8) + bytes([0x10]) + + _varint(1) + _binary_string("ts") + bytes([0x0A]) # ts Int64 + + _varint(1) + _binary_string("secret") # skip path + + _varint(1) + _binary_string("^tmp") # skip regexp + ) + self.assertEqual(self.decode(blob), "JSON") + + def test_unknown_tag_raises(self): + with self.assertRaises(NotImplementedError): + self.decode(bytes([0xFF])) + + def test_truncated_stream_raises(self): + with self.assertRaises(EOFError): + self.decode(b"") + + +class SplitTupleElementsTestCase(TestCase): + def test_flat(self): + self.assertEqual( + _split_tuple_elements("Int64, String"), ["Int64", "String"]) + + def test_nested_parens_are_kept_together(self): + self.assertEqual( + _split_tuple_elements("Array(Int64), Tuple(Int64, String)"), + ["Array(Int64)", "Tuple(Int64, String)"]) + + def test_empty(self): + self.assertEqual(_split_tuple_elements(""), []) + + +class SharedValueDecoderTestCase(TestCase): + def setUp(self): + self.decoder = SharedValueDecoder(_make_getter()) + + def test_empty_blob_is_none(self): + self.assertIsNone(self.decoder.decode(b"")) + + def test_scalar(self): + blob = bytes([0x0A]) + (42).to_bytes(8, 'little') + self.assertEqual(self.decoder.decode(blob), 42) + + def test_nothing(self): + self.assertIsNone(self.decoder.decode(bytes([0x00]))) + + def test_nullable_null_and_value(self): + self.assertIsNone(self.decoder.decode(bytes([0x23, 0x0A, 0x01]))) + value = bytes([0x23, 0x0A, 0x00]) + (7).to_bytes(8, 'little') + self.assertEqual(self.decoder.decode(value), 7) + + def test_array(self): + blob = ( + bytes([0x1E, 0x0A]) + _varint(2) + + (1).to_bytes(8, 'little') + (2).to_bytes(8, 'little') + ) + self.assertEqual(self.decoder.decode(blob), [1, 2]) + + def test_tuple(self): + blob = ( + bytes([0x1F]) + _varint(2) + bytes([0x0A, 0x15]) + + (5).to_bytes(8, 'little') + + _binary_string("x") + ) + self.assertEqual(self.decoder.decode(blob), (5, "x")) + + def test_json_value(self): + # A nested JSON value: header + paths. "p" is Int64(1), "a.b" is + # String("x") (a dotted path that denormalises into a nested + # dict), and "gone" carries a Nothing value that must be dropped. + header = ( + bytes([0x30, 0x00]) + _varint(0) + bytes([0x00]) + + _varint(0) + _varint(0) + _varint(0) + ) + value = ( + _varint(3) + + _binary_string("p") + bytes([0x0A]) + (1).to_bytes(8, 'little') + + _binary_string("a.b") + bytes([0x15]) + _binary_string("x") + + _binary_string("gone") + bytes([0x00]) + ) + self.assertEqual( + self.decoder.decode(header + value), + {"p": 1, "a": {"b": "x"}}) + + def test_array_of_json(self): + # Array(JSON) — the shape that previously raised on tag 0x30. + json_header = ( + bytes([0x30, 0x00]) + _varint(0) + bytes([0x00]) + + _varint(0) + _varint(0) + _varint(0) + ) + + def json_value(name, ivalue): + return ( + _varint(1) + _binary_string(name) + bytes([0x0A]) + + (ivalue).to_bytes(8, 'little') + ) + + blob = ( + bytes([0x1E]) + json_header + _varint(2) + + json_value("p", 1) + json_value("q", 2) + ) + self.assertEqual( + self.decoder.decode(blob), [{"p": 1}, {"q": 2}]) + + def test_handler_cache_reuse(self): + # Decoding the same spec twice must reuse the cached handler. + first = bytes([0x0A]) + (1).to_bytes(8, 'little') + second = bytes([0x0A]) + (2).to_bytes(8, 'little') + self.assertEqual(self.decoder.decode(first), 1) + self.assertEqual(self.decoder.decode(second), 2) + + +class DynamicColumnStatePrefixTestCase(TestCase): + """Defensive guards in ``DynamicColumn`` that the JSON happy path never + triggers.""" + + def setUp(self): + self.ctx = _make_context() + + def test_builds_default_shared_value_decoder(self): + # Constructed without an explicit decoder, the column makes its own. + column = DynamicColumn(_make_getter(self.ctx), context=self.ctx) + self.assertIsInstance( + column.shared_value_decoder, SharedValueDecoder) + + def test_unsupported_structure_version_raises(self): + column = DynamicColumn(_make_getter(self.ctx), context=self.ctx) + buf = _ListReader([(99).to_bytes(8, 'little')]) + with self.assertRaises(NotImplementedError): + column.read_state_prefix(buf) + + def test_unsupported_discriminators_mode_raises(self): + column = DynamicColumn(_make_getter(self.ctx), context=self.ctx) + buf = _ListReader([ + (2).to_bytes(8, 'little'), # structure version V2 + _varint(0), # zero declared variants + (5).to_bytes(8, 'little'), # bogus discriminators mode + ]) + with self.assertRaises(NotImplementedError): + column.read_state_prefix(buf) + + def test_compact_discriminators_mode_not_supported(self): + column = DynamicColumn(_make_getter(self.ctx), context=self.ctx) + column.discriminators_mode = 1 # VARIANT_MODE_COMPACT + with self.assertRaises(NotImplementedError): + column.read_items(1, _ListReader([])) + + def test_truncated_discriminators_raise(self): + column = DynamicColumn(_make_getter(self.ctx), context=self.ctx) + column._shared_variant_index = None + with self.assertRaises(EOFError): + # 3 rows promised, only 2 discriminator bytes available. + column.read_items(3, _ListReader([bytes([0, 0])])) + + def test_out_of_range_discriminator_raises(self): + column = DynamicColumn(_make_getter(self.ctx), context=self.ctx) + column._shared_variant_index = None + with self.assertRaises(ValueError): + # No variants declared, so any non-NULL discriminator is bogus. + column.read_items(1, _ListReader([bytes([5])])) + + def test_read_state_prefix_v1_then_all_null_items(self): + # End-to-end read of a Dynamic(Int64) column header in the legacy + # V1 framing, followed by a body with only NULL discriminators. + # Exercises the V1 legacy-slot read, the non-SharedVariant column + # construction and its state-prefix call, and the + # "no rows for this variant, skip" branch in read_items. + buf = _ListReader([ + (1).to_bytes(8, 'little'), # structure_version = DYNAMIC_V1 + _varint(0), # legacy max_dynamic_types slot + _varint(1), # one declared variant + _binary_string("Int64"), # variant type spec + (0).to_bytes(8, 'little'), # discriminators_mode = BASIC + ]) + column = DynamicColumn(_make_getter(self.ctx), context=self.ctx) + column.read_state_prefix(buf) + self.assertEqual(column.variant_specs, ["Int64"]) + # "Int64" sorts before "SharedVariant", so the latter takes + # global discriminator 1 and the SharedVariant slot is the last. + self.assertEqual(column._shared_variant_index, 1) + + result = column.read_items(2, _ListReader([bytes([0xFF, 0xFF])])) + self.assertEqual(result, [None, None]) + + def test_read_items_routes_rows_to_variants(self): + # Row 0 hits a variant exposing only read_items (the fallback + # branch); row 1 hits the SharedVariant slot, whose bytes go + # through the shared-value decoder; row 2 is NULL. + column = DynamicColumn(_make_getter(self.ctx), context=self.ctx) + column.discriminators_mode = 0 # VARIANT_MODE_BASIC + column.variant_columns = [_ReadItemsOnlyColumn(), _ReadDataColumn()] + column._shared_variant_index = 1 + column.shared_value_decoder = _FakeSharedDecoder() + + result = column.read_items(3, _ListReader([bytes([0, 1, 0xFF])])) + self.assertEqual(result, ["from_read_items", "decoded:blob", None]) + + +class NewJsonColumnUnitTestCase(TestCase): + """Branches of the JSON column reader/writer that the live-server + tests on CH 25.5 do not reach: the string serialization version, and + a few write-path / normalisation helpers.""" + + def setUp(self): + self.ctx = _make_context() + self.column = NewJsonColumn(_make_getter(self.ctx), context=self.ctx) + + def test_unsupported_serialization_version_raises(self): + buf = _SharedValueReader() + buf.reset((99).to_bytes(8, 'little')) + with self.assertRaises(NotImplementedError): + self.column.read_state_prefix(buf) + + def test_string_serialization_round_trip(self): + # OBJECT_STRING framing: a version header, then one String per row + # carrying the JSON text. An empty string decodes to ``{}``. + buf = _SharedValueReader() + buf.reset( + (OBJECT_STRING).to_bytes(8, 'little') + + _binary_string('{"a": 1}') + + _binary_string("") + ) + self.column.read_state_prefix(buf) + self.assertEqual(self.column.serialization_version, OBJECT_STRING) + self.assertEqual(self.column.read_items(2, buf), [{"a": 1}, {}]) + + def test_value_spec_for_mixed_float_and_bool_array(self): + # A float+bool array has no common numeric type, so it widens to + # Array(Nullable(String)). + self.assertEqual( + self.column._get_json_value_spec([1.5, True], 0), + "Array(Nullable(String))") + + def test_value_spec_for_pure_bool_array(self): + self.assertEqual( + self.column._get_json_value_spec([True, False], 0), + "Array(Nullable(Bool))") + + def test_preprocess_array_passthrough_for_unknown_type(self): + # A spec matching none of the scalar branches is passed through + # unchanged. + values = [[1, 2]] + self.assertEqual( + self.column._preprocess_array(values, "Nothing"), values) + + def test_unfold_json_item_defaults_result(self): + # Called without an accumulator, it allocates its own. + result = self.column._unfold_json_item({"a": 1}, depth=0) + # Leaves are keyed by their dotted path with a trailing separator + # that ``_unfold_json`` strips later. + self.assertIn("a.", result) + + def test_denormalize_dotted_paths_conflict_raises(self): + with self.assertRaises(ValueError): + self.column._denormalize_dotted_paths({"a": 1, "a.b": 2}) + + def test_tuples_to_lists_scalar_and_nested(self): + self.assertEqual(_tuples_to_lists(5), 5) + self.assertEqual(_tuples_to_lists((1, "x")), (1, "x")) + self.assertEqual(_tuples_to_lists([1, 2]), [1, 2]) + + +# ---------------------------------------------------------------------- +# Minimal buffer stand-ins +# ---------------------------------------------------------------------- + +def _SharedValueReader_for(blob): + reader = _SharedValueReader() + reader.reset(blob) + return reader + + +class _ReadItemsOnlyColumn(object): + """A variant column that only exposes ``read_items`` — forces + ``DynamicColumn.read_items`` down its low-level fallback branch.""" + + def read_items(self, n_items, buf): + return ["from_read_items"] * n_items + + +class _ReadDataColumn(object): + """The implicit SharedVariant String column: returns raw blobs.""" + + def read_data(self, n_items, buf): + return [b"blob"] * n_items + + +class _FakeSharedDecoder(object): + def decode(self, blob): + return "decoded:" + blob.decode() + + +class _ListReader(object): + """A buffer that yields pre-chunked byte strings for the driver's + ``read_binary_*`` / ``read_varint`` helpers, which only call + ``read(n)``.""" + + def __init__(self, chunks): + self._buf = b"".join(chunks) + self._pos = 0 + + def read(self, n): + start = self._pos + self._pos += n + return self._buf[start:start + n] + + def read_one(self): + byte = self._buf[self._pos] + self._pos += 1 + return byte diff --git a/tests/columns/test_newjson.py b/tests/columns/test_newjson.py new file mode 100644 index 00000000..5c96892c --- /dev/null +++ b/tests/columns/test_newjson.py @@ -0,0 +1,1243 @@ +from io import BytesIO +from unittest import TestCase + +from tests.testcase import BaseTestCase +from clickhouse_driver.bufferedreader import CompressedBufferedReader +from clickhouse_driver.bufferedwriter import CompressedBufferedWriter +from clickhouse_driver.columns.service import read_column, write_column +from clickhouse_driver.context import Context + + +class NewJSONTestCase(BaseTestCase): + required_server_version = (24, 8, 0) + + def client_kwargs(self, version): + return {"settings": {"enable_json_type": True}} + + def cli_client_kwargs(self): + return {"enable_json_type": 1} + + def test_simple(self): + rv = self.client.execute('SELECT \'{"bb": {"cc": [255, 1]}}\'::JSON') + self.assertEqual(rv, [({"bb": {"cc": [255, 1]}},)]) + + def test_json_0(self): + with self.create_table("a JSON"): + data = [({"key": 1},), ({"key": "val"},), ({"key": 2.0},)] + self.client.execute("INSERT INTO test (a) VALUES", data) + + query = "SELECT * FROM test" + expected_result = [ + ({"key": 1},), ({"key": "val"},), ({"key": 2.0},)] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_0_fromcli(self): + with self.create_table("a JSON"): + self.emit_cli( + 'INSERT INTO test (a) VALUES (\'{"key": 1}\'),\ + (\'{"key": "val"}\'),\ + (\'{"key": 2.0}\')' + ) + + query = "SELECT * FROM test" + expected_result = [ + ({"key": 1},), ({"key": "val"},), ({"key": 2.0},)] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_1(self): + with self.create_table("a JSON"): + data = [ + ( + { + "user_id": 101, + "username": "john_doe", + "email": "john.doe@example.com", + "profile": { + "first_name": "John", + "last_name": "Doe", + "age": 30, + "gender": "male", + }, + "preferences": {"theme": "dark", "notifications": True}, + "roles": ["admin", "user"], + }, + ) + ] + self.client.execute("INSERT INTO test (a) VALUES", data) + + query = "SELECT * FROM test" + expected_result = [ + ( + { + "email": "john.doe@example.com", + "roles": ["admin", "user"], + "user_id": 101, + "username": "john_doe", + "preferences": {"notifications": True, "theme": "dark"}, + "profile": { + "age": 30, + "first_name": "John", + "gender": "male", + "last_name": "Doe", + }, + }, + ) + ] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_1_fromcli(self): + with self.create_table("a JSON"): + self.emit_cli( + 'INSERT INTO test (a) VALUES (\'{"user_id": 101, "username": "john_doe", "email": "john.doe@example.com", "profile": {"first_name": "John", "last_name": "Doe", "age": 30, "gender": "male"}, "preferences": {"theme": "dark", "notifications": true}, "roles": ["admin", "user"]}\')' + ) + + query = "SELECT * FROM test" + expected_result = [ + ( + { + "email": "john.doe@example.com", + "roles": ["admin", "user"], + "user_id": 101, + "username": "john_doe", + "preferences": {"notifications": True, "theme": "dark"}, + "profile": { + "age": 30, + "first_name": "John", + "gender": "male", + "last_name": "Doe", + }, + }, + ) + ] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_2(self): + with self.create_table("a JSON"): + data = [ + ({},), + ({"foo": "bar", "bar": "baz"},), + ({"baz": "qux", "foo": 4919},), + ({"qux": "quux"},), + ({"foo": "AAAA"},), + ({"qux": 14099},), + ({"foo": [1, 0.2, "bar", "baz", False]},), + ({"foo": 0.1337},), + ({"foo": False},), + ({"bar": 1337},), + ({"bar": 0.999},), + ({"quux": 1000},), + ({"quux": 2000},), + ({"quux": 20.25},), + ({"alice": 0.432},), + ({"bob": 0.991},), + ({"boolean": True},), + ({"null": None},), + ({"string": "A quick brown fox jumps over the lazy dog."},), + ( + { + "nested": { + "number": 4141, + "string": "Hello, World!", + "double-nested": { + "foo": "bar", + "no.escaping": "1337", + "triple-nested": {"foo": "bar"}, + "numbers": [1, 2, 3], + "floats": [0.1, 0.2, 4], + "tuple-list": [ + 1, + 3, + "asdf", + [1, 4, 6], + {"foo": "bar", "list": [ + 1, 2, {"hello": "world"}]}, + ], + }, + } + }, + ), + ( + { + "list": [ + 123, + "2", + True, + {"foo": "bar", "list": [0.123, {"baz": "bar"}]}, + ] + }, + ), + ] + self.client.execute("INSERT INTO test (a) VALUES", data) + + query = "SELECT * FROM test" + expected_result = [ + ({},), + ({"bar": "baz", "foo": "bar"},), + ({"baz": "qux", "foo": 4919},), + ({"qux": "quux"},), + ({"foo": "AAAA"},), + ({"qux": 14099},), + ({"foo": ["1", "0.2", "bar", "baz", "false"]},), + ({"foo": 0.1337},), + ({"foo": False},), + ({"bar": 1337},), + ({"bar": 0.999},), + ({"quux": 1000},), + ({"quux": 2000},), + ({"quux": 20.25},), + ({"alice": 0.432},), + ({"bob": 0.991},), + ({"boolean": True},), + ({},), + ({"string": "A quick brown fox jumps over the lazy dog."},), + ( + { + "nested": { + "double-nested": { + "floats": [0.1, 0.2, 4.0], + "foo": "bar", + "no": {"escaping": "1337"}, + "numbers": [1, 2, 3], + "triple-nested": {"foo": "bar"}, + "tuple-list": [ + 1, + 3, + "asdf", + [1, 4, 6], + {"foo": "bar", "list": [ + 1, 2, {"hello": "world"}]}, + ], + }, + "number": 4141, + "string": "Hello, World!", + } + }, + ), + ( + { + "list": [ + 123, + "2", + True, + {"foo": "bar", "list": [0.123, {"baz": "bar"}]}, + ] + }, + ), + ] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_2_fromcli(self): + with self.create_table("a JSON"): + self.emit_cli( + 'INSERT INTO test (a) VALUES (\'{}\'),\ + (\'{"foo": "bar", "bar": "baz"}\'),\ + (\'{"baz": "qux", "foo": 4919}\'),\ + (\'{"qux": "quux"}\'),\ + (\'{"foo": "AAAA"}\'),\ + (\'{"qux": 14099}\'),\ + (\'{"foo": [1, 0.2, "bar", "baz", false]}\'),\ + (\'{"foo": 0.1337}\'),\ + (\'{"foo": false}\'),\ + (\'{"bar": 1337}\'),\ + (\'{"bar": 0.999}\'),\ + (\'{"quux": 1000}\'),\ + (\'{"quux": 2000}\'),\ + (\'{"quux": 20.25}\'),\ + (\'{"alice": 0.432}\'),\ + (\'{"bob": 0.991}\'),\ + (\'{"boolean": true}\'),\ + (\'{"null": null}\'),\ + (\'{"string": "A quick brown fox jumps over the lazy dog."}\'),\ + (\'{"nested": {"number": 4141, "string": "Hello, World!", "double-nested": {"foo": "bar", "no.escaping": "1337", "triple-nested": {"foo": "bar"}, "numbers": [1, 2, 3], "floats": [0.1, 0.2, 4], "tuple-list": [1, 3, "asdf", [1, 4, 6], {"foo": "bar", "list": [1, 2, {"hello": "world"}]}]}}}\'),\ + (\'{"list": [123, "2", true, {"foo": "bar", "list": [0.123, {"baz": "bar"}]}]}\')' + ) + + query = "SELECT * FROM test" + expected_result = [ + ({},), + ({"bar": "baz", "foo": "bar"},), + ({"baz": "qux", "foo": 4919},), + ({"qux": "quux"},), + ({"foo": "AAAA"},), + ({"qux": 14099},), + ({"foo": ["1", "0.2", "bar", "baz", "false"]},), + ({"foo": 0.1337},), + ({"foo": False},), + ({"bar": 1337},), + ({"bar": 0.999},), + ({"quux": 1000},), + ({"quux": 2000},), + ({"quux": 20.25},), + ({"alice": 0.432},), + ({"bob": 0.991},), + ({"boolean": True},), + ({},), + ({"string": "A quick brown fox jumps over the lazy dog."},), + ( + { + "nested": { + "double-nested": { + "floats": [0.1, 0.2, 4.0], + "foo": "bar", + "no": {"escaping": "1337"}, + "numbers": [1, 2, 3], + "triple-nested": {"foo": "bar"}, + "tuple-list": [ + 1, + 3, + "asdf", + [1, 4, 6], + {"foo": "bar", "list": [ + 1, 2, {"hello": "world"}]}, + ], + }, + "number": 4141, + "string": "Hello, World!", + } + }, + ), + ( + { + "list": [ + 123, + "2", + True, + {"foo": "bar", "list": [0.123, {"baz": "bar"}]}, + ] + }, + ), + ] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_3(self): + with self.create_table("a JSON"): + data = [ + ({"list": [1, "asdf", 0.025, None, + ["foo", "bar"], ["foo", "bar"]]},) + ] + self.client.execute("INSERT INTO test (a) VALUES", data) + + query = "SELECT * FROM test" + expected_result = [ + ({"list": (1, "asdf", 0.025, None, + ["foo", "bar"], ["foo", "bar"])},) + ] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_3_fromcli(self): + with self.create_table("a JSON"): + self.emit_cli( + 'INSERT INTO test (a) VALUES (\'{"list": [1, "asdf", 0.025, null, ["foo", "bar"], ["foo", "bar"]]}\')' + ) + + query = "SELECT * FROM test" + expected_result = [ + ({"list": (1, "asdf", 0.025, None, + ["foo", "bar"], ["foo", "bar"])},) + ] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_4(self): + with self.create_table("a JSON"): + data = [ + ({"list": [1, 2, 3]},), + ({"list": [0.1, 2, 3, None]},), + ({"list": ["test"]},), + ({"list": [None, None, None]},), + ({"list": [1, 2, None]},), + ({"list": ["asdf", None]},), + ] + self.client.execute("INSERT INTO test (a) VALUES", data) + + query = "SELECT * FROM test" + expected_result = [ + ({"list": [1, 2, 3]},), + ({"list": [0.1, 2.0, 3.0, 0.0]},), + ({"list": ["test"]},), + ({"list": [None, None, None]},), + ({"list": [1, 2, 0]},), + ({"list": ["asdf", None]},), + ] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_4_fromcli(self): + with self.create_table("a JSON"): + self.emit_cli( + 'INSERT INTO test (a) VALUES (\'{"list": [1, 2, 3]}\'),\ + (\'{"list": [0.1, 2, 3, null]}\'),\ + (\'{"list": ["test"]}\'),\ + (\'{"list": [null, null, null]}\'),\ + (\'{"list": [1, 2, null]}\'),\ + (\'{"list": ["asdf", null]}\')' + ) + + query = "SELECT * FROM test" + expected_result = [ + ({"list": [1, 2, 3]},), + ({"list": [0.1, 2.0, 3.0, None]},), + ({"list": ["test"]},), + ({"list": [None, None, None]},), + ({"list": [1, 2, None]},), + ({"list": ["asdf", None]},), + ] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_5(self): + with self.create_table("a JSON"): + data = [ + ( + { + "list": [ + "123", + "456", + { + "nested-list": [ + "789", + "10", + { + "double-nested-list": [ + 14099, + "AAAA", + { + "triple-nested-list": [ + 1, + 2, + { + "quadruple-nested-list": [ + 3, + 4, + { + "quintuple-nested-list": [ + 5, + 6, + ] + }, + ] + }, + ] + }, + ] + }, + ] + }, + ] + }, + ) + ] + self.client.execute("INSERT INTO test (a) VALUES", data) + + query = "SELECT * FROM test" + expected_result = [ + ( + { + "list": [ + "123", + "456", + { + "nested-list": [ + "789", + "10", + { + "double-nested-list": [ + 14099, + "AAAA", + { + "triple-nested-list": [ + 1, + 2, + { + "quadruple-nested-list": [ + 3, + 4, + { + "quintuple-nested-list": [ + 5, + 6, + ] + }, + ] + }, + ] + }, + ] + }, + ] + }, + ] + }, + ) + ] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_5_fromcli(self): + with self.create_table("a JSON"): + self.emit_cli( + 'INSERT INTO test (a) VALUES (\'{"list": ["123", "456", {"nested-list": ["789", "10", {"double-nested-list": [14099, "AAAA", {"triple-nested-list": [1, 2, {"quadruple-nested-list": [3, 4, {"quintuple-nested-list": [5, 6]}]}]}]}]}]}\')' + ) + + query = "SELECT * FROM test" + expected_result = [ + ( + { + "list": [ + "123", + "456", + { + "nested-list": [ + "789", + "10", + { + "double-nested-list": [ + 14099, + "AAAA", + { + "triple-nested-list": [ + 1, + 2, + { + "quadruple-nested-list": [ + 3, + 4, + { + "quintuple-nested-list": [ + 5, + 6, + ] + }, + ] + }, + ] + }, + ] + }, + ] + }, + ] + }, + ) + ] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_6(self): + with self.create_table("a JSON"): + data = [ + ( + { + "list": [ + "123", + "456", + {"nested-list": ["789", "10", + {"double-nested": "test"}]}, + ] + }, + ), + ( + { + "list": [ + "1337", + "444", + {"nested-list": ["123", "654", {"asdf": "fdas"}]}, + ] + }, + ), + ({"list": ["123", "456", {"nested-list": "1234"}]},), + ] + self.client.execute("INSERT INTO test (a) VALUES", data) + + query = "SELECT * FROM test" + expected_result = [ + ( + { + "list": [ + "123", + "456", + {"nested-list": ["789", "10", + {"double-nested": "test"}]}, + ] + }, + ), + ( + { + "list": [ + "1337", + "444", + {"nested-list": ["123", "654", {"asdf": "fdas"}]}, + ] + }, + ), + ({"list": ["123", "456", {"nested-list": "1234"}]},), + ] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_6_fromcli(self): + with self.create_table("a JSON"): + self.emit_cli( + 'INSERT INTO test (a) VALUES (\'{"list": ["123", "456", {"nested-list": ["789", "10", {"double-nested": "test"}]}]}\'),\ + (\'{"list": ["1337", "444", {"nested-list": ["123", "654", {"asdf": "fdas"}]}]}\'),\ + (\'{"list": ["123", "456", {"nested-list": "1234"}]}\')' + ) + + query = "SELECT * FROM test" + expected_result = [ + ( + { + "list": [ + "123", + "456", + {"nested-list": ["789", "10", + {"double-nested": "test"}]}, + ] + }, + ), + ( + { + "list": [ + "1337", + "444", + {"nested-list": ["123", "654", {"asdf": "fdas"}]}, + ] + }, + ), + ({"list": ["123", "456", {"nested-list": "1234"}]},), + ] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_7(self): + with self.create_table("a JSON"): + data = [ + ({"list": [1, "2", {"foo": "bar"}]},), + ({"list": "not a list"},), + ({"list": 14009},), + ({"list": 0.025},), + ({"list": True},), + ({"list": [14099, {"bar": "baz"}, {"baz": "quux"}]},), + ] + self.client.execute("INSERT INTO test (a) VALUES", data) + + query = "SELECT * FROM test" + expected_result = [ + ({"list": [1, "2", {"foo": "bar"}]},), + ({"list": "not a list"},), + ({"list": 14009},), + ({"list": 0.025},), + ({"list": True},), + ({"list": [14099, {"bar": "baz"}, {"baz": "quux"}]},), + ] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_7_fromcli(self): + with self.create_table("a JSON"): + self.emit_cli( + 'INSERT INTO test (a) VALUES (\'{"list": [1, "2", {"foo": "bar"}]}\'),\ + (\'{"list": "not a list"}\'),\ + (\'{"list": 14009}\'),\ + (\'{"list": 0.025}\'),\ + (\'{"list": true}\'),\ + (\'{"list": [14099, {"bar": "baz"}, {"baz": "quux"}]}\')' + ) + + query = "SELECT * FROM test" + expected_result = [ + ({"list": [1, "2", {"foo": "bar"}]},), + ({"list": "not a list"},), + ({"list": 14009},), + ({"list": 0.025},), + ({"list": True},), + ({"list": [14099, {"bar": "baz"}, {"baz": "quux"}]},), + ] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_8(self): + with self.create_table("a JSON"): + data = [ + ({"list1": [1, "2", {"foo": "bar"}]},), + ({"string": "string"},), + ({"int": 14009},), + ({"float": 0.025},), + ({"bool": True},), + ({"list2": [14099, {"bar": "baz"}, {"baz": "quux"}]},), + ] + self.client.execute("INSERT INTO test (a) VALUES", data) + + query = "SELECT * FROM test" + expected_result = [ + ({"list1": [1, "2", {"foo": "bar"}]},), + ({"string": "string"},), + ({"int": 14009},), + ({"float": 0.025},), + ({"bool": True},), + ({"list2": [14099, {"bar": "baz"}, {"baz": "quux"}]},), + ] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_8_fromcli(self): + with self.create_table("a JSON"): + self.emit_cli( + 'INSERT INTO test (a) VALUES (\'{"list1": [1, "2", {"foo": "bar"}]}\'),\ + (\'{"string": "string"}\'),\ + (\'{"int": 14009}\'),\ + (\'{"float": 0.025}\'),\ + (\'{"bool": true}\'),\ + (\'{"list2": [14099, {"bar": "baz"}, {"baz": "quux"}]}\')' + ) + + query = "SELECT * FROM test" + expected_result = [ + ({"list1": [1, "2", {"foo": "bar"}]},), + ({"string": "string"},), + ({"int": 14009},), + ({"float": 0.025},), + ({"bool": True},), + ({"list2": [14099, {"bar": "baz"}, {"baz": "quux"}]},), + ] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_9(self): + with self.create_table("a JSON"): + data = [ + ({"list": [1, "asdf", 0.025, ["foo", "bar", ["baz", "qux"]]]},), + ({"list": [10, "fdas", 0.075, ["bar", "foo", ["qux", "baz"]]]},), + ] + self.client.execute("INSERT INTO test (a) VALUES", data) + + query = "SELECT * FROM test" + expected_result = [ + ({"list": (1, "asdf", 0.025, + ("foo", "bar", ["baz", "qux"]))},), + ({"list": (10, "fdas", 0.075, + ("bar", "foo", ["qux", "baz"]))},), + ] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_9_fromcli(self): + with self.create_table("a JSON"): + self.emit_cli( + 'INSERT INTO test (a) VALUES (\'{"list": [1, "asdf", 0.025, ["foo", "bar", ["baz", "qux"]]]}\'),\ + (\'{"list": [10, "fdas", 0.075, ["bar", "foo", ["qux", "baz"]]]}\')' + ) + + query = "SELECT * FROM test" + expected_result = [ + ({"list": (1, "asdf", 0.025, + ("foo", "bar", ["baz", "qux"]))},), + ({"list": (10, "fdas", 0.075, + ("bar", "foo", ["qux", "baz"]))},), + ] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_10(self): + with self.create_table("a JSON"): + data = [({"list": ["a", None, "b", None, "c", None]},)] + self.client.execute("INSERT INTO test (a) VALUES", data) + + query = "SELECT * FROM test" + expected_result = [({"list": ["a", None, "b", None, "c", None]},)] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_10_fromcli(self): + with self.create_table("a JSON"): + self.emit_cli( + 'INSERT INTO test (a) VALUES (\'{"list": ["a", null, "b", null, "c", null]}\')' + ) + + query = "SELECT * FROM test" + expected_result = [({"list": ["a", None, "b", None, "c", None]},)] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_11(self): + with self.create_table("a JSON"): + data = [ + ({"asdf": [{"foo": "bar"}, {"bar": "baz"}]},), + ({"asdf": [{"baz": "qux"}, {"qux": "quux"}]},), + ] + self.client.execute("INSERT INTO test (a) VALUES", data) + + query = "SELECT * FROM test" + expected_result = [ + ({"asdf": [{"foo": "bar"}, {"bar": "baz"}]},), + ({"asdf": [{"baz": "qux"}, {"qux": "quux"}]},), + ] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_11_fromcli(self): + with self.create_table("a JSON"): + self.emit_cli( + 'INSERT INTO test (a) VALUES (\'{"asdf": [{"foo": "bar"}, {"bar": "baz"}]}\'),\ + (\'{"asdf": [{"baz": "qux"}, {"qux": "quux"}]}\')' + ) + + query = "SELECT * FROM test" + expected_result = [ + ({"asdf": [{"foo": "bar"}, {"bar": "baz"}]},), + ({"asdf": [{"baz": "qux"}, {"qux": "quux"}]},), + ] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_12(self): + with self.create_table("a JSON"): + data = [ + ({"fdsa": [["foo", "bar"], ["bar", "baz"]]},), + ({"fdsa": [["baz", "qux"], ["qux", "quux"]]},), + ] + self.client.execute("INSERT INTO test (a) VALUES", data) + + query = "SELECT * FROM test" + expected_result = [ + ({"fdsa": [["foo", "bar"], ["bar", "baz"]]},), + ({"fdsa": [["baz", "qux"], ["qux", "quux"]]},), + ] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_12_fromcli(self): + with self.create_table("a JSON"): + self.emit_cli( + 'INSERT INTO test (a) VALUES (\'{"fdsa": [["foo", "bar"], ["bar", "baz"]]}\'),\ + (\'{"fdsa": [["baz", "qux"], ["qux", "quux"]]}\')' + ) + + query = "SELECT * FROM test" + expected_result = [ + ({"fdsa": [["foo", "bar"], ["bar", "baz"]]},), + ({"fdsa": [["baz", "qux"], ["qux", "quux"]]},), + ] + result = self.client.execute(query) + self.assertEqual(result, expected_result) + + def test_json_shared_paths(self): + # Paths that overflow max_dynamic_paths land in the JSON column's + # shared data sub-column. Force a merge so the shared data + # representation is actually persisted. + spec = "id UInt32, a JSON(max_dynamic_paths=2, max_dynamic_types=2)" + template = "CREATE TABLE test ({}) ENGINE = MergeTree ORDER BY id" + with self.create_table(spec, template=template): + data = [] + for i in range(8): + data.append({ + "id": i, + "a": { + "common": "shared", + "k{}".format(i): i, + "num": i * 2, + }, + }) + self.client.execute( + "INSERT INTO test (id, a) VALUES", data) + self.client.execute("OPTIMIZE TABLE test FINAL") + result = self.client.execute( + "SELECT a FROM test ORDER BY id") + expected = [ + ({ + "common": "shared", + "k{}".format(i): i, + "num": i * 2, + },) for i in range(8) + ] + self.assertEqual(result, expected) + + def test_json_shared_paths_mixed_types(self): + # All paths go to shared data because both limits are zero; the + # values exercise the binary-encoded type tags for Int, Float, + # String and Bool. + spec = "id UInt32, a JSON(max_dynamic_paths=0, max_dynamic_types=0)" + template = "CREATE TABLE test ({}) ENGINE = MergeTree ORDER BY id" + with self.create_table(spec, template=template): + data = [ + {"id": 0, "a": {"x": 1, "y": "two", "z": True}}, + {"id": 1, "a": {"x": 2, "y": "three", "z": False}}, + {"id": 2, "a": {"f": 3.5}}, + {"id": 3, "a": {}}, + ] + self.client.execute( + "INSERT INTO test (id, a) VALUES", data) + self.client.execute("OPTIMIZE TABLE test FINAL") + result = self.client.execute( + "SELECT a FROM test ORDER BY id") + self.assertEqual(result, [ + ({"x": 1, "y": "two", "z": True},), + ({"x": 2, "y": "three", "z": False},), + ({"f": 3.5},), + ({},), + ]) + + def test_nullable_json_round_trip(self): + with self.create_table("a Nullable(JSON)"): + data = [(None,), ({"x": 1},), (None,), ({"y": "two"},)] + self.client.execute("INSERT INTO test (a) VALUES", data) + result = self.client.execute("SELECT * FROM test") + self.assertEqual(result, data) + + def test_non_nullable_json_coerces_none_to_empty_dict(self): + with self.create_table("a JSON"): + self.client.execute( + "INSERT INTO test (a) VALUES", [(None,), ({"x": 1},)]) + result = self.client.execute("SELECT * FROM test") + self.assertEqual(result, [({},), ({"x": 1},)]) + + def test_json_array_value_types(self): + # Each homogeneous array maps to a distinct Array spec on the + # write path (Int64 / Float64 / Bool / String), and round-trips + # back through the per-path Dynamic reader. + with self.create_table("a JSON"): + data = [ + ({"ints": [1, 2, 3]},), + ({"floats": [1.5, 2.5]},), + ({"bools": [True, False]},), + ({"strings": ["a", "b"]},), + ] + self.client.execute("INSERT INTO test (a) VALUES", data) + result = self.client.execute("SELECT * FROM test") + self.assertEqual(result, data) + + def test_json_array_mixed_numeric_coerced_to_string(self): + # A heterogeneous array has no common numeric type, so the + # server widens every element to String. + with self.create_table("a JSON"): + self.client.execute( + "INSERT INTO test (a) VALUES", [({"v": [1, "x", 2.5]},)]) + result = self.client.execute("SELECT * FROM test") + self.assertEqual(result, [({"v": ["1", "x", "2.5"]},)]) + + def test_json_nested_arrays(self): + # Arrays whose elements are themselves arrays exercise the + # recursive Array spec inference / decoder. + with self.create_table("a JSON"): + data = [({"grid": [[1, 2], [3]]},)] + self.client.execute("INSERT INTO test (a) VALUES", data) + result = self.client.execute("SELECT * FROM test") + self.assertEqual(result, data) + + def test_json_array_of_objects(self): + # An array of objects becomes a Tuple spec on the write path and + # a dynamic path on read. + with self.create_table("a JSON"): + data = [({"items": [{"p": 1}, {"p": 2}]},)] + self.client.execute("INSERT INTO test (a) VALUES", data) + result = self.client.execute("SELECT * FROM test") + self.assertEqual(result, data) + + def test_json_deeply_nested_object(self): + with self.create_table("a JSON"): + data = [({"a": {"b": {"c": {"d": 1}}}},)] + self.client.execute("INSERT INTO test (a) VALUES", data) + result = self.client.execute("SELECT * FROM test") + self.assertEqual(result, data) + + def test_json_string_value_input(self): + # A row given as a JSON string is parsed by the write path + # before serialization. + with self.create_table("a JSON"): + self.client.execute( + "INSERT INTO test (a) VALUES", [('{"x": 1, "y": "two"}',)]) + result = self.client.execute("SELECT * FROM test") + self.assertEqual(result, [({"x": 1, "y": "two"},)]) + + def test_json_shared_arrays(self): + # Arrays forced into the shared-data sub-column exercise the + # SharedVariant Array / nested-Array decoders, which the typed + # dynamic-path reader never reaches. + spec = "id UInt32, a JSON(max_dynamic_paths=0, max_dynamic_types=0)" + template = "CREATE TABLE test ({}) ENGINE = MergeTree ORDER BY id" + with self.create_table(spec, template=template): + data = [ + {"id": 0, "a": {"ints": [1, 2, 3]}}, + {"id": 1, "a": {"nested": [[1, 2], [3]]}}, + {"id": 2, "a": {"strings": ["a", "b"]}}, + {"id": 3, "a": {"floats": [1.5, 2.5]}}, + ] + self.client.execute("INSERT INTO test (id, a) VALUES", data) + self.client.execute("OPTIMIZE TABLE test FINAL") + result = self.client.execute("SELECT a FROM test ORDER BY id") + self.assertEqual(result, [ + ({"ints": [1, 2, 3]},), + ({"nested": [[1, 2], [3]]},), + ({"strings": ["a", "b"]},), + ({"floats": [1.5, 2.5]},), + ]) + + def test_json_array_with_nested_tuple_and_object(self): + # Heterogeneous arrays infer a Tuple spec on the write path. When + # an element is itself such an array, the spec nests + # (Tuple(Tuple(...), JSON)); the write path has to split the spec + # paren-aware and recurse rather than mishandle the inner commas. + with self.create_table("a JSON"): + data = [ + ({"v": [[[1], {"p": 1}], {"q": 2}]},), + ({"v": [[2, 3], {"p": 5}]},), + ] + self.client.execute("INSERT INTO test (a) VALUES", data) + result = self.client.execute("SELECT * FROM test") + self.assertEqual(result, data) + + def test_json_nested_container_shapes(self): + # Each of these infers a different nested spec on the write path, + # exercising the paren-aware recursion through Tuple/Array + # elements that carry a JSON sub-column. + with self.create_table("a JSON"): + data = [ + # Tuple(Array(JSON), Nullable(Int64)) + ({"v": [[{"p": 1}], 5]},), + # Array(Tuple(Nullable(Int64), JSON)) + ({"w": [[1, {"p": 1}], [2, {"q": 2}]]},), + # Array(Array(Array(JSON))) + ({"x": [[[{"p": 1}]]]},), + ] + self.client.execute("INSERT INTO test (a) VALUES", data) + result = self.client.execute("SELECT * FROM test ORDER BY a") + self.assertCountEqual(result, data) + + def test_json_tuple_with_plain_tuple_element(self): + # A complex tuple whose first element is a Tuple that has no JSON + # is written via the non-JSON Tuple branch. On read, a tuple + # without a dict stays a Python tuple (the long-standing + # _tuples_to_lists surface), so the inner element comes back as a + # tuple rather than a list. + with self.create_table("a JSON"): + self.client.execute( + "INSERT INTO test (a) VALUES", + [({"v": [[[1], "x"], {"p": 1}]},)]) + result = self.client.execute("SELECT * FROM test") + self.assertEqual(result, [({"v": [([1], "x"), {"p": 1}]},)]) + + def test_json_shared_arrays_of_objects(self): + # An array of objects forced into shared data serialises as + # Array(JSON); the SharedVariant decoder has to recurse into the + # nested JSON value (including dotted paths) to reconstruct it. + spec = "id UInt32, a JSON(max_dynamic_paths=0, max_dynamic_types=0)" + template = "CREATE TABLE test ({}) ENGINE = MergeTree ORDER BY id" + with self.create_table(spec, template=template): + data = [ + {"id": 0, "a": {"items": [{"p": 1}, {"q": "x"}]}}, + {"id": 1, "a": {"items": [{"nested": {"deep": 5}}]}}, + ] + self.client.execute("INSERT INTO test (id, a) VALUES", data) + self.client.execute("OPTIMIZE TABLE test FINAL") + result = self.client.execute("SELECT a FROM test ORDER BY id") + self.assertEqual(result, [ + ({"items": [{"p": 1}, {"q": "x"}]},), + ({"items": [{"nested": {"deep": 5}}]},), + ]) + + +class JSONInContainerColumnsTestCase(BaseTestCase): + """ + JSON columns nested inside container column types. The object + prefix is data-dependent, so the write path threads the block's + items into ``write_state_prefix`` to emit it in the prefix stream + position the server expects for nested columns; inserts into + ``Map(String, JSON)`` used to deadlock and ``Array(JSON)`` raised + ``NotImplementedError`` (issue #511). + """ + + required_server_version = (24, 8, 0) + + def client_kwargs(self, version): + return {"settings": {"enable_json_type": True}} + + def cli_client_kwargs(self): + return {"enable_json_type": 1} + + def test_map_of_json(self): + with self.create_table("a Map(String, JSON)"): + data = [ + ({"k": {"a": 1}},), + ({"k": {"b": "x"}, "j": {"c": 2.5, "d": {"e": True}}},), + ({},), + ({"empty": {}},), + ] + self.client.execute("INSERT INTO test (a) VALUES", data) + result = self.client.execute("SELECT * FROM test") + self.assertEqual(result, data) + + def test_map_of_json_server_side_view(self): + # The CLI view proves the bytes landed correctly on the server, + # not just that the client can read back its own encoding. + with self.create_table("a Map(String, JSON)"): + self.client.execute( + "INSERT INTO test (a) VALUES", + [({"k": {"a": 1, "n": {"d": "deep"}}},)]) + # Integer quoting in JSON output defaults differently across + # server versions; pin it so the assertion is stable. + cli = self.emit_cli( + "SELECT toJSONString(a) FROM test", + output_format_json_quote_64bit_integers=0, + ) + self.assertEqual(cli, '{"k":{"a":1,"n":{"d":"deep"}}}\n') + + def test_map_of_json_string_value_input(self): + # JSON given as text is parsed by the write path, same as for + # top-level JSON columns. + with self.create_table("a Map(String, JSON)"): + self.client.execute( + "INSERT INTO test (a) VALUES", [({"k": '{"s": 1}'},)]) + result = self.client.execute("SELECT * FROM test") + self.assertEqual(result, [({"k": {"s": 1}},)]) + + def test_array_of_json(self): + with self.create_table("a Array(JSON)"): + data = [ + ([{"a": 1}, {"b": "x"}],), + ([],), + ([{"c": [1, 2, 3]}],), + ] + self.client.execute("INSERT INTO test (a) VALUES", data) + result = self.client.execute("SELECT * FROM test") + self.assertEqual(result, data) + + def test_tuple_with_json(self): + with self.create_table("a Tuple(String, JSON)"): + data = [ + (("s1", {"a": 1}),), + (("s2", {"b": {"c": "deep"}}),), + ] + self.client.execute("INSERT INTO test (a) VALUES", data) + result = self.client.execute("SELECT * FROM test") + self.assertEqual(result, data) + + def test_map_of_array_of_json(self): + with self.create_table("a Map(String, Array(JSON))"): + data = [ + ({"k": [{"a": 1}], "l": [{"b": 2}, {"c": 3}]},), + ({},), + ] + self.client.execute("INSERT INTO test (a) VALUES", data) + result = self.client.execute("SELECT * FROM test") + self.assertEqual(result, data) + + def test_array_of_array_of_json(self): + with self.create_table("a Array(Array(JSON))"): + data = [ + ([[{"a": 1}], [{"b": 2}, {"c": 3}]],), + ([[]],), + ] + self.client.execute("INSERT INTO test (a) VALUES", data) + result = self.client.execute("SELECT * FROM test") + self.assertEqual(result, data) + + def test_map_of_nullable_json(self): + with self.create_table("a Map(String, Nullable(JSON))"): + data = [({"k": {"a": 1}, "n": None},)] + self.client.execute("INSERT INTO test (a) VALUES", data) + result = self.client.execute("SELECT * FROM test") + self.assertEqual(result, data) + + def test_array_of_nullable_json(self): + with self.create_table("a Array(Nullable(JSON))"): + data = [([{"a": 1}, None, {"b": 2}],)] + self.client.execute("INSERT INTO test (a) VALUES", data) + result = self.client.execute("SELECT * FROM test") + self.assertEqual(result, data) + + def test_map_of_map_of_json(self): + with self.create_table("a Map(String, Map(String, JSON))"): + data = [({"outer": {"inner": {"a": 1}}},)] + self.client.execute("INSERT INTO test (a) VALUES", data) + result = self.client.execute("SELECT * FROM test") + self.assertEqual(result, data) + + +class JSONWireRoundTripTestCase(TestCase): + # Which server versions run the integration tests above is a matrix + # choice, so the JSON write path would go uncovered on jobs against + # servers without JSON support. Serialize and deserialize a block + # locally so every line is exercised deterministically on every + # job. Wire compatibility itself is covered by the server-backed + # tests. + + def make_context(self): + context = Context() + context.client_settings = { + 'use_numpy': False, + 'strings_as_bytes': False, + } + context.settings = {} + return context + + def round_trip(self, spec, items): + context = self.make_context() + + sink = BytesIO() + write_buf = CompressedBufferedWriter(sink, 1024) + # prepare_items mutates the list it is given (e.g. None -> + # null_value); write a copy so `items` stays comparable. + write_column(context, 'a', spec, list(items), write_buf) + write_buf.flush() + + chunks = [sink.getvalue()] + read_buf = CompressedBufferedReader( + lambda: chunks.pop() if chunks else b'', 1024) + return list(read_column(context, spec, len(items), read_buf)) + + def test_json(self): + items = [ + {'i': 1, 'f': 2.5, 's': 'x', 'b': True, 'n': {'d': 'deep'}}, + {'list': [1, 2], 'strings': ['a', 'b']}, + {}, + ] + self.assertEqual(self.round_trip('JSON', items), items) + + def test_nullable_json(self): + items = [None, {'x': 1}, None] + self.assertEqual(self.round_trip('Nullable(JSON)', items), items) + + def test_map_of_json(self): + items = [ + {'k': {'a': 1}, 'j': {'b': 'x'}}, + {}, + {'empty': {}}, + ] + self.assertEqual(self.round_trip('Map(String, JSON)', items), items) + + def test_array_of_json(self): + items = [ + [{'a': 1}, {'b': 'x'}], + [], + ] + self.assertEqual(self.round_trip('Array(JSON)', items), items) + + def test_array_of_nullable_json(self): + items = [[{'a': 1}, None]] + self.assertEqual( + self.round_trip('Array(Nullable(JSON))', items), items) + + def test_tuple_with_json(self): + items = [('s1', {'a': 1}), ('s2', {'b': 2})] + self.assertEqual( + self.round_trip('Tuple(String, JSON)', items), items) + + def test_map_of_array_of_json(self): + items = [{'k': [{'a': 1}], 'l': [{'b': 2}, {'c': 3}]}] + self.assertEqual( + self.round_trip('Map(String, Array(JSON))', items), items) + + def test_write_state_prefix_requires_items(self): + from clickhouse_driver.columns.service import get_column_by_spec + + column = get_column_by_spec( + 'JSON', {'context': self.make_context()}, use_numpy=False) + with self.assertRaises(NotImplementedError): + column.write_state_prefix(BytesIO(), None) diff --git a/tests/columns/test_sparse.py b/tests/columns/test_sparse.py index e7ae8616..f41dd4cc 100644 --- a/tests/columns/test_sparse.py +++ b/tests/columns/test_sparse.py @@ -1,7 +1,12 @@ from datetime import date +from io import BytesIO +from ipaddress import IPv6Address +from unittest import TestCase from tests.testcase import BaseTestCase from clickhouse_driver import errors +from clickhouse_driver.columns.base import SparseSerialization +from clickhouse_driver.varint import write_varint ErrorCodes = errors.ErrorCodes @@ -102,6 +107,31 @@ def test_sparse_tuples(self): inserted = self.client.execute(query) self.assertEqual(inserted, data) + def test_sparse_ipv6(self): + columns = 'a IPv6' + + data = [ + (IPv6Address('::'), ), + (IPv6Address('::'), ), + (IPv6Address('2001:db8::1'), ), + ] + with self.create_table(columns): + self.client.execute( + 'INSERT INTO test VALUES', data + ) + + query = 'SELECT * FROM test' + inserted = self.emit_cli(query) + self.assertEqual( + inserted, + '::\n' + '::\n' + '2001:db8::1\n' + ) + + inserted = self.client.execute(query) + self.assertEqual(inserted, data) + def test_sparse_dates(self): columns = 'a Date32' @@ -124,3 +154,49 @@ def test_sparse_dates(self): inserted = self.client.execute(query) self.assertEqual(inserted, data) + + +class FakeColumn(object): + null_value = 0 + after_read_items = None + + +class SparseSerializationTestCase(TestCase): + # Sending sparse blocks is the server's choice; test directly. + + END_OF_GRANULE_FLAG = 1 << 62 + + def make_buf(self, group_sizes): + buf = BytesIO() + for size in group_sizes: + write_varint(size, buf) + buf.seek(0) + buf.read_one = lambda: ord(buf.read(1)) + return buf + + def test_read_and_apply_sparse(self): + serialization = SparseSerialization(FakeColumn()) + + # Non-default items at positions 3 and 7 of [0,0,5,0,0,0,7,0]. + buf = self.make_buf([2, 3, self.END_OF_GRANULE_FLAG | 1]) + n_items = serialization.read_sparse(8, buf) + + self.assertEqual(n_items, 2) + self.assertEqual(serialization.sparse_indexes, [3, 7]) + self.assertEqual(serialization.items_total, 9) + self.assertEqual( + serialization.apply_sparse([5, 7]), + [0, 0, 5, 0, 0, 0, 7, 0] + ) + + def test_apply_sparse_with_after_read_items(self): + column = FakeColumn() + column.after_read_items = lambda items, nulls_map=None: \ + tuple(x + 100 for x in items) + serialization = SparseSerialization(column) + + buf = self.make_buf([0, self.END_OF_GRANULE_FLAG | 1]) + n_items = serialization.read_sparse(3, buf) + + self.assertEqual(n_items, 1) + self.assertEqual(serialization.apply_sparse([105]), [105, 100]) diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml index e0fd290f..5e17583a 100644 --- a/tests/docker-compose.yml +++ b/tests/docker-compose.yml @@ -2,7 +2,7 @@ version: '3' services: clickhouse-server: - image: "$ORG/clickhouse-server:$VERSION" + image: "$ORG/clickhouse-server:$CLICKHOUSE_VERSION" container_name: test-clickhouse-server environment: - TZ=Europe/Moscow @@ -11,10 +11,11 @@ services: - "127.0.0.1:9440:9440" volumes: - "./clickhouse_server_config/$TOP_LEVEL.xml:/etc/clickhouse-server/config.d/test_config.xml" + - "./clickhouse_server_config/${TOP_LEVEL}_users.xml:/etc/clickhouse-server/users.d/test_users.xml" - "./clickhouse_server_config/certs:/etc/clickhouse-server/certs" clickhouse-client: - image: "$ORG/clickhouse-server:$VERSION" + image: "$ORG/clickhouse-server:$CLICKHOUSE_VERSION" container_name: test-clickhouse-client entrypoint: /bin/sh command: [-c, 'while :; do sleep 1; done'] diff --git a/tests/numpy/columns/test_low_cardinality.py b/tests/numpy/columns/test_low_cardinality.py index 5f32eec6..781bad1f 100644 --- a/tests/numpy/columns/test_low_cardinality.py +++ b/tests/numpy/columns/test_low_cardinality.py @@ -73,9 +73,12 @@ def test_nullable_int8(self): self.assertEqual(inserted, '\\N\n-1\n0\n1\n\\N\n') inserted = self.client.execute(query, columnar=True) + # pandas 3.x: Categorical.astype(str) preserves missing as NaN, and + # NaN != NaN. Substitute a sentinel so equality holds. self.assertArraysEqual( - inserted[0].astype(str), - pd.Categorical(data[0]).astype(str) + pd.Series(inserted[0]).astype(object).fillna('\\N').to_numpy(), + pd.Series(pd.Categorical(data[0])) + .astype(object).fillna('\\N').to_numpy(), ) self.assertIsInstance(inserted[0], pd.Categorical) @@ -213,7 +216,11 @@ def test_nullable_string(self): ) inserted = self.client.execute(query, columnar=True) + # pandas 3.x: Categorical.astype(str) preserves missing as NaN, and + # NaN != NaN. Substitute a sentinel so equality holds. self.assertArraysEqual( - inserted[0].astype(str), pd.Categorical(data[0]).astype(str) + pd.Series(inserted[0]).astype(object).fillna('\\N').to_numpy(), + pd.Series(pd.Categorical(data[0])) + .astype(object).fillna('\\N').to_numpy(), ) self.assertIsInstance(inserted[0], pd.Categorical) diff --git a/tests/numpy/test_generic.py b/tests/numpy/test_generic.py index 62c28f87..ef79de63 100644 --- a/tests/numpy/test_generic.py +++ b/tests/numpy/test_generic.py @@ -55,10 +55,13 @@ def test_with_column_types(self): class NumpyProgressTestCase(NumpyBaseTestCase): def test_select_with_progress(self): progress = self.client.execute_with_progress('SELECT 2') - self.assertEqual( - list(progress), - [(1, 0), (1, 0)] if self.server_version > (20,) else [(1, 0)] - ) + if self.server_version > (20,): + # total_rows in progress depends on server version + self.assertIn( + list(progress), ([(1, 0), (1, 0)], [(1, 1), (1, 1)]) + ) + else: + self.assertEqual(list(progress), [(1, 0)]) self.assertEqual(progress.get_result(), [(2,)]) self.assertTrue(self.client.connection.connected) diff --git a/tests/test_blocks.py b/tests/test_blocks.py index ff992678..0fbc068d 100644 --- a/tests/test_blocks.py +++ b/tests/test_blocks.py @@ -54,7 +54,10 @@ def test_columnar_block_extend(self): query = 'SELECT * FROM test ORDER BY a' - inserted = self.client.execute(query, columnar=True) + # One row per block even if the two parts get merged. + inserted = self.client.execute( + query, columnar=True, settings={'max_block_size': 1} + ) self.assertEqual(inserted, [(1, 2)]) def test_select_with_column_types(self): @@ -85,10 +88,15 @@ def test_close_connection_on_keyboard_interrupt(self): class ProgressTestCase(BaseTestCase): def test_select_with_progress(self): progress = self.client.execute_with_progress('SELECT 2') - self.assertEqual( - list(progress), - [(1, 0), (1, 0)] if self.server_version > (20,) else [(1, 0)] - ) + # CH 25 reports 1 byte per progress chunk for trivial selects; + # earlier versions reported 0. + if self.server_version >= (25,): + expected = [(1, 1), (1, 1)] + elif self.server_version > (20,): + expected = [(1, 0), (1, 0)] + else: + expected = [(1, 0)] + self.assertEqual(list(progress), expected) self.assertEqual(progress.get_result(), [(2,)]) self.assertTrue(self.client.connection.connected) @@ -102,7 +110,11 @@ def test_progress_totals(self): self.assertEqual(progress.progress_totals.rows, 1) self.assertEqual(progress.progress_totals.bytes, 1) - self.assertEqual(progress.progress_totals.total_rows, 0) + # CH 25 sets total_rows for trivial selects to 1; earlier + # versions left it at 0. + expected_total_rows = 1 if self.server_version >= (25,) else 0 + self.assertEqual( + progress.progress_totals.total_rows, expected_total_rows) def test_select_with_progress_error(self): with self.assertRaises(ServerException): diff --git a/tests/test_cityhash.py b/tests/test_cityhash.py new file mode 100644 index 00000000..a64146e8 --- /dev/null +++ b/tests/test_cityhash.py @@ -0,0 +1,42 @@ +from unittest import TestCase + +from clickhouse_driver._cityhash.cityhash import CityHash128 + + +class CityHash128TestCase(TestCase): + # Golden values for the vendored CityHash 1.0.2 algorithm. ClickHouse + # hashes compressed blocks with this exact version, so these must never + # change -- a mismatch means we broke wire compatibility with the server. + GOLDEN = { + b'': 82332263323914296566372529678324145705, + b'a': 279725777567359144512642526446120103158, + b'abc': 191491615738686005514802259311635598718, + b'hello world': 167458446662975529045819099149800539344, + b'x' * 63: 315746516683536713704198863747634701618, + b'x' * 64: 201844484092394838928428687108119794129, + b'x' * 65: 245755329935730809217271693433052602484, + bytes(range(256)): 67103632049168710853453900228853218707, + } + + def test_golden_vectors(self): + for data, expected in self.GOLDEN.items(): + self.assertEqual(CityHash128(data), expected) + + def test_result_is_128_bit_int(self): + value = CityHash128(b'abc') + self.assertIsInstance(value, int) + self.assertTrue(0 <= value < (1 << 128)) + + def test_str_matches_utf8_bytes(self): + self.assertEqual(CityHash128('abracadabra'), + CityHash128('abracadabra'.encode('utf-8'))) + + def test_empty_str_matches_empty_bytes(self): + self.assertEqual(CityHash128(''), CityHash128(b'')) + + def test_buffer_matches_bytes(self): + self.assertEqual(CityHash128(memoryview(b'abc')), CityHash128(b'abc')) + + def test_rejects_unsupported_type(self): + with self.assertRaises(TypeError): + CityHash128(123) diff --git a/tests/test_query_info.py b/tests/test_query_info.py index 0b74344b..e746f5df 100644 --- a/tests/test_query_info.py +++ b/tests/test_query_info.py @@ -33,7 +33,11 @@ def test_store_last_query_after_execute(self): self.assertIsNotNone(last_query.progress) self.assertEqual(last_query.progress.rows, 42) self.assertEqual(last_query.progress.bytes, 42) - self.assertEqual(last_query.progress.total_rows, 0) + # CH 25 fills total_rows with the actual row count; + # earlier versions left it at 0. + expected_total_rows = 42 if self.server_version >= (25,) else 0 + self.assertEqual( + last_query.progress.total_rows, expected_total_rows) if self.server_version > (22, 8): self.assertGreater(last_query.progress.elapsed_ns, 0) @@ -51,7 +55,11 @@ def test_last_query_after_execute_iter(self): self.assertIsNotNone(last_query.progress) self.assertEqual(last_query.progress.rows, 42) self.assertEqual(last_query.progress.bytes, 42) - self.assertEqual(last_query.progress.total_rows, 0) + # CH 25 fills total_rows with the actual row count; + # earlier versions left it at 0. + expected_total_rows = 42 if self.server_version >= (25,) else 0 + self.assertEqual( + last_query.progress.total_rows, expected_total_rows) if self.server_version > (22, 8): self.assertGreater(last_query.progress.elapsed_ns, 0) @@ -71,7 +79,11 @@ def test_last_query_after_execute_with_progress(self): self.assertIsNotNone(last_query.progress) self.assertEqual(last_query.progress.rows, 42) self.assertEqual(last_query.progress.bytes, 42) - self.assertEqual(last_query.progress.total_rows, 0) + # CH 25 fills total_rows with the actual row count; + # earlier versions left it at 0. + expected_total_rows = 42 if self.server_version >= (25,) else 0 + self.assertEqual( + last_query.progress.total_rows, expected_total_rows) if self.server_version > (22, 8): self.assertGreater(last_query.progress.elapsed_ns, 0) diff --git a/tests/test_substitution.py b/tests/test_substitution.py index 800759fd..2fa7ec9a 100644 --- a/tests/test_substitution.py +++ b/tests/test_substitution.py @@ -271,6 +271,50 @@ def test_escaped_str(self): ) self.assertEqual(rv, [("'", 1)]) + def test_array(self): + rv = self.client.execute( + 'SELECT {x:Array(String)}', {'x': ['a', 'b', 'c']} + ) + self.assertEqual(rv, [(['a', 'b', 'c'], )]) + + rv = self.client.execute( + 'SELECT {x:Array(UInt8)}', {'x': [1, 2, 3]} + ) + self.assertEqual(rv, [([1, 2, 3], )]) + + rv = self.client.execute('SELECT {x:Array(String)}', {'x': []}) + self.assertEqual(rv, [([], )]) + + def test_array_escaped(self): + rv = self.client.execute( + 'SELECT {x:Array(String)}', {'x': ["a'b", 'c\\d', 'e\tf']} + ) + self.assertEqual(rv, [(["a'b", 'c\\d', 'e\tf'], )]) + + def test_array_nullable(self): + rv = self.client.execute( + 'SELECT {x:Array(Nullable(String))}', {'x': ['a', None]} + ) + self.assertEqual(rv, [(['a', None], )]) + + def test_tuple(self): + rv = self.client.execute( + 'SELECT {x:Tuple(UInt8, String)}', {'x': (1, 'a')} + ) + self.assertEqual(rv, [((1, 'a'), )]) + + def test_nested(self): + rv = self.client.execute( + 'SELECT {x:Array(Tuple(UInt8, String))}', + {'x': [(1, 'a'), (2, 'b')]} + ) + self.assertEqual(rv, [([(1, 'a'), (2, 'b')], )]) + + rv = self.client.execute( + 'SELECT {x:Array(Array(String))}', {'x': [["a'b"], []]} + ) + self.assertEqual(rv, [([["a'b"], []], )]) + class NoServerSideParametersSubstitutionTestCase(BaseTestCase): def test_reserved_keywords(self): diff --git a/testsrequire.py b/testsrequire.py index 06c98cc4..de769e96 100644 --- a/testsrequire.py +++ b/testsrequire.py @@ -1,14 +1,14 @@ import os import sys -USE_NUMPY = bool(int(os.getenv('USE_NUMPY', '0'))) +USE_NUMPY = bool(int(os.getenv('USE_NUMPY') or '0')) +USE_ARROW = bool(int(os.getenv('USE_ARROW') or '0')) tests_require = [ 'pytest', 'parameterized', 'freezegun', - 'zstd', - 'clickhouse-cityhash>=1.0.2.1' + 'zstd' ] if sys.implementation.name == 'pypy': @@ -19,6 +19,9 @@ if USE_NUMPY: tests_require.extend(['numpy', 'pandas']) +if USE_ARROW: + tests_require.append('pyarrow') + try: from pip import main as pipmain except ImportError: