From cb89c084b131ef362b2b8e9dee4f99aa257db03d Mon Sep 17 00:00:00 2001 From: Conor McCarthy Date: Tue, 10 Oct 2023 09:08:35 +0100 Subject: [PATCH] Updates for 2.1 release --- conda-recipe/meta.yaml | 5 +- custom_theme/main.html | 11 + docs/api/pykx-q-data/type_conversions.md | 1710 +- docs/api/serialize.md | 3 + docs/extras/comparisons.md | 2 +- docs/extras/known_issues.md | 5 + docs/faq.md | 2 +- docs/getting-started/installing.md | 1 + docs/getting-started/interface_overview.ipynb | 49 +- docs/getting-started/quickstart.md | 16 +- docs/index.md | 50 +- docs/pykx-under-q/api.md | 8 +- docs/pykx-under-q/intro.md | 63 +- docs/pykx-under-q/upgrade.md | 6 +- docs/release-notes/changelog.md | 274 +- docs/release-notes/underq-changelog.md | 34 +- docs/spelling.txt | 7 + docs/user-guide/advanced/Pandas_API.ipynb | 23 +- docs/user-guide/advanced/attributes.md | 2 +- docs/user-guide/advanced/context_interface.md | 2 +- docs/user-guide/advanced/modes.md | 10 +- docs/user-guide/advanced/performance.md | 4 +- docs/user-guide/configuration.md | 14 +- docs/user-guide/fundamentals/creating.md | 46 +- docs/user-guide/fundamentals/indexing.md | 2 +- .../fundamentals/nulls_and_infinities.md | 4 +- docs/user-guide/fundamentals/text.md | 113 + docs/user-guide/index.md | 2 +- examples/notebooks/interface_overview.ipynb | 49 +- mkdocs.yml | 6 + pyproject.toml | 9 +- src/pykx/__init__.py | 9 +- src/pykx/_ipc.pxd | 8 +- src/pykx/_ipc.pyx | 4 +- src/pykx/_numpy.c | 6 +- src/pykx/_wrappers.pyx | 32 +- src/pykx/config.py | 8 +- src/pykx/core.pxd | 136 +- src/pykx/core.pyx | 110 +- src/pykx/include/foreign.h | 6 +- src/pykx/include/k.h | 119 +- src/pykx/include/py.h | 173 +- src/pykx/include/unlicensed_getitem.h | 12 +- src/pykx/include/vector_conversion.h | 6 +- src/pykx/ipc.py | 107 +- src/pykx/lib/kxic.k | 1 - src/pykx/nbextension.py | 6 +- src/pykx/numpy_conversions.c | 6 +- src/pykx/pandas_api/pandas_indexing.py | 4 +- src/pykx/pandas_api/pandas_meta.py | 3 +- src/pykx/pykx.c | 52 +- src/pykx/pykx.q | 99 +- src/pykx/pykx_init.q_ | Bin 3124 -> 3194 bytes src/pykx/pykxq.c | 36 +- src/pykx/read.py | 64 +- src/pykx/reimporter.py | 3 + src/pykx/serialize.py | 123 + src/pykx/system.py | 5 +- src/pykx/toq.pyx | 189 +- src/pykx/wrappers.py | 305 +- tests/__init__.py | 2 +- tests/qcumber_tests/conversions.quke | 5 +- tests/qinit.q | 1 + tests/test_license.py | 2 +- tests/test_pandas_api.py | 4 +- tests/test_pykx.py | 17 + tests/test_read.py | 15 + tests/test_repr_html_.ipynb | 15878 ++++++++++++++++ tests/test_system.py | 5 + tests/test_toq.py | 59 + tests/test_wrappers.py | 493 +- 71 files changed, 19090 insertions(+), 1555 deletions(-) create mode 100644 custom_theme/main.html create mode 100644 docs/api/serialize.md create mode 100644 docs/user-guide/fundamentals/text.md create mode 100644 src/pykx/serialize.py create mode 100644 tests/qinit.q create mode 100644 tests/test_repr_html_.ipynb diff --git a/conda-recipe/meta.yaml b/conda-recipe/meta.yaml index 1018058..fab0bcf 100644 --- a/conda-recipe/meta.yaml +++ b/conda-recipe/meta.yaml @@ -18,7 +18,7 @@ requirements: - python - setuptools==60.9.3 - setuptools_scm[toml]>=6.0.1 - - cython==3.0.0a11 + - cython==3.0.0 - numpy==1.22.* - tomli>=2.0.1 - wheel>=0.36.2 @@ -29,6 +29,7 @@ requirements: - numpy>=1.22 - pandas>=1.2,<2.0 - pytz>=2022.1 + - toml>=0.10.2 test: imports: @@ -37,4 +38,4 @@ test: about: license_file: - LICENSE.txt - home: https://code.kx.com/pykx/ \ No newline at end of file + home: https://code.kx.com/pykx/ diff --git a/custom_theme/main.html b/custom_theme/main.html new file mode 100644 index 0000000..bffbb07 --- /dev/null +++ b/custom_theme/main.html @@ -0,0 +1,11 @@ +{% extends "base.html" %} + +{% block extrahead %} + + + +{% endblock %} diff --git a/docs/api/pykx-q-data/type_conversions.md b/docs/api/pykx-q-data/type_conversions.md index c5922ea..27f289e 100644 --- a/docs/api/pykx-q-data/type_conversions.md +++ b/docs/api/pykx-q-data/type_conversions.md @@ -29,60 +29,57 @@ A breakdown of each of the `pykx.K` types and their analogous `numpy`, `pandas`, ## `pykx.List` -**Python** - -A python list of mixed types will be converted into a `pykx.List`. - -```Python ->>> pykx.List([1, b'foo', 'bar', 4.5]) -pykx.List(pykx.q(' -1 -"foo" -`bar -4.5 -')) -``` - -Calling `.py()` on a `pykx.List` will return a generic python list object where each object is converted into its analogous python type. - -```Python ->>> pykx.List([1, b'foo', 'bar', 4.5]).py() -[1, b'foo', 'bar', 4.5] -``` - -**Numpy** - -A numpy list with `dtype==object` containing data of mixed types will be converted into a `pykx.List` - -```Python ->>> pykx.List(np.array([1, b'foo', 'bar', 4.5], dtype=object)) -pykx.List(pykx.q(' -1 -"foo" -`bar -4.5 -')) -``` - -Calling `.np()` on a `pykx.List` object will return a numpy `ndarray` with `dtype==object` where each element has been converted into its closest analogous python type. - -```Python ->>> pykx.List([1, b'foo', 'bar', 4.5]).np() -array([1, b'foo', 'bar', 4.5], dtype=object) -``` - -**Pandas** - -Calling `.pd()` on a `pykx.List` object will return a pandas `Series` with `dtype==object` where each element has been converted into its closest analogous python type. - -```Python ->>> pykx.List([1, b'foo', 'bar', 4.5]).pd() -0 1 -1 b'foo' -2 bar -3 4.5 -dtype: object -``` +=== "Python" + A python list of mixed types will be converted into a `pykx.List`. + + ```Python + >>> pykx.List([1, b'foo', 'bar', 4.5]) + pykx.List(pykx.q(' + 1 + "foo" + `bar + 4.5 + ')) + ``` + + Calling `.py()` on a `pykx.List` will return a generic python list object where each object is converted into its analogous python type. + + ```Python + >>> pykx.List([1, b'foo', 'bar', 4.5]).py() + [1, b'foo', 'bar', 4.5] + ``` + +=== "Numpy" + A numpy list with `dtype==object` containing data of mixed types will be converted into a `pykx.List` + + ```Python + >>> pykx.List(np.array([1, b'foo', 'bar', 4.5], dtype=object)) + pykx.List(pykx.q(' + 1 + "foo" + `bar + 4.5 + ')) + ``` + + Calling `.np()` on a `pykx.List` object will return a numpy `ndarray` with `dtype==object` where each element has been converted into its closest analogous python type. + + ```Python + >>> pykx.List([1, b'foo', 'bar', 4.5]).np() + array([1, b'foo', 'bar', 4.5], dtype=object) + ``` + +=== "Pandas" + Calling `.pd()` on a `pykx.List` object will return a pandas `Series` with `dtype==object` where each element has been converted into its closest analogous python type. + + ```Python + >>> pykx.List([1, b'foo', 'bar', 4.5]).pd() + 0 1 + 1 b'foo' + 2 bar + 3 4.5 + dtype: object + ``` ## `pykx.BooleanAtom` @@ -104,1124 +101,1061 @@ True ## `pykx.BooleanVector` -**Python** - -A list of python bool types will be converted into a `pykx.BooleanVector`. - -```Python ->>> pykx.BooleanVector([True, False, True]) -pykx.BooleanVector(pykx.q('101b')) -``` +=== "Python" + A list of python bool types will be converted into a `pykx.BooleanVector`. -Calling `.py()` on a `pykx.BooleanVector` will return a list of python bool objects. + ```Python + >>> pykx.BooleanVector([True, False, True]) + pykx.BooleanVector(pykx.q('101b')) + ``` -```Python ->>> pykx.BooleanVector([True, False, True]).py() -[True, False, True] -``` + Calling `.py()` on a `pykx.BooleanVector` will return a list of python bool objects. -**Numpy, Pandas, Pyarrow** + ```Python + >>> pykx.BooleanVector([True, False, True]).py() + [True, False, True] + ``` -Converting a `pykx.BoolVector` will result in an array of objects with the `bool` `dtype`, arrays of that `dtype` can also be converted into `pykx.BoolVector` objects. +=== "Numpy, Pandas, Pyarrow" + Converting a `pykx.BoolVector` will result in an array of objects with the `bool` `dtype`, arrays of that `dtype` can also be converted into `pykx.BoolVector` objects. ## `pykx.GUIDAtom` -**Python** +=== "Python" + The python uuid4 type from the `uuid` library will be converted into a `pykx.GUIDAtom`. -The python uuid4 type from the `uuid` library will be converted into a `pykx.GUIDAtom`. + ```Python + >>> from uuid import uuid4 + >>> pykx.GUIDAtom(uuid4()) + pykx.GUIDAtom(pykx.q('012e8fb7-52c4-49e6-9b4e-93aa625ca3d7')) + ``` -```Python ->>> from uuid import uuid4 ->>> pykx.GUIDAtom(uuid4()) -pykx.GUIDAtom(pykx.q('012e8fb7-52c4-49e6-9b4e-93aa625ca3d7')) -``` + Calling `.py()` on a `pykx.GUIDAtom` will return a python uuid4 object. -Calling `.py()` on a `pykx.GUIDAtom` will return a python uuid4 object. - -```Python ->>> pykx.GUIDAtom(uuid4()).py() -UUID('d16f9f3f-2a57-4dfd-818e-04c9c7a53584') -``` + ```Python + >>> pykx.GUIDAtom(uuid4()).py() + UUID('d16f9f3f-2a57-4dfd-818e-04c9c7a53584') + ``` ## `pykx.GUIDVector` -**Python** +=== "Python" + A list of python uuid4 types from the `uuid` library will be converted into a `pykx.GUIDVector`. -A list of python uuid4 types from the `uuid` library will be converted into a `pykx.GUIDVector`. + ```Python + >>> pykx.GUIDVector([uuid4(), uuid4()]) + pykx.GUIDVector(pykx.q('542ccbef-8aa1-4433-804a-7928172ec2d4 ff6f89fb-1aec-4073-821a-ce281ca6263e')) + ``` -```Python ->>> pykx.GUIDVector([uuid4(), uuid4()]) -pykx.GUIDVector(pykx.q('542ccbef-8aa1-4433-804a-7928172ec2d4 ff6f89fb-1aec-4073-821a-ce281ca6263e')) -``` + Calling `.py()` on a `pykx.GUIDVector` will return a list of python uuid4 objects. -Calling `.py()` on a `pykx.GUIDVector` will return a list of python uuid4 objects. + ```Python + >>> pykx.GUIDVector([uuid4(), uuid4()]).py() + [UUID('a3b284fc-5f31-4ba2-b521-fa8b5c309e02'), UUID('95ee9044-3930-492c-96f2-e336110de023')] + ``` -```Python ->>> pykx.GUIDVector([uuid4(), uuid4()]).py() -[UUID('a3b284fc-5f31-4ba2-b521-fa8b5c309e02'), UUID('95ee9044-3930-492c-96f2-e336110de023')] -``` - -**Numpy, Pandas, PyArrow** - -Each of these will return an array of their respective object types around a list of uuid4 objects. +=== "Numpy, Pandas, PyArrow" + Each of these will return an array of their respective object types around a list of uuid4 objects. ## `pykx.ByteAtom` -**Python** +=== "Python" + The python int type will be converted into a `pykx.ByteAtom`. -The python int type will be converted into a `pykx.ByteAtom`. + Float types will also be converted but the decimal will be truncated away and no rounding done. -Float types will also be converted but the decimal will be truncated away and no rounding done. + ```Python + >>> pykx.ByteAtom(1.0) + pykx.ByteAtom(pykx.q('0x01')) + >>> pykx.ByteAtom(1.5) + pykx.ByteAtom(pykx.q('0x01')) + ``` -```Python ->>> pykx.ByteAtom(1.0) -pykx.ByteAtom(pykx.q('0x01')) ->>> pykx.ByteAtom(1.5) -pykx.ByteAtom(pykx.q('0x01')) -``` + Calling `.py()` on a `pykx.ByteAtom` will return a python int object. -Calling `.py()` on a `pykx.ByteAtom` will return a python int object. - -```Python ->>> pykx.ByteAtom(1.5).py() -1 -``` + ```Python + >>> pykx.ByteAtom(1.5).py() + 1 + ``` ## `pykx.ByteVector` -**Python** - -A list of python int types will be converted into a `pykx.ByteVector`. - -Float types will also be converted but the decimal will be truncated away and no rounding done. +=== "Python" + A list of python int types will be converted into a `pykx.ByteVector`. -```Python ->>> pykx.ByteVector([1, 2.5]) -pykx.ByteVector(pykx.q('0x0102')) -``` + Float types will also be converted but the decimal will be truncated away and no rounding done. -Calling `.py()` on a `pykx.ByteVector` will return a list of python int objects. + ```Python + >>> pykx.ByteVector([1, 2.5]) + pykx.ByteVector(pykx.q('0x0102')) + ``` -```Python ->>> pykx.ByteVector([1, 2.5]).py() -[1, 2] -``` + Calling `.py()` on a `pykx.ByteVector` will return a list of python int objects. -**Numpy, Pandas, PyArrow** + ```Python + >>> pykx.ByteVector([1, 2.5]).py() + [1, 2] + ``` -Converting a `pykx.ByteVector` will result in an array of objects with the `uint8` `dtype`, arrays of that `dtype` can also be converted into `pykx.ByteVector` objects. +=== "Numpy, Pandas, PyArrow" + Converting a `pykx.ByteVector` will result in an array of objects with the `uint8` `dtype`, arrays of that `dtype` can also be converted into `pykx.ByteVector` objects. ## `pykx.ShortAtom` -**Python** +=== "Python" + The python int type will be converted into a `pykx.ShortAtom`. -The python int type will be converted into a `pykx.ShortAtom`. + Float types will also be converted but the decimal will be truncated away and no rounding done. -Float types will also be converted but the decimal will be truncated away and no rounding done. + ```Python + >>> pykx.ShortAtom(1) + pykx.ShortAtom(pykx.q('1h')) + >>> pykx.ShortAtom(1.5) + pykx.ShortAtom(pykx.q('1h')) + ``` -```Python ->>> pykx.ShortAtom(1) -pykx.ShortAtom(pykx.q('1h')) ->>> pykx.ShortAtom(1.5) -pykx.ShortAtom(pykx.q('1h')) -``` - -Calling `.py()` on a `pykx.ShortAtom` will return a python int object. + Calling `.py()` on a `pykx.ShortAtom` will return a python int object. -```Python ->>> pykx.ShortAtom(1.5).py() -1 -``` + ```Python + >>> pykx.ShortAtom(1.5).py() + 1 + ``` ## `pykx.ShortVector` -**Python** +=== "Python" + A list of python int types will be converted into a `pykx.ShortVector`. -A list of python int types will be converted into a `pykx.ShortVector`. + Float types will also be converted but the decimal will be truncated away and no rounding done. -Float types will also be converted but the decimal will be truncated away and no rounding done. + ```Python + >>> pykx.ShortVector([1, 2.5]) + pykx.ShortVector(pykx.q('1 2h')) + ``` -```Python ->>> pykx.ShortVector([1, 2.5]) -pykx.ShortVector(pykx.q('1 2h')) -``` - -Calling `.py()` on a `pykx.ShortVector` will return a list of python int objects. - -```Python ->>> pykx.ShortVector([1, 2.5]).py() -[1, 2] -``` + Calling `.py()` on a `pykx.ShortVector` will return a list of python int objects. -**Numpy, Pandas, PyArrow** + ```Python + >>> pykx.ShortVector([1, 2.5]).py() + [1, 2] + ``` -Converting a `pykx.ShortVector` will result in an array of objects with the `int16` `dtype`, arrays of that `dtype` can also be converted into `pykx.ShortVector` objects. +=== "Numpy, Pandas, PyArrow" + Converting a `pykx.ShortVector` will result in an array of objects with the `int16` `dtype`, arrays of that `dtype` can also be converted into `pykx.ShortVector` objects. ## `pykx.IntAtom` -**Python** - -The python int type will be converted into a `pykx.IntAtom`. +=== "Python" + The python int type will be converted into a `pykx.IntAtom`. -Float types will also be converted but the decimal will be truncated away and no rounding done. + Float types will also be converted but the decimal will be truncated away and no rounding done. -```Python ->>> pykx.IntAtom(1) -pykx.IntAtom(pykx.q('1i')) ->>> pykx.IntAtom(1.5) -pykx.IntAtom(pykx.q('1i')) -``` + ```Python + >>> pykx.IntAtom(1) + pykx.IntAtom(pykx.q('1i')) + >>> pykx.IntAtom(1.5) + pykx.IntAtom(pykx.q('1i')) + ``` -Calling `.py()` on a `pykx.IntAtom` will return a python int object. + Calling `.py()` on a `pykx.IntAtom` will return a python int object. -```Python ->>> pykx.IntAtom(1.5).py() -1 -``` + ```Python + >>> pykx.IntAtom(1.5).py() + 1 + ``` ## `pykx.IntVector` -**Python** - -A list of python int types will be converted into a `pykx.IntVector`. - -Float types will also be converted but the decimal will be truncated away and no rounding done. +=== "Python" + A list of python int types will be converted into a `pykx.IntVector`. -```Python ->>> pykx.IntVector([1, 2.5]) -pykx.IntVector(pykx.q('1 2i')) -``` + Float types will also be converted but the decimal will be truncated away and no rounding done. -Calling `.py()` on a `pykx.IntVector` will return a list of python int objects. + ```Python + >>> pykx.IntVector([1, 2.5]) + pykx.IntVector(pykx.q('1 2i')) + ``` -```Python ->>> pykx.IntVector([1, 2.5]).py() -[1, 2] -``` + Calling `.py()` on a `pykx.IntVector` will return a list of python int objects. -**Numpy, Pandas, PyArrow** + ```Python + >>> pykx.IntVector([1, 2.5]).py() + [1, 2] + ``` -Converting a `pykx.IntVector` will result in an array of objects with the `int32` `dtype`, arrays of that `dtype` can also be converted into `pykx.IntVector` objects. +=== "Numpy, Pandas, PyArrow" + Converting a `pykx.IntVector` will result in an array of objects with the `int32` `dtype`, arrays of that `dtype` can also be converted into `pykx.IntVector` objects. ## `pykx.LongAtom` -**Python** +=== "Python" + The python int type will be converted into a `pykx.LongAtom`. -The python int type will be converted into a `pykx.LongAtom`. + Float types will also be converted but the decimal will be truncated away and no rounding done. -Float types will also be converted but the decimal will be truncated away and no rounding done. + ```Python + >>> pykx.LongAtom(1) + pykx.LongAtom(pykx.q('1')) + >>> pykx.LongAtom(1.5) + pykx.LongAtom(pykx.q('1')) + ``` -```Python ->>> pykx.LongAtom(1) -pykx.LongAtom(pykx.q('1')) ->>> pykx.LongAtom(1.5) -pykx.LongAtom(pykx.q('1')) -``` + Calling `.py()` on a `pykx.LongAtom` will return a python int object. -Calling `.py()` on a `pykx.LongAtom` will return a python int object. - -```Python ->>> pykx.LongAtom(1.5).py() -1 -``` + ```Python + >>> pykx.LongAtom(1.5).py() + 1 + ``` ## `pykx.LongVector` -**Python** - -A list of python int types will be converted into a `pykx.LongVector`. - -Float types will also be converted but the decimal will be truncated away and no rounding done. +=== "Python" + A list of python int types will be converted into a `pykx.LongVector`. -```Python ->>> pykx.LongVector([1, 2.5]) -pykx.LongVector(pykx.q('1 2')) -``` + Float types will also be converted but the decimal will be truncated away and no rounding done. -Calling `.py()` on a `pykx.LongVector` will return a list of python int objects. + ```Python + >>> pykx.LongVector([1, 2.5]) + pykx.LongVector(pykx.q('1 2')) + ``` -```Python ->>>> pykx.LongVector([1, 2.5]).py() -[1, 2] -``` + Calling `.py()` on a `pykx.LongVector` will return a list of python int objects. -**Numpy, Pandas, PyArrow** + ```Python + >>>> pykx.LongVector([1, 2.5]).py() + [1, 2] + ``` -Converting a `pykx.LongVector` will result in an array of objects with the `int64` `dtype`, arrays of that `dtype` can also be converted into `pykx.LongVector` objects. +=== "Numpy, Pandas, PyArrow" + Converting a `pykx.LongVector` will result in an array of objects with the `int64` `dtype`, arrays of that `dtype` can also be converted into `pykx.LongVector` objects. ## `pykx.RealAtom` -**Python** - -The python float and int types will be converted into a `pykx.RealAtom`. +=== "Python" + The python float and int types will be converted into a `pykx.RealAtom`. -```Python ->>> pykx.RealAtom(2.5) -pykx.RealAtom(pykx.q('2.5e')) -``` + ```Python + >>> pykx.RealAtom(2.5) + pykx.RealAtom(pykx.q('2.5e')) + ``` -Calling `.py()` on a `pykx.RealAtom` will return a python float object. + Calling `.py()` on a `pykx.RealAtom` will return a python float object. -```Python ->>>> pykx.RealAtom(2.5).py() -2.5 -``` + ```Python + >>>> pykx.RealAtom(2.5).py() + 2.5 + ``` ## `pykx.RealVector` -**Python** +=== "Python" + A list of python int and float types will be converted into a `pykx.RealVector`. -A list of python int and float types will be converted into a `pykx.RealVector`. + ```Python + >>> pykx.RealVector([1, 2.5]) + pykx.RealVector(pykx.q('1 2.5e')) + ``` -```Python ->>> pykx.RealVector([1, 2.5]) -pykx.RealVector(pykx.q('1 2.5e')) -``` - -Calling `.py()` on a `pykx.RealVector` will return a list of python float objects. - -```Python ->>> pykx.RealVector([1, 2.5]).py() -[1.0, 2.5] -``` - -**Numpy, Pandas** + Calling `.py()` on a `pykx.RealVector` will return a list of python float objects. -Converting a `pykx.RealVector` will result in an array of objects with the `float32` `dtype`, arrays of that `dtype` can also be converted into `pykx.RealVector` objects. + ```Python + >>> pykx.RealVector([1, 2.5]).py() + [1.0, 2.5] + ``` +=== "Numpy, Pandas" + Converting a `pykx.RealVector` will result in an array of objects with the `float32` `dtype`, arrays of that `dtype` can also be converted into `pykx.RealVector` objects. -**PyArrow** -This will return a `PyArrow` array with the FloatArray type. +=== "PyArrow" + This will return a `PyArrow` array with the FloatArray type. ## `pykx.FloatAtom` -**Python** +=== "Python" + The python float and int types will be converted into a `pykx.FloatAtom`. -The python float and int types will be converted into a `pykx.FloatAtom`. + ```Python + >>> pykx.FloatAtom(2.5) + pykx.FloatAtom(pykx.q('2.5')) + ``` -```Python ->>> pykx.FloatAtom(2.5) -pykx.FloatAtom(pykx.q('2.5')) -``` + Calling `.py()` on a `pykx.FloatAtom` will return a python float object. -Calling `.py()` on a `pykx.FloatAtom` will return a python float object. - -```Python ->>>> pykx.FloatAtom(2.5).py() -2.5 -``` + ```Python + >>>> pykx.FloatAtom(2.5).py() + 2.5 + ``` ## `pykx.FloatVector` -**Python** - -A list of python int and float types will be converted into a `pykx.FloatVector`. - -```Python ->>> pykx.FloatVector([1, 2.5]) -pykx.FloatVector(pykx.q('1 2.5')) -``` - -Calling `.py()` on a `pykx.FloatVector` will return a list of python float objects. +=== "Python" + A list of python int and float types will be converted into a `pykx.FloatVector`. -```Python ->>> pykx.FloatVector([1, 2.5]).py() -[1.0, 2.5] -``` + ```Python + >>> pykx.FloatVector([1, 2.5]) + pykx.FloatVector(pykx.q('1 2.5')) + ``` -**Numpy, Pandas** + Calling `.py()` on a `pykx.FloatVector` will return a list of python float objects. -Converting a `pykx.FloatVector` will result in an array of objects with the `float64` `dtype`, arrays of that `dtype` can also be converted into `pykx.FloatVector` objects. + ```Python + >>> pykx.FloatVector([1, 2.5]).py() + [1.0, 2.5] + ``` -**PyArrow** +=== "Numpy, Pandas" + Converting a `pykx.FloatVector` will result in an array of objects with the `float64` `dtype`, arrays of that `dtype` can also be converted into `pykx.FloatVector` objects. -This will return a `PyArrow` array with the DoubleArray type. +=== "PyArrow" + This will return a `PyArrow` array with the DoubleArray type. ## `pykx.CharAtom` -**Python** +=== "Python" + The python bytes type with length 1 will be converted into a `pykx.CharAtom`. -The python bytes type with length 1 will be converted into a `pykx.CharAtom`. + ```Python + >>> pykx.CharAtom(b'a') + pykx.CharAtom(pykx.q('"a"')) + ``` -```Python ->>> pykx.CharAtom(b'a') -pykx.CharAtom(pykx.q('"a"')) -``` + Calling `.py()` on a `pykx.CharAtom` will return a python bytes object. -Calling `.py()` on a `pykx.CharAtom` will return a python bytes object. - -```Python ->>> pykx.CharAtom(b'a').py() -b'a' -``` + ```Python + >>> pykx.CharAtom(b'a').py() + b'a' + ``` ## `pykx.CharVector` -**Python** - -The python bytes type with length greater than 1 will be converted into a `pykx.CharVector`. - -```Python ->>> pykx.CharVector(b'abc') -pykx.CharVector(pykx.q('"abc"')) -``` - -Calling `.py()` on a `pykx.CharVector` will return a python bytes object. - -```Python ->>> pykx.CharVector(b'abc').py() -b'abc' -``` - -**Numpy** - -Calling `.np()` on a `pykx.CharVector` will return a numpy `ndarray` with `dtype` `'|S1'`. - -```Python ->>> pykx.CharVector(b'abc').np() -array([b'a', b'b', b'c'], dtype='|S1') -``` - -Converting a `ndarray` of this `dtype` will create a `pykx.CharVector`. - -```Python ->>> pykx.CharVector(np.array([b'a', b'b', b'c'], dtype='|S1')) -pykx.CharVector(pykx.q('"abc"')) -``` -**Pandas** - -Calling `.pd()` on a `pykx.CharVector` will return a pandas `Series` with `dtype` `bytes8`. - -```Python ->>> pykx.CharVector(b'abc').pd() -0 b'a' -1 b'b' -2 b'c' -dtype: bytes8 -``` -Converting a `Series` of this `dtype` will create a `pykx.CharVector`. - -```Python ->>> pykx.CharVector(pd.Series([b'a', b'b', b'c'], dtype=bytes)) -pykx.CharVector(pykx.q('"abc"')) -``` -**PyArrow** - -Calling `.pa()` on a `pykx.CharVector` will return a pyarrow `BinaryArray`. - -```Python - -[ - 61, - 62, - 63 -] -``` +=== "Python" + The python bytes type with length greater than 1 will be converted into a `pykx.CharVector`. + + ```Python + >>> pykx.CharVector(b'abc') + pykx.CharVector(pykx.q('"abc"')) + ``` + + Calling `.py()` on a `pykx.CharVector` will return a python bytes object. + + ```Python + >>> pykx.CharVector(b'abc').py() + b'abc' + ``` + +=== "Numpy" + Calling `.np()` on a `pykx.CharVector` will return a numpy `ndarray` with `dtype` `'|S1'`. + + ```Python + >>> pykx.CharVector(b'abc').np() + array([b'a', b'b', b'c'], dtype='|S1') + ``` + + Converting a `ndarray` of this `dtype` will create a `pykx.CharVector`. + + ```Python + >>> pykx.CharVector(np.array([b'a', b'b', b'c'], dtype='|S1')) + pykx.CharVector(pykx.q('"abc"')) + ``` +=== "Pandas" + Calling `.pd()` on a `pykx.CharVector` will return a pandas `Series` with `dtype` `bytes8`. + + ```Python + >>> pykx.CharVector(b'abc').pd() + 0 b'a' + 1 b'b' + 2 b'c' + dtype: bytes8 + ``` + + Converting a `Series` of this `dtype` will create a `pykx.CharVector`. + + ```Python + >>> pykx.CharVector(pd.Series([b'a', b'b', b'c'], dtype=bytes)) + pykx.CharVector(pykx.q('"abc"')) + ``` +=== "PyArrow" + Calling `.pa()` on a `pykx.CharVector` will return a pyarrow `BinaryArray`. + + ```Python + + [ + 61, + 62, + 63 + ] + ``` ## `pykx.SymbolAtom` -**Python** +=== "Python" + The python string type will be converted into a `pykx.SymbolAtom`. -The python string type will be converted into a `pykx.SymbolAtom`. + ```Python + >>> pykx.toq('symbol') + pykx.SymbolAtom(pykx.q('`symbol')) + ``` -```Python ->>> pykx.toq('symbol') -pykx.SymbolAtom(pykx.q('`symbol')) -``` + Calling `.py()` on a `pykx.SymbolAtom` will return a python string object. -Calling `.py()` on a `pykx.SymbolAtom` will return a python string object. + ```Python + >>> pykx.toq('symbol').py() + 'symbol' + ``` -```Python ->>> pykx.toq('symbol').py() -'symbol' -``` ## `pykx.SymbolVector` -**Python** - -A list of python string types will be converted into a `pykx.SymbolVector`. - -```Python ->>> pykx.SymbolVector(['a', 'b', 'c']) -pykx.SymbolVector(pykx.q('`a`b`c')) -``` - -Calling `.py()` on a `pykx.SymbolVector` will return a list of python string objects. - -```Python ->>> pykx.SymbolVector(['a', 'b', 'c']).py() -['a', 'b', 'c'] -``` +=== "Python" + A list of python string types will be converted into a `pykx.SymbolVector`. -**Numpy** + ```Python + >>> pykx.SymbolVector(['a', 'b', 'c']) + pykx.SymbolVector(pykx.q('`a`b`c')) + ``` -Calling `.np()` on a `pykx.SymbolVector` will return a numpy `ndarray` of python strings with `dtype` `object`. + Calling `.py()` on a `pykx.SymbolVector` will return a list of python string objects. -```Python ->>> pykx.SymbolVector(['a', 'b', 'c']).np() -array(['a', 'b', 'c'], dtype=object) -``` + ```Python + >>> pykx.SymbolVector(['a', 'b', 'c']).py() + ['a', 'b', 'c'] + ``` -Converting a `ndarray` of `dtype` `object` will create a `pykx.SymbolVector`. +=== "Numpy" + Calling `.np()` on a `pykx.SymbolVector` will return a numpy `ndarray` of python strings with `dtype` `object`. -```Python ->>> pykx.SymbolVector(np.array(['a', 'b', 'c'], dtype=object)) -pykx.SymbolVector(pykx.q('`a`b`c')) -``` + ```Python + >>> pykx.SymbolVector(['a', 'b', 'c']).np() + array(['a', 'b', 'c'], dtype=object) + ``` -**Pandas** + Converting a `ndarray` of `dtype` `object` will create a `pykx.SymbolVector`. -Calling `.pd()` on a `pykx.SymbolVector` will return a pandas `Series` with `dtype` `object`. + ```Python + >>> pykx.SymbolVector(np.array(['a', 'b', 'c'], dtype=object)) + pykx.SymbolVector(pykx.q('`a`b`c')) + ``` -```Python ->>> pykx.SymbolVector(['a', 'b', 'c']).pd() -0 a -1 b -2 c -dtype: object -``` +=== "Pandas" + Calling `.pd()` on a `pykx.SymbolVector` will return a pandas `Series` with `dtype` `object`. -**PyArrow** + ```Python + >>> pykx.SymbolVector(['a', 'b', 'c']).pd() + 0 a + 1 b + 2 c + dtype: object + ``` -Calling `.pa()` on a `pykx.SymbolVector` will return a pyarrow `StringArray`. +=== "PyArrow" + Calling `.pa()` on a `pykx.SymbolVector` will return a pyarrow `StringArray`. -```Python ->>> pykx.SymbolVector(['a', 'b', 'c']).pa() - -[ - "a", - "b", - "c" -] -``` + ```Python + >>> pykx.SymbolVector(['a', 'b', 'c']).pa() + + [ + "a", + "b", + "c" + ] + ``` ## `pykx.TimestampAtom` -**Python** +=== "Python" + The python datetime type will be converted into a `pykx.TimestampAtom`. -The python datetime type will be converted into a `pykx.TimestampAtom`. + ```Python + >>> kx.TimestampAtom(datetime(2150, 10, 22, 20, 31, 15, 70713)) + pykx.TimestampAtom(pykx.q('2150.10.22D20:31:15.070713000')) + ``` -```Python ->>> kx.TimestampAtom(datetime(2150, 10, 22, 20, 31, 15, 70713)) -pykx.TimestampAtom(pykx.q('2150.10.22D20:31:15.070713000')) -``` - -Calling `.py()` on a `pykx.TimestampAtom` will return a python datetime object. + Calling `.py()` on a `pykx.TimestampAtom` will return a python datetime object. -```Python ->>> kx.TimestampAtom(datetime(2150, 10, 22, 20, 31, 15, 70713)).py() -datetime.datetime(2150, 10, 22, 20, 31, 15, 70713) -``` + ```Python + >>> kx.TimestampAtom(datetime(2150, 10, 22, 20, 31, 15, 70713)).py() + datetime.datetime(2150, 10, 22, 20, 31, 15, 70713) + ``` ## `pykx.TimestampVector` -**Python** +=== "Python" + A list of python `datetime` types will be converted into a `pykx.TimestampVector`. -A list of python `datetime` types will be converted into a `pykx.TimestampVector`. + ```Python + >>> kx.TimestampVector([datetime(2150, 10, 22, 20, 31, 15, 70713), datetime(2050, 10, 22, 20, 31, 15, 70713)]) + pykx.TimestampVector(pykx.q('2150.10.22D20:31:15.070713000 2050.10.22D20:31:15.070713000')) + ``` -```Python ->>> kx.TimestampVector([datetime(2150, 10, 22, 20, 31, 15, 70713), datetime(2050, 10, 22, 20, 31, 15, 70713)]) -pykx.TimestampVector(pykx.q('2150.10.22D20:31:15.070713000 2050.10.22D20:31:15.070713000')) -``` + Calling `.py()` on a `pykx.TimestampVector` will return a list of python `datetime` objects. -Calling `.py()` on a `pykx.TimestampVector` will return a list of python `datetime` objects. + ```Python + >>> kx.TimestampVector([datetime(2150, 10, 22, 20, 31, 15, 70713), datetime(2050, 10, 22, 20, 31, 15, 70713)]).py() + [datetime.datetime(2150, 10, 22, 20, 31, 15, 70713), datetime.datetime(2050, 10, 22, 20, 31, 15, 70713)] + ``` -```Python ->>> kx.TimestampVector([datetime(2150, 10, 22, 20, 31, 15, 70713), datetime(2050, 10, 22, 20, 31, 15, 70713)]).py() -[datetime.datetime(2150, 10, 22, 20, 31, 15, 70713), datetime.datetime(2050, 10, 22, 20, 31, 15, 70713)] -``` +=== "Numpy" + Calling `.np()` on a `pykx.TimestampVector` will return a numpy `ndarray` with `dtype` `datetime64[ns]`. -**Numpy** + ```Python + >>> kx.TimestampVector([datetime(2150, 10, 22, 20, 31, 15, 70713), datetime(2050, 10, 22, 20, 31, 15, 70713)]).np() + array(['2150-10-22T20:31:15.070713000', '2050-10-22T20:31:15.070713000'], + dtype='datetime64[ns]') + ``` -Calling `.np()` on a `pykx.TimestampVector` will return a numpy `ndarray` with `dtype` `datetime64[ns]`. + Converting a `ndarray` of `dtype` `datetime64[ns]` will create a `pykx.TimestampVector`. -```Python ->>> kx.TimestampVector([datetime(2150, 10, 22, 20, 31, 15, 70713), datetime(2050, 10, 22, 20, 31, 15, 70713)]).np() -array(['2150-10-22T20:31:15.070713000', '2050-10-22T20:31:15.070713000'], - dtype='datetime64[ns]') -``` + ```Python + >>> kx.TimestampVector(np.array(['2150-10-22T20:31:15.070713000', '2050-10-22T20:31:15.070713000'], dtype='datetime64[ns]')) + pykx.TimestampVector(pykx.q('2150.10.22D20:31:15.070713000 2050.10.22D20:31:15.070713000')) + ``` -Converting a `ndarray` of `dtype` `datetime64[ns]` will create a `pykx.TimestampVector`. +=== "Pandas" + Calling `.pd()` on a `pykx.TimestampVector` will return a pandas `Series` with `dtype` `datetime64[ns]`. -```Python ->>> kx.TimestampVector(np.array(['2150-10-22T20:31:15.070713000', '2050-10-22T20:31:15.070713000'], dtype='datetime64[ns]')) -pykx.TimestampVector(pykx.q('2150.10.22D20:31:15.070713000 2050.10.22D20:31:15.070713000')) -``` -**Pandas** - -Calling `.pd()` on a `pykx.TimestampVector` will return a pandas `Series` with `dtype` `datetime64[ns]`. - -```Python ->>> kx.TimestampVector([datetime(2150, 10, 22, 20, 31, 15, 70713), datetime(2050, 10, 22, 20, 31, 15, 70713)]).pd() -0 2150-10-22 20:31:15.070713 -1 2050-10-22 20:31:15.070713 -dtype: datetime64[ns] -``` + ```Python + >>> kx.TimestampVector([datetime(2150, 10, 22, 20, 31, 15, 70713), datetime(2050, 10, 22, 20, 31, 15, 70713)]).pd() + 0 2150-10-22 20:31:15.070713 + 1 2050-10-22 20:31:15.070713 + dtype: datetime64[ns] + ``` -**PyArrow** +=== "PyArrow" + Calling `.pa()` on a `pykx.TimestampVector` will return a pyarrow `TimestampArray`. -Calling `.pa()` on a `pykx.TimestampVector` will return a pyarrow `TimestampArray`. - -```Python ->>> kx.TimestampVector([datetime(2150, 10, 22, 20, 31, 15, 70713), datetime(2050, 10, 22, 20, 31, 15, 70713)]).pa() - -[ - 2150-10-22 20:31:15.070713000, - 2050-10-22 20:31:15.070713000 -] -``` + ```Python + >>> kx.TimestampVector([datetime(2150, 10, 22, 20, 31, 15, 70713), datetime(2050, 10, 22, 20, 31, 15, 70713)]).pa() + + [ + 2150-10-22 20:31:15.070713000, + 2050-10-22 20:31:15.070713000 + ] + ``` ## `pykx.MonthAtom` -**Python** +=== "Python" + The python date type will be converted into a `pykx.MonthAtom`. -The python date type will be converted into a `pykx.MonthAtom`. - -```Python ->>> from datetime import date ->>> kx.MonthAtom(date(1972, 5, 1)) -pykx.MonthAtom(pykx.q('1972.05m')) -``` + ```Python + >>> from datetime import date + >>> kx.MonthAtom(date(1972, 5, 1)) + pykx.MonthAtom(pykx.q('1972.05m')) + ``` -Calling `.py()` on a `pykx.MonthAtom` will return a python date object. + Calling `.py()` on a `pykx.MonthAtom` will return a python date object. -```Python ->>> kx.MonthAtom(date(1972, 5, 1)).py() -datetime.date(1972, 5, 1) -``` + ```Python + >>> kx.MonthAtom(date(1972, 5, 1)).py() + datetime.date(1972, 5, 1) + ``` ## `pykx.MonthVector` -**Python** +=== "Python" + A list of python `date` types will be converted into a `pykx.MonthVector`. -A list of python `date` types will be converted into a `pykx.MonthVector`. + ```Python + >>> kx.MonthVector([date(1972, 5, 1), date(1999, 5, 1)]) + pykx.MonthVector(pykx.q('1972.05 1999.05m')) + ``` -```Python ->>> kx.MonthVector([date(1972, 5, 1), date(1999, 5, 1)]) -pykx.MonthVector(pykx.q('1972.05 1999.05m')) -``` + Calling `.py()` on a `pykx.MonthVector` will return a list of python `date` objects. -Calling `.py()` on a `pykx.MonthVector` will return a list of python `date` objects. + ```Python + >>> kx.MonthVector([date(1972, 5, 1), date(1999, 5, 1)]).py() + [datetime.date(1972, 5, 1), datetime.date(1999, 5, 1)] + ``` -```Python ->>> kx.MonthVector([date(1972, 5, 1), date(1999, 5, 1)]).py() -[datetime.date(1972, 5, 1), datetime.date(1999, 5, 1)] -``` +=== "Numpy" + Calling `.np()` on a `pykx.MonthVector` will return a numpy `ndarray` with `dtype` `datetime64[M]`. -**Numpy** + ```Python + >>> kx.MonthVector([date(1972, 5, 1), date(1999, 5, 1)]).np() + array(['1972-05', '1999-05'], dtype='datetime64[M]') + ``` -Calling `.np()` on a `pykx.MonthVector` will return a numpy `ndarray` with `dtype` `datetime64[M]`. + Converting a `ndarray` of `dtype` `datetime64[M]` will create a `pykx.MonthVector`. -```Python ->>> kx.MonthVector([date(1972, 5, 1), date(1999, 5, 1)]).np() -array(['1972-05', '1999-05'], dtype='datetime64[M]') -``` + ```Python + >>> kx.MonthVector(np.array(['1972-05', '1999-05'], dtype='datetime64[M]')) + pykx.MonthVector(pykx.q('1972.05 1999.05m')) + ``` -Converting a `ndarray` of `dtype` `datetime64[M]` will create a `pykx.MonthVector`. +=== "Pandas" + Calling `.pd()` on a `pykx.MonthVector` will return a pandas `Series` with `dtype` `datetime64[ns]`. -```Python ->>> kx.MonthVector(np.array(['1972-05', '1999-05'], dtype='datetime64[M]')) -pykx.MonthVector(pykx.q('1972.05 1999.05m')) -``` -**Pandas** - -Calling `.pd()` on a `pykx.MonthVector` will return a pandas `Series` with `dtype` `datetime64[ns]`. - -```Python ->>> kx.MonthVector([date(1972, 5, 1), date(1999, 5, 1)]).pd() -0 1972-05-01 -1 1999-05-01 -dtype: datetime64[ns] -``` + ```Python + >>> kx.MonthVector([date(1972, 5, 1), date(1999, 5, 1)]).pd() + 0 1972-05-01 + 1 1999-05-01 + dtype: datetime64[ns] + ``` ## `pykx.DateAtom` -**Python** +=== "Python" + The python date type will be converted into a `pykx.DateAtom`. -The python date type will be converted into a `pykx.DateAtom`. + ```Python + >>> kx.DateAtom(date(1972, 5, 31)) + pykx.DateAtom(pykx.q('1972.05.31')) + ``` -```Python ->>> kx.DateAtom(date(1972, 5, 31)) -pykx.DateAtom(pykx.q('1972.05.31')) -``` + Calling `.py()` on a `pykx.DateAtom` will return a python date object. -Calling `.py()` on a `pykx.DateAtom` will return a python date object. - -```Python ->>> kx.DateAtom(date(1972, 5, 31)).py() -datetime.date(1972, 5, 31) -``` + ```Python + >>> kx.DateAtom(date(1972, 5, 31)).py() + datetime.date(1972, 5, 31) + ``` ## `pykx.DateVector` -**Python** +=== "Python" + A list of python `date` types will be converted into a `pykx.DateVector`. -A list of python `date` types will be converted into a `pykx.DateVector`. + ```Python + >>> kx.DateVector([date(1972, 5, 1), date(1999, 5, 1)]) + pykx.DateVector(pykx.q('1972.05.01 1999.05.01')) + ``` -```Python ->>> kx.DateVector([date(1972, 5, 1), date(1999, 5, 1)]) -pykx.DateVector(pykx.q('1972.05.01 1999.05.01')) -``` - -Calling `.py()` on a `pykx.DateVector` will return a list of python `date` objects. - -```Python ->>> kx.DateVector([date(1972, 5, 1), date(1999, 5, 1)]).py() -[datetime.date(1972, 5, 1), datetime.date(1999, 5, 1)] -``` + Calling `.py()` on a `pykx.DateVector` will return a list of python `date` objects. -**Numpy** + ```Python + >>> kx.DateVector([date(1972, 5, 1), date(1999, 5, 1)]).py() + [datetime.date(1972, 5, 1), datetime.date(1999, 5, 1)] + ``` -Calling `.np()` on a `pykx.DateVector` will return a numpy `ndarray` of python strings with `dtype` `datetime64[D]`. +=== "Numpy" + Calling `.np()` on a `pykx.DateVector` will return a numpy `ndarray` of python strings with `dtype` `datetime64[D]`. -```Python ->>> kx.DateVector([date(1972, 5, 1), date(1999, 5, 1)]).np() -array(['1972-05-01', '1999-05-01'], dtype='datetime64[D]') -``` + ```Python + >>> kx.DateVector([date(1972, 5, 1), date(1999, 5, 1)]).np() + array(['1972-05-01', '1999-05-01'], dtype='datetime64[D]') + ``` -Converting a `ndarray` of `dtype` `datetime64[D]` will create a `pykx.DateVector`. + Converting a `ndarray` of `dtype` `datetime64[D]` will create a `pykx.DateVector`. -```Python ->>> kx.DateVector(np.array(['1972-05-01', '1999-05-01'], dtype='datetime64[D]')) -pykx.DateVector(pykx.q('1972.05.01 1999.05.01')) -``` -**Pandas** + ```Python + >>> kx.DateVector(np.array(['1972-05-01', '1999-05-01'], dtype='datetime64[D]')) + pykx.DateVector(pykx.q('1972.05.01 1999.05.01')) + ``` -Calling `.pd()` on a `pykx.DateVector` will return a pandas `Series` with `dtype` `datetime64[ns]`. +=== "Pandas" + Calling `.pd()` on a `pykx.DateVector` will return a pandas `Series` with `dtype` `datetime64[ns]`. -```Python ->>> kx.DateVector([date(1972, 5, 1), date(1999, 5, 1)]).pd() -0 1972-05-01 -1 1999-05-01 -dtype: datetime64[ns] -``` + ```Python + >>> kx.DateVector([date(1972, 5, 1), date(1999, 5, 1)]).pd() + 0 1972-05-01 + 1 1999-05-01 + dtype: datetime64[ns] + ``` -**PyArrow** +=== "PyArrow" + Calling `.pa()` on a `pykx.DateVector` will return a pyarrow `Date32Array`. -Calling `.pa()` on a `pykx.DateVector` will return a pyarrow `Date32Array`. - -```Python ->>> kx.DateVector([date(1972, 5, 1), date(1999, 5, 1)]).pa() - -[ - 1972-05-01, - 1999-05-01 -] -``` + ```Python + >>> kx.DateVector([date(1972, 5, 1), date(1999, 5, 1)]).pa() + + [ + 1972-05-01, + 1999-05-01 + ] + ``` ## `pykx.Datetime` types -**Python and Numpy** +=== "Python and Numpy" + These types are deprecated and can only be accessed using the `raw` key word argument. -These types are deprecated and can only be accessed using the `raw` key word argument. + Converting these types to python will return a float object or a `float64` object in numpy's case. -Converting these types to python will return a float object or a `float64` object in numpy's case. - -```Python ->>> kx.q('0001.02.03T04:05:06.007, 0001.02.03T04:05:06.007').py(raw=True) -[-730085.8297915857, -730085.8297915857] ->>> kx.q('0001.02.03T04:05:06.007, 0001.02.03T04:05:06.007').np(raw=True) -array([-730085.82979159, -730085.82979159]) ->>> kx.q('0001.02.03T04:05:06.007, 0001.02.03T04:05:06.007').np(raw=True).dtype -dtype('float64') -``` + ```Python + >>> kx.q('0001.02.03T04:05:06.007, 0001.02.03T04:05:06.007').py(raw=True) + [-730085.8297915857, -730085.8297915857] + >>> kx.q('0001.02.03T04:05:06.007, 0001.02.03T04:05:06.007').np(raw=True) + array([-730085.82979159, -730085.82979159]) + >>> kx.q('0001.02.03T04:05:06.007, 0001.02.03T04:05:06.007').np(raw=True).dtype + dtype('float64') + ``` ## `pykx.TimespanAtom` -**Python** +=== "Python" + The python `timedelta` type will be converted into a `pykx.TimespanAtom`. -The python `timedelta` type will be converted into a `pykx.TimespanAtom`. + ```Python + >>> from datetime import timedelta + >>> kx.TimespanAtom(timedelta(days=43938, seconds=68851, microseconds=664551)) + pykx.TimespanAtom(pykx.q('43938D19:07:31.664551000')) + ``` -```Python ->>> from datetime import timedelta ->>> kx.TimespanAtom(timedelta(days=43938, seconds=68851, microseconds=664551)) -pykx.TimespanAtom(pykx.q('43938D19:07:31.664551000')) -``` + Calling `.py()` on a `pykx.TimespanAtom` will return a python `timedelta` object. -Calling `.py()` on a `pykx.TimespanAtom` will return a python `timedelta` object. - -```Python ->>> kx.TimespanAtom(timedelta(days=43938, seconds=68851, microseconds=664551)).py() -datetime.timedelta(days=43938, seconds=68851, microseconds=664551) -``` + ```Python + >>> kx.TimespanAtom(timedelta(days=43938, seconds=68851, microseconds=664551)).py() + datetime.timedelta(days=43938, seconds=68851, microseconds=664551) + ``` ## `pykx.TimespanVector` -**Python** +=== "Python" + A list of python `timedelta` types will be converted into a `pykx.TimespanVector`. -A list of python `timedelta` types will be converted into a `pykx.TimespanVector`. + ```Python + >>> kx.TimespanVector([timedelta(days=43938, seconds=68851, microseconds=664551), timedelta(days=43938, seconds=68851, microseconds=664551)]) + pykx.TimespanVector(pykx.q('43938D19:07:31.664551000 43938D19:07:31.664551000')) + ``` -```Python ->>> kx.TimespanVector([timedelta(days=43938, seconds=68851, microseconds=664551), timedelta(days=43938, seconds=68851, microseconds=664551)]) -pykx.TimespanVector(pykx.q('43938D19:07:31.664551000 43938D19:07:31.664551000')) -``` + Calling `.py()` on a `pykx.TimespanVector` will return a list of python `timedelta` objects. -Calling `.py()` on a `pykx.TimespanVector` will return a list of python `timedelta` objects. + ```Python + >>> kx.TimespanVector([timedelta(days=43938, seconds=68851, microseconds=664551), timedelta(days=43938, seconds=68851, microseconds=664551)]).py() + [datetime.timedelta(days=43938, seconds=68851, microseconds=664551), datetime.timedelta(days=43938, seconds=68851, microseconds=664551)] + ``` -```Python ->>> kx.TimespanVector([timedelta(days=43938, seconds=68851, microseconds=664551), timedelta(days=43938, seconds=68851, microseconds=664551)]).py() -[datetime.timedelta(days=43938, seconds=68851, microseconds=664551), datetime.timedelta(days=43938, seconds=68851, microseconds=664551)] -``` - -**Numpy** - -Calling `.np()` on a `pykx.TimespanVector` will return a numpy `ndarray` of python strings with `dtype` `timedelta64[ns]`. - -```Python ->>> kx.TimespanVector([timedelta(days=43938, seconds=68851, microseconds=664551), timedelta(days=43938, seconds=68851, microseconds=664551)]).np() -array([3796312051664551000, 3796312051664551000], dtype='timedelta64[ns]') -``` +=== "Numpy" + Calling `.np()` on a `pykx.TimespanVector` will return a numpy `ndarray` of python strings with `dtype` `timedelta64[ns]`. -Converting a `ndarray` of `dtype` `datetime64[ns]` will create a `pykx.TimespanVector`. + ```Python + >>> kx.TimespanVector([timedelta(days=43938, seconds=68851, microseconds=664551), timedelta(days=43938, seconds=68851, microseconds=664551)]).np() + array([3796312051664551000, 3796312051664551000], dtype='timedelta64[ns]') + ``` -```Python ->>> kx.TimespanVector(np.array([3796312051664551000, 3796312051664551000], dtype='timedelta64[ns]')) -pykx.TimespanVector(pykx.q('43938D19:07:31.664551000 43938D19:07:31.664551000')) -``` -**Pandas** + Converting a `ndarray` of `dtype` `datetime64[ns]` will create a `pykx.TimespanVector`. -Calling `.pd()` on a `pykx.TimespanVector` will return a pandas `Series` with `dtype` `timedelta64[ns]`. + ```Python + >>> kx.TimespanVector(np.array([3796312051664551000, 3796312051664551000], dtype='timedelta64[ns]')) + pykx.TimespanVector(pykx.q('43938D19:07:31.664551000 43938D19:07:31.664551000')) + ``` -```Python ->>> kx.TimespanVector([timedelta(days=43938, seconds=68851, microseconds=664551), timedelta(days=43938, seconds=68851, microseconds=664551)]).pd() -0 43938 days 19:07:31.664551 -1 43938 days 19:07:31.664551 -dtype: timedelta64[ns] -``` +=== "Pandas" + Calling `.pd()` on a `pykx.TimespanVector` will return a pandas `Series` with `dtype` `timedelta64[ns]`. -**PyArrow** + ```Python + >>> kx.TimespanVector([timedelta(days=43938, seconds=68851, microseconds=664551), timedelta(days=43938, seconds=68851, microseconds=664551)]).pd() + 0 43938 days 19:07:31.664551 + 1 43938 days 19:07:31.664551 + dtype: timedelta64[ns] + ``` -Calling `.pa()` on a `pykx.TimespanVector` will return a pyarrow `DurationArray`. +=== "PyArrow" + Calling `.pa()` on a `pykx.TimespanVector` will return a pyarrow `DurationArray`. -```Python ->>> kx.TimespanVector([timedelta(days=43938, seconds=68851, microseconds=664551), timedelta(days=43938, seconds=68851, microseconds=664551)]).pa() - -[ - 3796312051664551000, - 3796312051664551000 -] -``` + ```Python + >>> kx.TimespanVector([timedelta(days=43938, seconds=68851, microseconds=664551), timedelta(days=43938, seconds=68851, microseconds=664551)]).pa() + + [ + 3796312051664551000, + 3796312051664551000 + ] + ``` ## `pykx.MinuteAtom` -**Python** +=== "Python" + The python `timedelta` type will be converted into a `pykx.MinuteAtom`. -The python `timedelta` type will be converted into a `pykx.MinuteAtom`. + ```Python + >>> kx.MinuteAtom(timedelta(minutes=216)) + pykx.MinuteAtom(pykx.q('03:36')) + ``` -```Python ->>> kx.MinuteAtom(timedelta(minutes=216)) -pykx.MinuteAtom(pykx.q('03:36')) -``` + Calling `.py()` on a `pykx.MinuteAtom` will return a python `timedelta` object. -Calling `.py()` on a `pykx.MinuteAtom` will return a python `timedelta` object. - -```Python ->>> kx.MinuteAtom(timedelta(minutes=216)).py() -datetime.timedelta(seconds=12960) -``` + ```Python + >>> kx.MinuteAtom(timedelta(minutes=216)).py() + datetime.timedelta(seconds=12960) + ``` ## `pykx.MinuteVector` -**Python** - -A list of python `timedelta` types will be converted into a `pykx.MinuteVector`. +=== "Python" + A list of python `timedelta` types will be converted into a `pykx.MinuteVector`. -```Python ->>> kx.MinuteVector([timedelta(minutes=216), timedelta(minutes=67)]) -pykx.MinuteVector(pykx.q('03:36 01:07')) -``` + ```Python + >>> kx.MinuteVector([timedelta(minutes=216), timedelta(minutes=67)]) + pykx.MinuteVector(pykx.q('03:36 01:07')) + ``` -Calling `.py()` on a `pykx.MinuteVector` will return a list of python `timedelta` objects. + Calling `.py()` on a `pykx.MinuteVector` will return a list of python `timedelta` objects. -```Python ->>> kx.MinuteVector([timedelta(minutes=216), timedelta(minutes=67)]).py() -[datetime.timedelta(seconds=12960), datetime.timedelta(seconds=4020)] -``` + ```Python + >>> kx.MinuteVector([timedelta(minutes=216), timedelta(minutes=67)]).py() + [datetime.timedelta(seconds=12960), datetime.timedelta(seconds=4020)] + ``` -**Numpy** +=== "Numpy" + Calling `.np()` on a `pykx.MinuteVector` will return a numpy `ndarray` of python strings with `dtype` `timedelta64[m]`. -Calling `.np()` on a `pykx.MinuteVector` will return a numpy `ndarray` of python strings with `dtype` `timedelta64[m]`. + ```Python + >>> kx.MinuteVector([timedelta(minutes=216), timedelta(minutes=67)]).np() + array([216, 67], dtype='timedelta64[m]') + ``` -```Python ->>> kx.MinuteVector([timedelta(minutes=216), timedelta(minutes=67)]).np() -array([216, 67], dtype='timedelta64[m]') -``` + Converting a `ndarray` of `dtype` `timedelta64[m]` will create a `pykx.MinuteVector`. -Converting a `ndarray` of `dtype` `timedelta64[m]` will create a `pykx.MinuteVector`. + ```Python + >>> kx.MinuteVector(np.array([216, 67], dtype='timedelta64[m]')) + pykx.MinuteVector(pykx.q('03:36 01:07')) + ``` -```Python ->>> kx.MinuteVector(np.array([216, 67], dtype='timedelta64[m]')) -pykx.MinuteVector(pykx.q('03:36 01:07')) -``` -**Pandas** +=== "Pandas" + Calling `.pd()` on a `pykx.MinuteVector` will return a pandas `Series` with `dtype` `timedelta64[ns]`. -Calling `.pd()` on a `pykx.MinuteVector` will return a pandas `Series` with `dtype` `timedelta64[ns]`. - -```Python ->>> kx.MinuteVector([timedelta(minutes=216), timedelta(minutes=67)]).pd() -0 0 days 03:36:00 -1 0 days 01:07:00 -dtype: timedelta64[ns] -``` + ```Python + >>> kx.MinuteVector([timedelta(minutes=216), timedelta(minutes=67)]).pd() + 0 0 days 03:36:00 + 1 0 days 01:07:00 + dtype: timedelta64[ns] + ``` ## `pykx.SecondAtom` -**Python** +=== "Python" + The python `timedelta` type will be converted into a `pykx.SecondAtom`. -The python `timedelta` type will be converted into a `pykx.SecondAtom`. + ```Python + >>> kx.SecondAtom(timedelta(seconds=13019)) + pykx.SecondAtom(pykx.q('03:36:59')) + ``` -```Python ->>> kx.SecondAtom(timedelta(seconds=13019)) -pykx.SecondAtom(pykx.q('03:36:59')) -``` + Calling `.py()` on a `pykx.SecondAtom` will return a python `timedelta` object. -Calling `.py()` on a `pykx.SecondAtom` will return a python `timedelta` object. - -```Python ->>> kx.SecondAtom(timedelta(seconds=13019)).py() -datetime.timedelta(seconds=13019) -``` + ```Python + >>> kx.SecondAtom(timedelta(seconds=13019)).py() + datetime.timedelta(seconds=13019) + ``` ## `pykx.SecondVector` -**Python** +=== "Python" + A list of python `timedelta` types will be converted into a `pykx.SecondVector`. -A list of python `timedelta` types will be converted into a `pykx.SecondVector`. + ```Python + >>> kx.SecondVector([timedelta(seconds=13019), timedelta(seconds=1019)]) + pykx.SecondVector(pykx.q('03:36:59 00:16:59')) + ``` -```Python ->>> kx.SecondVector([timedelta(seconds=13019), timedelta(seconds=1019)]) -pykx.SecondVector(pykx.q('03:36:59 00:16:59')) -``` + Calling `.py()` on a `pykx.SecondVector` will return a list of python `timedelta` objects. -Calling `.py()` on a `pykx.SecondVector` will return a list of python `timedelta` objects. + ```Python + >>> kx.SecondVector([timedelta(seconds=13019), timedelta(seconds=1019)]).py() + [datetime.timedelta(seconds=13019), datetime.timedelta(seconds=1019)] + ``` -```Python ->>> kx.SecondVector([timedelta(seconds=13019), timedelta(seconds=1019)]).py() -[datetime.timedelta(seconds=13019), datetime.timedelta(seconds=1019)] -``` - -**Numpy** +=== "Numpy" + Calling `.np()` on a `pykx.SecondVector` will return a numpy `ndarray` of python strings with `dtype` `timedelta64[s]`. -Calling `.np()` on a `pykx.SecondVector` will return a numpy `ndarray` of python strings with `dtype` `timedelta64[s]`. + ```Python + >>> kx.SecondVector([timedelta(seconds=13019), timedelta(seconds=1019)]).np() + array([13019, 1019], dtype='timedelta64[s]') + ``` -```Python ->>> kx.SecondVector([timedelta(seconds=13019), timedelta(seconds=1019)]).np() -array([13019, 1019], dtype='timedelta64[s]') -``` + Converting a `ndarray` of `dtype` `timedelta64[s]` will create a `pykx.SecondVector`. -Converting a `ndarray` of `dtype` `timedelta64[s]` will create a `pykx.SecondVector`. + ```Python + >>> kx.SecondVector(np.array([13019, 1019], dtype='timedelta64[s]')) + pykx.SecondVector(pykx.q('03:36:59 00:16:59')) + ``` -```Python ->>> kx.SecondVector(np.array([13019, 1019], dtype='timedelta64[s]')) -pykx.SecondVector(pykx.q('03:36:59 00:16:59')) -``` -**Pandas** - -Calling `.pd()` on a `pykx.SecondVector` will return a pandas `Series` with `dtype` `timedelta64[ns]`. - -```Python ->>> kx.SecondVector([timedelta(seconds=13019), timedelta(seconds=1019)]).pd() -0 0 days 03:36:59 -1 0 days 00:16:59 -dtype: timedelta64[ns] -``` +=== "Pandas" + Calling `.pd()` on a `pykx.SecondVector` will return a pandas `Series` with `dtype` `timedelta64[ns]`. -**PyArrow** + ```Python + >>> kx.SecondVector([timedelta(seconds=13019), timedelta(seconds=1019)]).pd() + 0 0 days 03:36:59 + 1 0 days 00:16:59 + dtype: timedelta64[ns] + ``` -Calling `.pa()` on a `pykx.SecondVector` will return a pyarrow `DurationArray`. +=== "PyArrow" + Calling `.pa()` on a `pykx.SecondVector` will return a pyarrow `DurationArray`. -```Python ->>> kx.SecondVector([timedelta(seconds=13019), timedelta(seconds=1019)]).pa() - -[ - 13019, - 1019 -] -``` + ```Python + >>> kx.SecondVector([timedelta(seconds=13019), timedelta(seconds=1019)]).pa() + + [ + 13019, + 1019 + ] + ``` ## `pykx.TimeAtom` -**Python** +=== "Python" + The python `timedelta` type will be converted into a `pykx.TimeAtom`. -The python `timedelta` type will be converted into a `pykx.TimeAtom`. + ```Python + >>> kx.TimeAtom(timedelta(seconds=59789, microseconds=214000)) + pykx.TimeAtom(pykx.q('16:36:29.214')) + ``` -```Python ->>> kx.TimeAtom(timedelta(seconds=59789, microseconds=214000)) -pykx.TimeAtom(pykx.q('16:36:29.214')) -``` + Calling `.py()` on a `pykx.TimeAtom` will return a python `timedelta` object. -Calling `.py()` on a `pykx.TimeAtom` will return a python `timedelta` object. - -```Python ->>> kx.TimeAtom(timedelta(seconds=59789, microseconds=214000)).py() -datetime.timedelta(seconds=59789, microseconds=214000) -``` + ```Python + >>> kx.TimeAtom(timedelta(seconds=59789, microseconds=214000)).py() + datetime.timedelta(seconds=59789, microseconds=214000) + ``` ## `pykx.TimeVector` -**Python** +=== "Python" + A list of python `timedelta` types will be converted into a `pykx.TimeVector`. -A list of python `timedelta` types will be converted into a `pykx.TimeVector`. - -```Python ->>> kx.TimeVector([timedelta(seconds=59789, microseconds=214000), timedelta(seconds=23789, microseconds=214000)]) -pykx.TimeVector(pykx.q('16:36:29.214 06:36:29.214')) -``` + ```Python + >>> kx.TimeVector([timedelta(seconds=59789, microseconds=214000), timedelta(seconds=23789, microseconds=214000)]) + pykx.TimeVector(pykx.q('16:36:29.214 06:36:29.214')) + ``` -Calling `.py()` on a `pykx.TimeVector` will return a list of python `timedelta` objects. + Calling `.py()` on a `pykx.TimeVector` will return a list of python `timedelta` objects. -```Python ->>> kx.TimeVector([timedelta(seconds=59789, microseconds=214000), timedelta(seconds=23789, microseconds=214000)]).py() -[datetime.timedelta(seconds=59789, microseconds=214000), datetime.timedelta(seconds=23789, microseconds=214000)] -``` + ```Python + >>> kx.TimeVector([timedelta(seconds=59789, microseconds=214000), timedelta(seconds=23789, microseconds=214000)]).py() + [datetime.timedelta(seconds=59789, microseconds=214000), datetime.timedelta(seconds=23789, microseconds=214000)] + ``` -**Numpy** +=== "Numpy" -Calling `.np()` on a `pykx.TimeVector` will return a numpy `ndarray` of python strings with `dtype` `timedelta64[ms]`. + Calling `.np()` on a `pykx.TimeVector` will return a numpy `ndarray` of python strings with `dtype` `timedelta64[ms]`. -```Python ->>> kx.TimeVector([timedelta(seconds=59789, microseconds=214000), timedelta(seconds=23789, microseconds=214000)]).np() -array([59789214, 23789214], dtype='timedelta64[ms]') -``` + ```Python + >>> kx.TimeVector([timedelta(seconds=59789, microseconds=214000), timedelta(seconds=23789, microseconds=214000)]).np() + array([59789214, 23789214], dtype='timedelta64[ms]') + ``` -Converting a `ndarray` of `dtype` `timedelta64[ms]` will create a `pykx.TimeVector`. + Converting a `ndarray` of `dtype` `timedelta64[ms]` will create a `pykx.TimeVector`. -```Python ->>> kx.TimeVector(np.array([59789214, 23789214], dtype='timedelta64[ms]')) -pykx.TimeVector(pykx.q('16:36:29.214 06:36:29.214')) -``` -**Pandas** + ```Python + >>> kx.TimeVector(np.array([59789214, 23789214], dtype='timedelta64[ms]')) + pykx.TimeVector(pykx.q('16:36:29.214 06:36:29.214')) + ``` -Calling `.pd()` on a `pykx.TimeVector` will return a pandas `Series` with `dtype` `timedelta64[ns]`. +=== "Pandas" -```Python ->>> kx.TimeVector([timedelta(seconds=59789, microseconds=214000), timedelta(seconds=23789, microseconds=214000)]).pd() -0 0 days 16:36:29.214000 -1 0 days 06:36:29.214000 -dtype: timedelta64[ns] -``` + Calling `.pd()` on a `pykx.TimeVector` will return a pandas `Series` with `dtype` `timedelta64[ns]`. -**PyArrow** + ```Python + >>> kx.TimeVector([timedelta(seconds=59789, microseconds=214000), timedelta(seconds=23789, microseconds=214000)]).pd() + 0 0 days 16:36:29.214000 + 1 0 days 06:36:29.214000 + dtype: timedelta64[ns] + ``` -Calling `.pa()` on a `pykx.TimeVector` will return a pyarrow `DurationArray`. +=== "PyArrow" + Calling `.pa()` on a `pykx.TimeVector` will return a pyarrow `DurationArray`. -```Python ->>> kx.TimeVector([timedelta(seconds=59789, microseconds=214000), timedelta(seconds=23789, microseconds=214000)]).pa() - -[ - 59789214, - 23789214 -] -``` + ```Python + >>> kx.TimeVector([timedelta(seconds=59789, microseconds=214000), timedelta(seconds=23789, microseconds=214000)]).pa() + + [ + 59789214, + 23789214 + ] + ``` ## `pykx.Dictionary` -**Python** +=== "Python" + A python `dict` type will be converted into a `pykx.Dictionary`. -A python `dict` type will be converted into a `pykx.Dictionary`. + ```Python + >>> kx.Dictionary({'foo': b'bar', 'baz': 3.5, 'z': 'prime'}) + pykx.Dictionary(pykx.q(' + foo| "bar" + baz| 3.5 + z | `prime + ')) + ``` -```Python ->>> kx.Dictionary({'foo': b'bar', 'baz': 3.5, 'z': 'prime'}) -pykx.Dictionary(pykx.q(' -foo| "bar" -baz| 3.5 -z | `prime -')) -``` - -Calling `.py()` on a `pykx.Dictionary` will return a python `dict` object. + Calling `.py()` on a `pykx.Dictionary` will return a python `dict` object. -```Python ->>> kx.Dictionary({'foo': b'bar', 'baz': 3.5, 'z': 'prime'}).py() -{'foo': b'bar', 'baz': 3.5, 'z': 'prime'} -``` + ```Python + >>> kx.Dictionary({'foo': b'bar', 'baz': 3.5, 'z': 'prime'}).py() + {'foo': b'bar', 'baz': 3.5, 'z': 'prime'} + ``` ## `pykx.Table` -**Python** - -Calling `.py()` on a `pykx.Table` will return a python `dict` object. - -```Python ->>> kx.q('([] a: 10?10; b: 10?10)').py() -{'a': [5, 6, 4, 1, 3, 3, 7, 8, 2, 1], 'b': [8, 1, 7, 2, 4, 5, 4, 2, 7, 8]} -``` - -**Numpy** - -Calling `.np()` on a `pykx.Table` will return a numpy `record` array of the rows of the table with each type converted to it closest analogous numpy type. - -```Python ->>> kx.q('([] a: 10?10; b: 10?10)').np() -rec.array([(9, 9), (9, 7), (2, 6), (5, 6), (4, 4), (2, 7), (5, 8), (8, 4), - (7, 4), (9, 6)], - dtype=[('a', '>> kx.q('([] a: 10?10; b: 10?10)').pd() - a b -0 1 9 -1 0 7 -2 5 7 -3 1 1 -4 0 9 -5 0 1 -6 1 0 -7 7 8 -8 6 8 -9 3 3 -``` - -Converting a `pandas` `DataFrame` object will result in a `pykx.Table` object. - -```Python ->>> kx.Table(pd.DataFrame({'a': [x for x in range(10)], 'b': [float(x) for x in range(10)]})) -pykx.Table(pykx.q(' -a b ---- -0 0 -1 1 -2 2 -3 3 -4 4 -5 5 -6 6 -7 7 -8 8 -9 9 -')) -``` - -**PyArrow** - -Calling `.pa()` on a `pykx.Table` will return a pyarrow `Table`. - -```Python ->>> kx.q('([] a: 10?10; b: 10?10)').pa() -pyarrow.Table -a: int64 -b: int64 ----- -a: [[0,7,3,3,6,8,2,3,8,9]] -b: [[5,7,5,6,7,0,2,1,8,1]] -``` - -Converting a `pyarow` `Table` object will result in a `pykx.Table` object. - -```Python ->>> kx.Table(pa.Table.from_arrays([[1, 2, 3, 4], [5, 6, 7, 8]], names=['a', 'b'])) -pykx.Table(pykx.q(' -a b ---- -1 5 -2 6 -3 7 -4 8 -')) -``` +=== "Python" + Calling `.py()` on a `pykx.Table` will return a python `dict` object. + + ```Python + >>> kx.q('([] a: 10?10; b: 10?10)').py() + {'a': [5, 6, 4, 1, 3, 3, 7, 8, 2, 1], 'b': [8, 1, 7, 2, 4, 5, 4, 2, 7, 8]} + ``` + +=== "Numpy" + Calling `.np()` on a `pykx.Table` will return a numpy `record` array of the rows of the table with each type converted to it closest analogous numpy type. + + ```Python + >>> kx.q('([] a: 10?10; b: 10?10)').np() + rec.array([(9, 9), (9, 7), (2, 6), (5, 6), (4, 4), (2, 7), (5, 8), (8, 4), + (7, 4), (9, 6)], + dtype=[('a', '>> kx.q('([] a: 10?10; b: 10?10)').pd() + a b + 0 1 9 + 1 0 7 + 2 5 7 + 3 1 1 + 4 0 9 + 5 0 1 + 6 1 0 + 7 7 8 + 8 6 8 + 9 3 3 + ``` + + Converting a `pandas` `DataFrame` object will result in a `pykx.Table` object. + + ```Python + >>> kx.Table(pd.DataFrame({'a': [x for x in range(10)], 'b': [float(x) for x in range(10)]})) + pykx.Table(pykx.q(' + a b + --- + 0 0 + 1 1 + 2 2 + 3 3 + 4 4 + 5 5 + 6 6 + 7 7 + 8 8 + 9 9 + ')) + ``` + +=== "PyArrow" + Calling `.pa()` on a `pykx.Table` will return a pyarrow `Table`. + + ```Python + >>> kx.q('([] a: 10?10; b: 10?10)').pa() + pyarrow.Table + a: int64 + b: int64 + ---- + a: [[0,7,3,3,6,8,2,3,8,9]] + b: [[5,7,5,6,7,0,2,1,8,1]] + ``` + + Converting a `pyarow` `Table` object will result in a `pykx.Table` object. + + ```Python + >>> kx.Table(pa.Table.from_arrays([[1, 2, 3, 4], [5, 6, 7, 8]], names=['a', 'b'])) + pykx.Table(pykx.q(' + a b + --- + 1 5 + 2 6 + 3 7 + 4 8 + ')) + ``` diff --git a/docs/api/serialize.md b/docs/api/serialize.md new file mode 100644 index 0000000..5cb0758 --- /dev/null +++ b/docs/api/serialize.md @@ -0,0 +1,3 @@ +# Serialization + +::: pykx.serialize diff --git a/docs/extras/comparisons.md b/docs/extras/comparisons.md index 37dcf86..cbfd849 100644 --- a/docs/extras/comparisons.md +++ b/docs/extras/comparisons.md @@ -22,7 +22,7 @@ PyQ brings the Python and q interpreters into the same process so that code writ Because of this, it is impossible to develop Python software that depends on PyQ, unless you are willing to run it in a different process. This barrier reasonably makes Python developers hesitant to use PyQ, as it locks them into using the PyQ binary to execute their program. -PyKX provide a more Pythonic approach to interfacing between Python and q than is offered by PyQ. For one PyKX can be run explicitly from a Python session unlike PyQ which relies on execution of a special binary or initialisation from q. In addition to this PyKX provides a class-based hierarchical type system built atop q's type management system. This allows for sub-classes to be used. PyKX also provides a [context interface](../api/pykx-execution/ctx.md) which can be used to load q scripts and interact with q namespaces in a Pythonic manner. Finally the query functionality provided by PyKX allows for more flexibility in the objects used in tabular updates through use of the q functional select, exec, update and delete functions rather than generating a qSQL statement. +PyKX provide a more Pythonic approach to interfacing between Python and q than is offered by PyQ. For one PyKX can be run explicitly from a Python session unlike PyQ which relies on execution of a special binary or initialization from q. In addition to this PyKX provides a class-based hierarchical type system built atop q's type management system. This allows for sub-classes to be used. PyKX also provides a [context interface](../api/pykx-execution/ctx.md) which can be used to load q scripts and interact with q namespaces in a Pythonic manner. Finally the query functionality provided by PyKX allows for more flexibility in the objects used in tabular updates through use of the q functional select, exec, update and delete functions rather than generating a qSQL statement. ### qPython diff --git a/docs/extras/known_issues.md b/docs/extras/known_issues.md index 9521efe..c60cbf6 100644 --- a/docs/extras/known_issues.md +++ b/docs/extras/known_issues.md @@ -4,3 +4,8 @@ - The timeout value is always set to `0` when using `PYKX_Q_LOCK`. - Enabling `PYKX_ALLOCATOR` and using PyArrow tables can cause segfaults in certain scenarios. - `kurl` functions require their `options` dictionary to have mixed type values. Add a `None` value to bypass: `{'': None, ...}` (See [docs](https://code.kx.com/insights/core/kurl/kurl.html)) +- Pandas 2.0 has deprecated the `datetime64[D/M]` types. + - Due to this change it is not always possible to determine if the resulting q Table should + use a `MonthVector` or a `DayVector`. In the scenario that it is not possible to determine + the expected type a warning will be raised and the `DayVector` type will be used as a + default. diff --git a/docs/faq.md b/docs/faq.md index 57e4ddd..977c223 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -5,7 +5,7 @@ ``` >>> import pykx as kx :228: PyKXWarning: Failed to initialize embedded q; falling back to unlicensed mode, which has limited functionality. Refer to https://code.kx.com/pykx/user-guide/advanced/modes.html for more information. Captured output from initialization attempt: - '2022.09.15T10:32:13.419 licence error: cores + '2022.09.15T10:32:13.419 license error: cores ``` This error indicates your license is limited to a given number of cores but PyKX tried to use more cores than the license allows. diff --git a/docs/getting-started/installing.md b/docs/getting-started/installing.md index b2027a9..1ff26c6 100644 --- a/docs/getting-started/installing.md +++ b/docs/getting-started/installing.md @@ -154,6 +154,7 @@ PyKX depends on the following third-party Python packages: - `pandas~=1.2` - `numpy~=1.22` - `pytz~=2022.1` +- `toml~=0.10.2` They are installed automatically by `pip` when PyKX is installed. diff --git a/docs/getting-started/interface_overview.ipynb b/docs/getting-started/interface_overview.ipynb index fa762d3..493e0ad 100644 --- a/docs/getting-started/interface_overview.ipynb +++ b/docs/getting-started/interface_overview.ipynb @@ -71,7 +71,8 @@ "warnings.filterwarnings('ignore') # Do not copy, as we are skipping symlinking pyKX to QHOME the core insights libraries will not be copied over and will raise warnings\n", "os.environ['IGNORE_QHOME'] = '1' # Ignore symlinking PyKX q libraries to QHOME \n", "os.environ['PYKX_Q_LOADED_MARKER'] = '' # Only used here for running Notebook under mkdocs-jupyter during document generation.\n", - "import pykx as kx" + "import pykx as kx\n", + "kx.q.system.console_size = [10, 80]" ] }, { @@ -197,8 +198,8 @@ " 'col3': ['Hello', 'World']})\n", "patable = pa.Table.from_pandas(pdtable)\n", "\n", - "print(kx.K(pdtable))\n", - "# print(kx.K(patable))" + "display(kx.K(pdtable))\n", + "# display(kx.K(patable))" ] }, { @@ -339,7 +340,7 @@ "### Table conversions\n", "Conversions between q keyed and unkeyed tables to an appropriate Python representation are supported for the `py()`, `np()`, `pd()` and `pa()` methods.\n", "\n", - "Round trip conversions `q -> Python -> q` are however only supported for Pandas and PyArrow. Conversions from numpy records are still to be completed and the most natural representation for a table in native python is a dictionary as such the conversion from python to q returns a q dictionary rather than a table\n", + "Round trip conversions `q -> Python -> q` are however only supported for Pandas and PyArrow. Conversions from Numpy records are still to be completed and the most natural representation for a table in native python is a dictionary as such the conversion from python to q returns a q dictionary rather than a table\n", "\n", "Define a q table containing all q data types for conversion" ] @@ -371,8 +372,8 @@ "metadata": {}, "outputs": [], "source": [ - "print(qtab.pd())\n", - "print(qtab.pa())" + "display(qtab.pd())\n", + "display(qtab.pa())" ] }, { @@ -826,7 +827,7 @@ "kx.q('`:db/2020.03/t/ set ([] a:2+til 3; b:\"bat\"; c:-3?0Ng)')\n", "kx.q(r'\\l db')\n", "t_partitioned = kx.q('t')\n", - "print(t_partitioned)" + "t_partitioned" ] }, { @@ -1072,7 +1073,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(kx.q.uj(s,t))" + "kx.q.uj(s,t)" ] }, { @@ -1194,7 +1195,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(kx.q.demo_extension.test_data)" + "kx.q.demo_extension.test_data" ] }, { @@ -1212,7 +1213,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(kx.q.demo_extension.test_function(kx.q.demo_extension.test_data))" + "kx.q.demo_extension.test_function(kx.q.demo_extension.test_data)" ] }, { @@ -1293,7 +1294,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(kx.q.qsql.select(qtab))" + "kx.q.qsql.select(qtab)" ] }, { @@ -1309,7 +1310,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(kx.q.qsql.select(qtab))" + "kx.q.qsql.select(qtab)" ] }, { @@ -1327,7 +1328,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(kx.q.qsql.select('qtab'))" + "kx.q.qsql.select('qtab')" ] }, { @@ -1347,8 +1348,8 @@ "metadata": {}, "outputs": [], "source": [ - "# print(kx.q.qsql.select(qtab, where='col1=`a'))\n", - "print(kx.q.qsql.select(qtab, where=['col3<0.5', 'col2>0.7']))" + "# kx.q.qsql.select(qtab, where='col1=`a')\n", + "kx.q.qsql.select(qtab, where=['col3<0.5', 'col2>0.7'])" ] }, { @@ -1427,8 +1428,8 @@ "metadata": {}, "outputs": [], "source": [ - "print(kx.q.qsql.delete(qtab))\n", - "print(kx.q.qsql.delete('qtab'))" + "kx.q.qsql.delete(qtab)\n", + "kx.q.qsql.delete('qtab')" ] }, { @@ -1452,8 +1453,8 @@ "metadata": {}, "outputs": [], "source": [ - "# print(kx.q.qsql.delete(qtab, columns = 'col3'))\n", - "print(kx.q.qsql.delete(qtab, columns = ['col1','col2']))" + "# kx.q.qsql.delete(qtab, columns = 'col3')\n", + "kx.q.qsql.delete(qtab, columns = ['col1','col2'])" ] }, { @@ -1477,7 +1478,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(kx.q.qsql.delete(qtab, where='col1 in `a`b'))" + "kx.q.qsql.delete(qtab, where='col1 in `a`b')" ] }, { @@ -1506,7 +1507,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(kx.q('qtab'))" + "kx.q('qtab')" ] }, { @@ -1535,10 +1536,10 @@ "metadata": {}, "outputs": [], "source": [ - "# print(kx.q.qsql.update({'avg_col2':'avg col2'}, by={'col1': 'col1'}))\n", - "# print(kx.q.qsql.update({'col3':100}, where='col1=`a'))\n", + "# kx.q.qsql.update({'avg_col2':'avg col2'}, by={'col1': 'col1'})\n", + "# kx.q.qsql.update({'col3':100}, where='col1=`a')\n", "kx.q.qsql.update('qtab', {'col2': 4.2}, 'col1=`b', modify=True)\n", - "print(kx.q['qtab'])" + "kx.q['qtab']" ] }, { diff --git a/docs/getting-started/quickstart.md b/docs/getting-started/quickstart.md index 26f769f..279eaac 100644 --- a/docs/getting-started/quickstart.md +++ b/docs/getting-started/quickstart.md @@ -191,7 +191,19 @@ PyKX objects can be interacted with in a variety of ways, through indexing using pykx.FloatVector(pykx.q('0.3992327 1.726329 2.488636 3.653597 4.028107 5.444905 6.542917 7.00628 8.152..')) ``` -* Pass a PyKX array objects to a numpy functions +* Apply a Python function on a PyKX Vector + + ```python + >>> qvec = kx.random.random(10, 10, seed=42) + >>> qvec + pykx.LongVector(pykx.q('4 7 2 2 9 4 2 0 8 0')) + >>> qvec.apply(lambda x:x+1) + pykx.LongVector(pykx.q('5 8 3 3 10 5 3 1 9 1')) + ``` + + + +* Pass a PyKX array objects to a Numpy functions ```python >>> qarray1 = kx.toq([random() for _ in range(10)], kx.FloatVector) @@ -265,7 +277,7 @@ PyKX objects can be interacted with in a variety of ways, through indexing using ## Converting PyKX objects to common Python types -Objects generated via the PyKX library can be converted where reasonable to `Python`, `Numpy`, `Pandas` and `PyArrow` types which are analagous to their underlying q representation. For example q tables are converted to Pandas Dataframes and PyArrow tables respectively. This is facilitated in each case through the use of the `py`, `np`, `pd` and `pa` methods. +Objects generated via the PyKX library can be converted where reasonable to `Python`, `Numpy`, `Pandas` and `PyArrow` types which are analogous to their underlying q representation. For example q tables are converted to Pandas Dataframes and PyArrow tables respectively. This is facilitated in each case through the use of the `py`, `np`, `pd` and `pa` methods. * Convert PyKX objects to Python diff --git a/docs/index.md b/docs/index.md index e5ebfde..f7050ad 100644 --- a/docs/index.md +++ b/docs/index.md @@ -2,36 +2,52 @@ ## About -PyKX is an interface between the vector programming language q, it's associated time-series columnar database kdb+, underlying data types and Python. This provides users with the ability to efficiently interact with the worlds fastest time-series database and to apply analytics against vast amounts of data in-memory or on-disk. +PyKX is a Python-first interface for the q language and its time-series vector database kdb+. -PyKX takes a Python-first approach to this integration. This is to say it takes the stance that q should be used primarily as a data processing engine and database. Additionally q should be used primarily as a domain-specific language (DSL) embedded within Python, which is a more general-purpose language. +For Python developers, PyKX unlocks the speed and power of kdb+ for data processing and storage from within your Python environment. It enables anyone with Python knowledge to apply analytics against vast amounts of data, both in-memory and on-disk, in a fraction of the time, allowing you to focus on getting the best from your data. -This is not to say that the interface is limiting to developers familiar to q. Expert users of q using this interface are capable of running the same analyses they would normally run within a q process using PyKX. If a user so chooses, they can simply run q code through PyKX. However, through PyKX, Python developers who have no experience with q can access and leverage q through a Pythonic interface. +For q developers, PyKX brings together Python's data science ecosystem and the power of kdb+'s vector and time-series analytics. This makes them available in both q and Python environments. You can use it to run q code within a Python environment or embed Python analytics within your q session. -The documentation presented here should provide a user with the stepping stones needed to query vast amounts of historical data, apply vector analytics to q data types and see the value of operating with the q data formats for the application of analytic functions. +To begin your journey with PyKX follow the sections in the grid below. +
-## Documentation Breakdown +- :material-run-fast:{ .lg .middle } __Getting Started__ -### [Getting Started](getting-started/what_is_pykx.md) + --- -This provides documentation for users that are new to q/kdb+ and PyKX. Included in this section are installation instructions and quickstart guides which should allow a user to get up and running. + Documentation for users new to PyKX! Contains installation instructions + alongside quickstart guides and sample getting started notebooks. + -### [User Guide](user-guide/index.md) + [:octicons-arrow-right-24: Getting started](getting-started/what_is_pykx.md) -Our user guide provides useful information which allows a user to get an understanding of the key concepts behind PyKX, how the library is intended to be used and includes examples of the library functionality. +- :material-book-open-variant:{ .lg .middle } __User Guide__ -### [API](api/pykx-execution/q.md) + --- -The API reference guide contains detailed descriptions of the functions, modules and objects managed by PyKX. It describes how functions can be called, data types manipulated and data queried in addition to much broader usage of the library. Use of the API reference assumes you have a strong understanding of how the library is intended to be used through the getting started and user guide sections. + Useful information allowing users to understand the key concepts that behind PyKX. + Including how the library is intended to be used and examples of this fucntionality. + -### Extras + [:octicons-arrow-right-24: User Guide](user-guide/index.md) -The `Extras` section contains additional information users may find interesting, this includes the following: +- :material-api:{ .lg .middle } __API Reference__ -- [Known interface issues](extras/known_issues.md) -- [Comparisons against other q-Python interfaces](extras/comparisons.md) + --- -## [Getting Help](support.md) + Detailed descriptions of the functions, modules and objects managed by PyKX. Using + the API reference assumes you have an understanding of how PyKX is intended to be used + through the getting started and user guide. -If you have any issues or questions relating to PyKX the support page provides users with links to helpful community locations and support contact information for PyKX. + [:octicons-arrow-right-24: API reference](api/pykx-execution/q.md) + +- :material-alert-decagram:{ .lg .middle } __Release Notes__ + + --- + + The latest additions and fixes for PyKX alongside historical changes. + + [:octicons-arrow-right-24: Release notes](release-notes/changelog.md) + +
diff --git a/docs/pykx-under-q/api.md b/docs/pykx-under-q/api.md index 1f7f2ff..23d0b3f 100644 --- a/docs/pykx-under-q/api.md +++ b/docs/pykx-under-q/api.md @@ -582,7 +582,7 @@ type | description `::` | Returns null on successful execution ```q -// Set a q array of guids using default behaviour +// Set a q array of guids using default behavior q).pykx.set[`test;3?0Ng] q)print .pykx.get`test [UUID('3d13cc9e-f7f1-c0ee-782c-5346f5f7b90e') @@ -644,7 +644,7 @@ type | description | q).pykx.pyexec"aclass = type('TestClass', (object,), {'x': pykx.LongAtom(3), 'y': pykx.toq('hello')})"; q)a:.pykx.get`aclass -// Retrieve an existing attribute to show defined behaviour +// Retrieve an existing attribute to show defined behavior q)a[`:x]` 3 @@ -670,7 +670,7 @@ q).pykx.print a[`:k] 0 0.493183 0a3e1784-0125-1b68-5ae7-962d49f2404d mi 1 0.578520 5aecf7c8-abba-e288-5a58-0fb6656b5e69 ig -// Attempt to set an attribute against an object which does not support this behaviour +// Attempt to set an attribute against an object which does not support this behavior q)arr:.pykx.eval"[1, 2, 3]" q).pykx.setattr[arr;`test;5] 'AttributeError("'list' object has no attribute 'test'") @@ -1047,7 +1047,7 @@ pyarglist argList name | type | description -----------|--------|------------ -`argList` | `list` | List of opsitional arguments +`argList` | `list` | List of optional arguments **Return:** diff --git a/docs/pykx-under-q/intro.md b/docs/pykx-under-q/intro.md index 9dabbdf..94e4dee 100644 --- a/docs/pykx-under-q/intro.md +++ b/docs/pykx-under-q/intro.md @@ -38,7 +38,7 @@ To facilitate the execution of Python code within a q session a user must first python -c "import pykx;pykx.install_into_QHOME(to_local_folder=True)" ``` -### Initialisation +### Initialization Once installation has been completed a user should be in a position to initialise the library as follows @@ -111,7 +111,7 @@ This interface allows a user to execute Python code a variety of ways: $ q pykx.q q)\l test.p q).pykx.get[`func] - {[f;x].pykx.i.pykx[f;x]}[foreign]enlist + {[f;x].pykx.util.pykx[f;x]}[foreign]enlist ``` #### Evaluating Python code @@ -144,7 +144,7 @@ Finally to return a hybrid representation which can be manipulated to return the ```q q)show b:.pykx.eval"1+2" -{[f;x].pykx.i.pykx[f;x]}[foreign]enlist +{[f;x].pykx.util.pykx[f;x]}[foreign]enlist q)b` // Convert to a q object 3 q)b`. // Convert to a Python foreign @@ -165,14 +165,14 @@ Foreign objects can be stored in variables just like any other q datatype, or as Foreign objects cannot be directly operated on in q. Instead, Python objects are typically represented as PyKX objects, which wrap the underlying foreign objects. This provides the ability to get and set attributes, index, call or convert the underlying foreign object to a q object. -Use .pykx.wrap to create an PyKX object from a foreign object. +Use `.pykx.wrap` to create an PyKX object from a foreign object. ```q q)x foreign q)p:.pykx.wrap x q)p /how an PyKX object looks -{[f;x].pykx.i.pykx[f;x]}[foreign]enlist +{[f;x].pykx.util.pykx[f;x]}[foreign]enlist ``` More commonly, PyKX objects are retrieved directly from Python using one of the following functions: @@ -199,7 +199,7 @@ For example: ```q q)x:.pykx.eval"(1,2,3)" q)x -{[f;x].pykx.i.pykx[f;x]}[foreign]enlist +{[f;x].pykx.util.pykx[f;x]}[foreign]enlist q)x`. foreign q)x` @@ -320,10 +320,10 @@ For example ```q q)np:.pykx.import`numpy q)np`:arange -{[f;x].pykx.i.pykx[f;x]}[foreign]enlist +{[f;x].pykx.util.pykx[f;x]}[foreign]enlist q)arange:np`:arange / callable returning PyKX object q)arange 12 -{[f;x].pykx.i.pykx[f;x]}[foreign]enlist +{[f;x].pykx.util.pykx[f;x]}[foreign]enlist q)arange[12]` 0 1 2 3 4 5 6 7 8 9 10 11 ``` @@ -454,7 +454,15 @@ In particular the following types are supported: 4. PyArrow objects 5. PyKX objects -By default when passing a q object to a callable function it will be converted to it's underlying Numpy equivalent representation. This will be the case for all types including tabular structures which are converted to numpy records. +By default when passing a q object to a callable function it will be converted to the most "natural" analogous types. This is controlled through the setting of `.pykx.util.defaultConv` + +- PyKX/q generic list objects will be converted to Python lists +- PyKX/q table/keyed table objects will be converted to Pandas equivalent DataFrames +- All other PyKX/q objects will be converted to their analogous PyKX/q types + +!!! Warning + + Prior to PyKX 2.1.0 all conversions from q objects to Python would convert to their Numpy equivalent. This behaviour raised a number of issues with migration for users previously operating with embedPy and as such has been migrated to the behaviour described above. If you require the same behaviour as that prior to 2.1.0 please set the environment variable `PYKX_DEFAULT_CONVERSION="np"` For example: @@ -464,32 +472,35 @@ q)typeFunc 1; q)typeFunc til 10; +q)typeFunc (10?1f;10?1f) + q)typeFunc ([]100?1f;100?1f); - + ``` -The default behaviour of the conversions which are undertaken when making function/method calls is controlled through the definition of `.pykx.i.defaultConv` +The default behavior of the conversions which are undertaken when making function/method calls is controlled through the definition of `.pykx.util.defaultConv` ```q -q).pykx.i.defaultConv -"np" +q).pykx.util.defaultConv +"default" ``` This can have one of the following values: -| Python type | Value | -|-------------|-------| -| Python | "py" | -| Numpy | "np" | -| Pandas | "pd" | -| PyArrow | "pa" | -| PyKX | "k" | +| Python type | Value | +|-------------|-----------| +| Default | "default" | +| Python | "py" | +| Numpy | "np" | +| Pandas | "pd" | +| PyArrow | "pa" | +| PyKX | "k" | -Taking the examples above for numpy we can update the default types across all function calls +Taking the examples above for Numpy we can update the default types across all function calls ```q q)typeFunc:.pykx.eval"lambda x:print(type(x))" -q).pykx.i.defaultConv:"py" +q).pykx.util.defaultConv:"py" q)typeFunc 1; q)typeFunc til 10; @@ -497,7 +508,7 @@ q)typeFunc til 10; q)typeFunc ([]100?1f;100?1f); -q).pykx.i.defaultConv:"pd" +q).pykx.util.defaultConv:"pd" q)typeFunc 1; q)typeFunc til 10; @@ -505,7 +516,7 @@ q)typeFunc til 10; q)typeFunc ([]100?1f;100?1f); -q).pykx.i.defaultConv:"pa" +q).pykx.util.defaultConv:"pa" q)typeFunc 1; q)typeFunc til 10; @@ -513,7 +524,7 @@ q)typeFunc til 10; q)typeFunc ([]100?1f;100?1f); -q).pykx.i.defaultConv:"k" +q).pykx.util.defaultConv:"k" q)typeFunc 1; q)typeFunc til 10; @@ -550,7 +561,7 @@ q).pykx.qeval"var1" 42 q).pykx.set[`var2;{x*2}] q)qfunc:.pykx.get[`var2;<] -{[f;x].pykx.i.pykx[f;x]}[foreign]enlist +{[f;x].pykx.util.pykx[f;x]}[foreign]enlist q)qfunc[3] 6 ``` diff --git a/docs/pykx-under-q/upgrade.md b/docs/pykx-under-q/upgrade.md index d1274d4..a9d1967 100644 --- a/docs/pykx-under-q/upgrade.md +++ b/docs/pykx-under-q/upgrade.md @@ -1,6 +1,6 @@ # Differences and upgrade considerations from embedPy -As outlined [here](intro.md) PyKX provides users with the ability to execute Python code within a q session similar to [embedPy](https://github.com/kxsystems/embedpy). This document outlines points of consideration when upgrading from embedPy to PyKX under q both with respect to the function mappings between the two interfaces and differences in their behaviour. +As outlined [here](intro.md) PyKX provides users with the ability to execute Python code within a q session similar to [embedPy](https://github.com/kxsystems/embedpy). This document outlines points of consideration when upgrading from embedPy to PyKX under q both with respect to the function mappings between the two interfaces and differences in their behavior. ## Functional differences @@ -33,7 +33,7 @@ EmbedPy does not allow users to discern between q string and symbol types when c ### Python object type support -EmbedPy contains a fundamental limitation with respect to the data formats that are supported when converting betwen q and Python. Namely that all q objects when passed to Python functions use the analagous Python/Numpy representation. This limitation means that a user of embedPy must handle their own data conversions when handling Pandas or PyArrow objects. +EmbedPy contains a fundamental limitation with respect to the data formats that are supported when converting between q and Python. Namely that all q objects when passed to Python functions use the analogous Python/Numpy representation. This limitation means that a user of embedPy must handle their own data conversions when handling Pandas or PyArrow objects. PyKX natively supports data conversions from q to Python, Numpy, Pandas and PyArrow and as such can support workflows which previously required users to manually control these conversions, for example: @@ -56,7 +56,7 @@ The following table describes the function mapping from PyKX to embedPy for vari | Execute Python code returning as intermediary q/Python object | `.pykx.eval` | `.p.eval` | | Execute Python code returning a q object | `.pykx.qeval` | `.p.qeval` | | Execute Python code returning a Python foreign object | `.pykx.pyeval` | `.p.eval` | -| Retrieve a printable representation of a supplied PyKX/q objext | `.pykx.repr` | `.p.repr` | +| Retrieve a printable representation of a supplied PyKX/q object | `.pykx.repr` | `.p.repr` | | Set an attribute on a supplied Python object | `.pykx.setattr` | `.p.setattr` | | Retrieve an attribute from a supplied Python object | `.pykx.getattr` | `.p.getattr` | | Convert a Python foreign object to a wrapped object for conversion | `.pykx.wrap` | `.p.wrap` | diff --git a/docs/release-notes/changelog.md b/docs/release-notes/changelog.md index 4058c3c..00f021d 100644 --- a/docs/release-notes/changelog.md +++ b/docs/release-notes/changelog.md @@ -4,16 +4,162 @@ The changelog presented here outlines changes to PyKX when operating within a Python environment specifically, if you require changelogs associated with PyKX operating under a q environment see [here](./underq-changelog.md). +## PyKX 2.1.0 + +#### Release Date + +2023-10-09 + +### Additions + +- Added functionality to the CSV Reader to allow for the input of data structures while defining column types. For example, +the following reads a CSV file and specifies the types of the three columns named `x1`, `x2` and `x3` to be of type `Integer`, `GUID` and `Timestamp`. + + ```python + >>> table = q.read.csv('example.csv', {'x1':kx.IntAtom,'x2':kx.GUIDAtom,'x3':kx.TimestampAtom}) + ``` + +- Conversions from Pandas Dataframes and PyArrow tables using `pykx.toq` can now specify the `ktype` argument as a dictionary allowing selective type conversions for defined columns + + ```python + >>> import pykx as kx + >>> import pandas as pd + >>> df = pd.DataFrame.from_dict({'x': [1, 2], 'y': ['a', 'b']}) + >>> kx.toq(df).dtypes + pykx.Table(pykx.q(' + columns type + ----------------------- + x "kx.LongAtom" + y "kx.SymbolAtom" + ')) + >>> kx.toq(df, ktype={'x': kx.FloatAtom}).dtypes + pykx.Table(pykx.q(' + columns type + ----------------------- + x "kx.FloatAtom" + y "kx.SymbolAtom" + ')) + ``` + +- Addition of the ability for users to run an `apply` method on vector objects within PyKX allowing the application of Python/PyKX functionality on these vectors directly + + ```python + >>> import pykx as kx + >>> random_vec = kx.random.random(2, 10.0, seed=100) + >>> random_vec + pykx.FloatVector(pykx.q('8.909647 3.451941')) + >>> random_vec.apply(lambda x:x+1) + pykx.FloatVector(pykx.q('9.909647 4.451941')) + >>> def func(x, y): + ... return x+y + >>> random_vec.apply(func, y=2) + pykx.FloatVector(pykx.q('10.909647 5.451941')) + ``` + +- Notebooks will HTML print tables and dictionaries through the addition of `_repr_html_`. Previous `q` style output is still available using `print`. +- Added [`serialize` and `deserialize`](../api/serialize.html) as base methods to assist with the serialization of `K` objects for manual use over IPC. +- Added support for `pandas` version `2.0`. + +!!! Warning "Pandas 2.0 has deprecated the `datetime64[D/M]` types." + + Due to this change it is not always possible to determine if the resulting q Table should + use a `MonthVector` or a `DayVector`. In the scenario that it is not possible to determine + the expected type a warning will be raised and the `DayVector` type will be used as a + default. + +### Fixes and Improvements + +- Empty PyKX keyed tables can now be converted to Pandas DataFrames, previously this would raise a `ValueError` + + ```python + >>> import pykx as kx + >>> df = kx.q('0#`a xkey ([]a:1 2 3;b:3 4 5)').pd() + >>> df + Empty DataFrame + Columns: [b] + Index: [] + >>> df.index.name + 'a' + >>> kx.toq(df) + pykx.KeyedTable(pykx.q(' + a| b + -| - + ')) + ``` + +- Fix to issue introduced in 2.0.0 where indexing of `pykx.Table` returned incorrect values when passed negative/out of range values + + === "Behavior prior to change" + + ```python + >>> import pykx as kx + >>> tab = kx.Table(data={"c1": list(range(3))}) + >>> tbl[-1] + pykx.Table(pykx.q(' + c1 + -- + + ')) + >>> tab[-4] + pykx.Table(pykx.q(' + c1 + -- + + ')) + >>> tab[3] + pykx.Table(pykx.q(' + c1 + -- + + ')) + ``` + + === "Behavior post change" + + ```python + >>> import pykx as kx + >>> tab = kx.Table(data={"c1": list(range(3))}) + >>> tab[-1] + pykx.Table(pykx.q(' + c1 + -- + 2 + ')) + >>> tab[-4] + ... + IndexError: index out of range + >>> tab[3] + ... + IndexError: index out of range + ``` + +- Fix to issue where PyKX would not initialize when users with a [`QINIT`](https://code.kx.com/q/basics/by-topic/#environment) environment variable set which pointed to a file contained a `show` statement +- Retrieval of `dtypes` with tables containing `real` columns will now return `kx.RealAtom` for the type rather than incorrectly returning `kx.ShortAtom` +- Users with [`QINIT`](https://code.kx.com/q/basics/by-topic/#environment) environment variable would previously load twice on initialization within PyKX +- Users installing PyKX under q on Windows had been missing installation of required files using `pykx.install_into_QHOME()` + +### Dependency Updates + +- The version of `Cython` used to build `PyKX` was updated to the full `3.0.x` release version. + ## PyKX 2.0.1 +#### Release Date + +2023-09-21 + ### Fixes and Improvements -- User input based license initialisation introduced in 2.0.0 no longer expects user input when operating in a non-interactive modality, use of PyKX in this mode will revert to previous behaviour +- User input based license initialization introduced in 2.0.0 no longer expects user input when operating in a non-interactive modality, use of PyKX in this mode will revert to previous behavior - Use of the environment variables `QARGS='--unlicensed'` or `QARGS='--licensed'` operate correctly following regression in 2.0.0 - Fix to issue where `OSError` would be raised when `close()` was called on an IPC connection which has already disconnected server side ## PyKX 2.0.0 +#### Release Date + +2023-09-18 + - PyKX 2.0.0 major version increase is required due to the following major changes which are likely to constitute breaking changes - Pandas API functionality is enabled permanently which will modify data indexing and retrieval of `pykx.Table` objects. Users should ensure to review and test their codebase before upgrading. - EmbedPy replacement functionality for PyKX under q is now non-beta for Linux and MacOS installations, see [here](underq-changelog.md) for full information on 2.0.0 changelog. @@ -73,7 +219,7 @@ pykx.FloatVector(pykx.q('1 2f')) ``` -- Support for fixed length string dtype with numpy arrays +- Support for fixed length string dtype with Numpy arrays ```python >>> import pykx as kx @@ -91,7 +237,7 @@ - Return of Pandas API functions `dtypes`, `columns`, `empty`, `ndim`, `size` and `shape` return `kx` objects rather than Pythonic objects - Removed GLIBC_2.34 dependency for conda installs - Removed the ability for users to incorrectly call `pykx.q.{select/exec/update/delete}` with error message now suggesting usage of `pykx.q.qsql.{function}` -- Fixed behaviour of `loc` when used on `KeyedTable` objects to match the pandas behaviour. +- Fixed behavior of `loc` when used on `KeyedTable` objects to match the pandas behavior. - Addition of warning on failure to link the content of a users `QHOME` directory pointing users to documentation for warning suppression - Update to PyKX foreign function handling to support application of Path objects as first argument i.e. ```q("{[f;x] f x}")(lambda x: x)(Path('test'))``` - SQL interface will attempt to automatically load on Windows and Mac @@ -99,7 +245,7 @@ - Messages mistakenly sent to a PyKX client handle are now gracefully ignored. - Application of Pandas API `dtypes` operations return a table containing `column` to `type` mappings with `PyKX` object specific types rather than Pandas/Python types - === "Behaviour prior to change" + === "Behavior prior to change" ```python >>> table = kx.Table([[1, 'a', 2.0, b'testing', b'b'], [2, 'b', 3.0, b'test', b'a']]) @@ -117,7 +263,7 @@ dtype: object ``` - === "Behaviour post change" + === "Behavior post change" ```python >>> table = kx.Table([[1, 'a', 2.0, b'testing', b'b'], [2, 'b', 3.0, b'test', b'a']]) @@ -140,7 +286,7 @@ - Fixed an issue where inequality checks would return `False` incorrectly - === "Behaviour prior to change" + === "Behavior prior to change" ```python >>> import pykx as kx @@ -148,7 +294,7 @@ pykx.q('0b') ``` - === "Behaviour post change" + === "Behavior post change" ```python >>> import pykx as kx @@ -162,21 +308,27 @@ ## PyKX 1.6.3 +#### Release Date + +2023-08-18 + ### Additions - Addition of argument `return_info` to `pykx.util.debug_environment` allowing user to optionally return the result as a `str` rather than to stdout -## PyKX 1.6.3 - ### Fixes and Improvements -- Fixed Pandas API use of `ndim` functionality which should return `2` when interacting with tables following the expected Pandas behaviour. +- Fixed Pandas API use of `ndim` functionality which should return `2` when interacting with tables following the expected Pandas behavior. - Fixed an error when using the Pandas API to update a column with a `Symbols`, `Characters`, and `Generic Lists`. - Prevent attempting to pass wrapped Python functions over IPC. - Support IPC payloads over 4GiB. ## PyKX 1.6.2 +#### Release Date + +2023-08-15 + ### Additions - Added `to_local_folder` kwarg to `install_into_QHOME` to enable use of `pykx.q` without write access to `QHOME`. @@ -193,11 +345,15 @@ ## PyKX 1.6.1 +#### Release Date + +2023-07-19 + ### Additions - Added `sorted`, `grouped`, `parted`, and `unique`. As methods off of `Tables` and `Vectors`. - Added `PyKXReimport` class to allow subprocesses to reimport `PyKX` safely. - - Also includes `.pykx.safeReimport` in `pykx.q` to allows this behaviour when running under q as well. + - Also includes `.pykx.safeReimport` in `pykx.q` to allows this behavior when running under q as well. - Added environment variables to specify a path to `libpython` in the case `pykx.q` cannot find it. ### Fixes and Improvements @@ -210,10 +366,14 @@ - Updated insights libraries to 4.0.2 - Fixed `pykx.q` functionality when run on Windows. - Fixed an issue where reimporting `PyKX` when run under q would cause a segmentation fault. -- Updated the warning message for the insights core libraries failing to load to make it more clear that no error has occured. +- Updated the warning message for the insights core libraries failing to load to make it more clear that no error has occurred. ## PyKX 1.6.0 +#### Release Date + +2023-06-16 + ### Additions - Added `merge_asof` to the Pandas like API. @@ -225,7 +385,7 @@ - q vector type promotion in licensed mode. - Added `.pykx.toraw` to `pykx.q` to enable raw conversions (e.g. `kx.toq(x, raw=True)`) - Added support for Python `3.11`. - - Support for pyarrow in this python version is currently in Beta. + - Support for PyArrow in this python version is currently in Beta. - Added the ability to use `kx.RawQConnection` as a Python based `q` server using `kx.RawQConnection(port=x, as_server=True)`. - More documentation around using this functionality can be found [here](../examples/server/server.md). @@ -262,6 +422,10 @@ ## PyKX 1.5.3 +#### Release Date + +2023-05-18 + ### Additions - Added support for Pandas `Float64Index`. @@ -269,12 +433,20 @@ ## PyKX 1.5.2 +#### Release Date + +2023-04-30 + ### Additions - Added support for ARM 64 Linux. ## PyKX 1.5.1 +#### Release Date + +2023-04-28 + ### Fixes and Improvements - Fixed an issue with `pykx.q` that caused errors to not be raised properly under q. @@ -282,6 +454,10 @@ ## PyKX 1.5.0 +#### Release Date + +2023-04-17 + ### Additions - Added wrappers around various `q` [system commands](https://code.kx.com/q/basics/syscmds/). @@ -303,20 +479,32 @@ ## PyKX 1.4.2 +#### Release Date + +2023-03-08 + ### Fixes and Improvements - Fixed an issue that would cause `EmbeddedQ` to fail to load. ## PyKX 1.4.1 +#### Release Date + +2023-03-06 + ### Fixes and Improvements - Added constructors for `Table` and `KeyedTable` objects to allow creation of these objects from dictionaries and list like objects. - Fixed a memory leak around calling wrapped `Foreign` objects in `pykx.q`. -- Fixed an issue around the `tls` keyword argument when creating `QConnection` instances, as well as a bug in the unlicensed behaviour of `SecureQConnection`'s. +- Fixed an issue around the `tls` keyword argument when creating `QConnection` instances, as well as a bug in the unlicensed behavior of `SecureQConnection`'s. ## PyKX 1.4.0 +#### Release Date + +2023-01-23 + ### Additions - Addition of a utility function `kx.ssl_info()` to retrieve the SSL configuration when running in unlicensed mode (returns the same info as kx.q('-26!0') with a license). @@ -336,8 +524,8 @@ - Improved error output of `kx.QConnection` objects when an error is raised within the context interface. - Fixed `.py()` conversion of nested `k.Dictionary` objects and keyed `k.Dictionary` objects. - Fixed unclear error message when querying a `QConnection` instance that has been closed. -- Added support for conversions of non C contiguous numpy arrays. -- Fixed conversion of null `GUIDAtom`'s to and from numpy types. +- Added support for conversions of non C contiguous Numpy arrays. +- Fixed conversion of null `GUIDAtom`'s to and from Numpy types. - Improved performance of converting `q` enums to pandas Categoricals. ### Beta Features @@ -347,12 +535,20 @@ ## PyKX 1.3.2 +#### Release Date + +2023-01-06 + ### Features and Fixes - Fixed support for using TLS with `SyncQConnection` instances. ## PyKX 1.3.1 +#### Release Date + +2022-11-16 + ### Features and Fixes - Added environment variable `PYKX_Q_LIB_LOCATION` to specify a path to load the PyKX q libraries from. @@ -372,9 +568,13 @@ ## PyKX 1.3.0 +#### Release Date + +2022-10-20 + ### Features and Fixes -- Support for converting `datetime.datetime` objects with timezone information into `pykx.TimestampAtom`s and `pykx.TimestampVector`s. +- Support for converting `datetime.datetime` objects with time zone information into `pykx.TimestampAtom`s and `pykx.TimestampVector`s. - Added a magic command to run cells of q code in a Jupyter Notebook. The addition of `%%q` at the start of a Jupyter Notebook cell will allow a user to execute q code locally similarly to loading a q file. - Added `no_ctx` key word argument to `pykx.QConnection` instances to disable sending extra queries to/from q to manage the context interface. - Improvements to SQL interface for PyKX including the addition of support for prepared statements, execution of these statements and retrieval of inputs see [here](../api/query.md#pykx.query.SQL) for more information. @@ -383,16 +583,24 @@ ### Beta Features -- EmbedPy replacement functionality `pykx.q` updated significantly to provide parity with embedPy from a syntax perspective. Documentation of the interface [here](../pykx-under-q/intro.md) provides API usage. Note that initialisation requires the first version of Python to be retrieved on a users `PATH` to have PyKX installed. Additional flexibility with respect to installation location is expected in `1.4.0` please provide any feedback to `pykx@kx.com` +- EmbedPy replacement functionality `pykx.q` updated significantly to provide parity with embedPy from a syntax perspective. Documentation of the interface [here](../pykx-under-q/intro.md) provides API usage. Note that initialization requires the first version of Python to be retrieved on a users `PATH` to have PyKX installed. Additional flexibility with respect to installation location is expected in `1.4.0` please provide any feedback to `pykx@kx.com` ## PyKX 1.2.2 +#### Release Date + +2022-10-01 + ### Features and Fixes -- Fixed an issue causing the timeout argument for `QConnection` instances to not work work properly. +- Fixed an issue causing the timeout argument for `QConnection` instances to not work properly. ## PyKX 1.2.1 +#### Release Date + +2022-09-27 + ### Features and Fixes - Added support for OpenSSLv3 for IPC connections created when in 'licensed' mode. @@ -400,36 +608,48 @@ ## PyKX 1.2.0 +#### Release Date + +2022-09-01 + ### Features and Fixes - Support for converting any python type to a `q` Foreign object has been added. - Support for converting Pandas categorical types into `pykx.EnumVector` type objects. - Support for q querying against Pandas/PyArrow tables through internal conversion to q representation and subsequent query. `kx.q.qsql.select()` - Support for casting Python objects prior to converting into K objects. (e.g. `kx.IntAtom(3.14, cast=True)` or `kx.toq("3.14", ktype=kx.FloatAtom, cast=True)`). -- Support usage of numpy [`__array_ufunc__`'s](https://numpy.org/doc/stable/reference/ufuncs.html) directly on `pykx.Vector` types. -- Support usage of numpy `__array_function__`'s directly on `pykx.Vector` types (Note: these will return a numpy ndarray object not an analogous `pykx.K` object). +- Support usage of Numpy [`__array_ufunc__`'s](https://numpy.org/doc/stable/reference/ufuncs.html) directly on `pykx.Vector` types. +- Support usage of Numpy `__array_function__`'s directly on `pykx.Vector` types (Note: these will return a Numpy ndarray object not an analogous `pykx.K` object). - Improved performance of `pykx.SymbolVector` conversion into native Python type (e.g. `.py()` conversion for `pykx.SymbolVector`'s). - Improved performance and memory usage of various comparison operators between `K` types. - Improved performance of various `pykx.toq` conversions. - `pykx.Vector` types will now automatically enlist atomic types instead of erroring. -- Fixed conversions of numpy float types into `pykx.FloatAtom` and `pykx.RealAtom` types. +- Fixed conversions of Numpy float types into `pykx.FloatAtom` and `pykx.RealAtom` types. - Fixed conversion of `None` Python objects into analogous null `K` types if a `ktype` is specified. - Added `event_loop` parameter to `pykx.AsyncQConnection` that takes a running event loop as a parameter and allows the event loop to manage `pykx.QFuture` objects. ### Beta Features - Added extra functionality to `pykx.q` related to the calling and use of python foreign objects directly within a `q` process. -- Support for [NEP-49](https://numpy.org/neps/nep-0049.html), which allows numpy arrays to be converted into `q` Vectors without copying the underlying data. This behaviour is opt-in and you can do so by setting the environment variable `PYKX_ALLOCATOR` to 1, "1" or True or by adding the flag `--pykxalloc` to the `QARGS` environment variable. Note: This feature also requires a python version of at least 3.8. +- Support for [NEP-49](https://numpy.org/neps/nep-0049.html), which allows Numpy arrays to be converted into `q` Vectors without copying the underlying data. This behavior is opt-in and you can do so by setting the environment variable `PYKX_ALLOCATOR` to 1, "1" or True or by adding the flag `--pykxalloc` to the `QARGS` environment variable. Note: This feature also requires a python version of at least 3.8. - Support the ability to trigger early garbage collection of objects in the `q` memory space by adding `--pykxgc` to the QARGS environment variable, or by setting the `PYKX_GC` environment variable to 1, "1" or True. ## PyKX 1.1.1 +#### Release Date + +2022-06-13 + ### Features & Fixes - Added ability to skip symlinking `$QHOME` to `PyKX`'s local `$QHOME` by setting the environment variable `IGNORE_QHOME`. ## PyKX 1.1.0 +#### Release Date + +2022-06-07 + ### Dependencies - The dependency on the system library `libcurl` has been made optional for Linux. If it is missing on Linux, a warning will be emitted instead of an error being raised, and the KX Insights Core library `kurl` will not be fully loaded. Windows and macOS are unaffected, as they don't support the KX Insights Core features to begin with. @@ -461,6 +681,10 @@ ## PyKX 1.0.1 +#### Release Date + +2022-03-18 + ### Deprecations & Removals - The `sync` parameter for `pykx.QConnection` and `pykx.QConnection.__call__` has been renamed to the less confusing name `wait`. The `sync` parameter remains, but its usage will result in a `DeprecationWarning` being emitted. The `sync` parameter will be removed in a future version. @@ -480,6 +704,10 @@ ## PyKX 1.0.0 +#### Release Date + +2022-02-14 + ### Migration Notes To switch from Pykdb to PyKX, you will need to update the name of the dependency from `pykdb` to `pykx` in your `pyproject.toml`/`requirements.txt`/`setup.cfg`/etc. When Pykdb was renamed to PyKX, its version number was reset. The first public release of PyKX has the version number 1.0.0, and will employ [semantic versioning](https://semver.org/). diff --git a/docs/release-notes/underq-changelog.md b/docs/release-notes/underq-changelog.md index ba7bd54..7e9f226 100644 --- a/docs/release-notes/underq-changelog.md +++ b/docs/release-notes/underq-changelog.md @@ -6,13 +6,41 @@ This changelog provides updates from PyKX 2.0.0 and above, for information relat The changelog presented here outlines changes to PyKX when operating within a q environment specifically, if you require changelogs associated with PyKX operating within a Python environment see [here](./changelog.md). +## PyKX 2.1.0 + +### Fixes and Improvements + +- Update to default conversion logic for q objects passed to PyKX functions to more closely match embedPy based conversion expectations.For version <=2.0 conversions of KX lists would produce N Dimensional Numpy arrays of singular type. This results in issues when applying to many analytic libraries which rely on lists of lists rather than singular N Dimensional arrays. Additionally q tables and keyed tables would be converted to numpy recarrays, these are now converted to Pandas DataFrames. To maintain previous behaviour please set the following environment variable `PYKX_DEFAULT_CONVERSION="np"`. + + === "Behaviour prior to change" + + ```q + q).pykx.eval["lambda x:print(type(x))"](10?1f;10?1f) + + q).pykx.eval["lambda x:print(type(x))"]([]10?1f;10?1f) + + ``` + + === "Behaviour post change" + + ```q + q).pykx.eval["lambda x:print(type(x))"](10?1f;10?1f) + + q).pykx.eval["lambda x:print(type(x))"]([]10?1f;10?1f) + + ``` + ## PyKX 2.0.0 +#### Release Date + +2023-09-18 + ### Additions -- Addition of `.pykx.qcallable` and `.pykx.pycallable` fucntions which allow wrapping of a foreign Python callable function returning the result as q or Python foreign respectively. -- Addition of `.pykx.version` allowing users to programatically access their version from a q process. -- Addition of `.pykx.debug` namespace containing copies of useful process initialisation information specific to usage within a q enviroment +- Addition of `.pykx.qcallable` and `.pykx.pycallable` functions which allow wrapping of a foreign Python callable function returning the result as q or Python foreign respectively. +- Addition of `.pykx.version` allowing users to programmatically access their version from a q process. +- Addition of `.pykx.debug` namespace containing copies of useful process initialization information specific to usage within a q environment - Addition of function `.pykx.debugInfo` which returns a string representation of useful information when debugging issues with the the use of PyKX within the q environment - Added the ability for users to print the return of a `conversion` object diff --git a/docs/spelling.txt b/docs/spelling.txt index 927a39d..286571f 100644 --- a/docs/spelling.txt +++ b/docs/spelling.txt @@ -5,8 +5,11 @@ booleans callables canonicalized changelog +changelogs CPython ctx +ctxa +ctxb dataframe dataframes dataset @@ -19,12 +22,14 @@ disambiguated docstring dtype ey +getattr hopen hsym indexable infinities introspectable ipc +kx localhost mul namespace @@ -48,7 +53,9 @@ QHOME qPython qSQL quickstart +reimporting subclasses +schemas symlink symlinks timedelta diff --git a/docs/user-guide/advanced/Pandas_API.ipynb b/docs/user-guide/advanced/Pandas_API.ipynb index 6df7fb1..cb98590 100644 --- a/docs/user-guide/advanced/Pandas_API.ipynb +++ b/docs/user-guide/advanced/Pandas_API.ipynb @@ -32,7 +32,8 @@ "os.environ['PYKX_Q_LOADED_MARKER'] = '' # Only used here for running Notebook under mkdocs-jupyter during document generation.\n", "import pykx as kx\n", "import numpy as np\n", - "import pandas as pd" + "import pandas as pd\n", + "kx.q.system.console_size = [10, 80]" ] }, { @@ -1276,11 +1277,11 @@ }, "outputs": [], "source": [ - "print(f'{tab.head()}\\n\\n')\n", - "print('Pop the `v` column out of the table')\n", - "print(f'{tab.pop(\"v\").head()}\\n\\n')\n", - "print('Updated Table')\n", - "print(tab.head())" + "display(tab.head())\n", + "print('\\n\\nPop the `v` column out of the table')\n", + "display(tab.pop(\"v\"))\n", + "print('\\n\\nUpdated Table')\n", + "display(tab.head())" ] }, { @@ -1300,11 +1301,11 @@ }, "outputs": [], "source": [ - "print(f'{tab.head()}\\n\\n')\n", - "print('Pop the `z` and `w` columns out of the table')\n", - "print(f'{tab.pop([\"z\", \"w\"]).head()}\\n\\n')\n", - "print('Updated Table')\n", - "print(tab.head())" + "display(tab.head())\n", + "print('\\n\\nPop the `z` and `w` columns out of the table')\n", + "display(tab.pop([\"z\", \"w\"]).head())\n", + "print('\\n\\nUpdated Table')\n", + "display(tab.head())" ] }, { diff --git a/docs/user-guide/advanced/attributes.md b/docs/user-guide/advanced/attributes.md index 82681c5..ce35522 100644 --- a/docs/user-guide/advanced/attributes.md +++ b/docs/user-guide/advanced/attributes.md @@ -141,7 +141,7 @@ order. When attributes are set on PyKX objects various functions can use these attributes to speed up their execution, by using different algorithms. For example searching through a list without an attribute -requires checking every single value, howevver setting the sorted attribute allows a search algorithm +requires checking every single value, however setting the sorted attribute allows a search algorithm to use a binary search in stead and then only a fraction of the values actually need to be checked. Examples of some functions that can use attributes to speed up execution. diff --git a/docs/user-guide/advanced/context_interface.md b/docs/user-guide/advanced/context_interface.md index d827cde..347a8d9 100644 --- a/docs/user-guide/advanced/context_interface.md +++ b/docs/user-guide/advanced/context_interface.md @@ -51,7 +51,7 @@ switching contexts. Note that context switches persists across `pykx.q` calls (but not `pykx.QConnection(...)` calls). One should take care when switching contexts, as unexpectedly being in an different context can -result in undesirable behaviour. `QContext` objects are Python context managers, which means they +result in undesirable behavior. `QContext` objects are Python context managers, which means they can be used with the `with` statement like so: ```python diff --git a/docs/user-guide/advanced/modes.md b/docs/user-guide/advanced/modes.md index 4d9e993..13210b4 100644 --- a/docs/user-guide/advanced/modes.md +++ b/docs/user-guide/advanced/modes.md @@ -9,7 +9,7 @@ PyKX exists to supersede all previous interfaces between q and Python, this docu ## PyKX within a Python session -PyKX operating within a Python session is intended to offer a replacement for [qPython](https://github.com/exxeleron/qPython) and [PyQ](https://github.com/kxsystems/pyq). In order to facilitate replacement of qPython PyKX provides a mode of operation for IPC based communication which allows for the creation of IPC connections and the conversion of data from Pythonic representations to kx objects, this IPC only modality is refered to as `"Unlicensed mode"` within the documentation. The following outline the differences between `"Licensed"` and `"Unlicensed"` operation. +PyKX operating within a Python session is intended to offer a replacement for [qPython](https://github.com/exxeleron/qPython) and [PyQ](https://github.com/kxsystems/pyq). In order to facilitate replacement of qPython PyKX provides a mode of operation for IPC based communication which allows for the creation of IPC connections and the conversion of data from Pythonic representations to kx objects, this IPC only modality is referred to as `"Unlicensed mode"` within the documentation. The following outline the differences between `"Licensed"` and `"Unlicensed"` operation. The following table outlines some of the key differences between the two operating modes @@ -127,9 +127,9 @@ The following are the differences provided through operation with a valid KX Lic 4. kx.q.schema 5. kx.q.console 6. [Pandas API](Pandas_API.ipynb) functionality for interactions with and PyKX Table objects -6. Keyed tables can be converted to equivalent numpy types -7. All types can be disambiguited, generic null can be discerned from a projection null, and similar for regular vs splayed tables. -8. Numpy list object conversion when operating with a valid PyKX license are optimised relative to unlicensed mode. +6. Keyed tables can be converted to equivalent Numpy types +7. All types can be disambiguated, generic null can be discerned from a projection null, and similar for regular vs splayed tables. +8. Numpy list object conversion when operating with a valid PyKX license are optimized relative to unlicensed mode. 9. The `is_null`, `is_inf`, `has_nulls`, and `has_infs` methods of `K` objects are only supported when using a license. ### Choosing to run with/without a license @@ -139,7 +139,7 @@ Users can choose to initialise PyKX under one of these modalities explicitly thr | Modality argument| Description| |------------------|----------| -| `--unlicensed` | Starts PyKX in unlicensed mode. No license check will be performed, and no warning will be emitted at startup if embedded q initialization fails. | +| `--unlicensed` | Starts PyKX in unlicensed mode. No license check will be performed, and no warning will be emitted at start-up if embedded q initialization fails. | | `--licensed` | Raise a `PyKXException` (as opposed to emitting a `PyKXWarning`) if embedded q initialization fails. diff --git a/docs/user-guide/advanced/performance.md b/docs/user-guide/advanced/performance.md index bfb3339..535bedb 100644 --- a/docs/user-guide/advanced/performance.md +++ b/docs/user-guide/advanced/performance.md @@ -35,11 +35,11 @@ PyKX exposes this maximum value as `pykx.q.system.max_num_threads`, which cannot ### Multi-threading By default PyKX does not currently support calling into q from multiple threads within a Python process simultaneously. -The [GIL](https://wiki.python.org/moin/GlobalInterpreterLock) generally prevents this from occuring. +The [GIL](https://wiki.python.org/moin/GlobalInterpreterLock) generally prevents this from occurring. However enabling the `PYKX_RELEASE_GIL` environment variable will cause the Python Global Interpreter Lock to be dropped when calling into `q`. Caution must be used when calling into q from multiple threads if this environment variable is set as it will no longer be thread safe, you can optionally also -enable the `PYKX_Q_LOCK` environment variable as well which will add an extra reentrant lock around embedded q to ensure two threads cannot access `q`'s memory in an unsafe manner. +enable the `PYKX_Q_LOCK` environment variable as well which will add an extra re-entrant lock around embedded q to ensure two threads cannot access `q`'s memory in an unsafe manner. ## Peach diff --git a/docs/user-guide/configuration.md b/docs/user-guide/configuration.md index 0dffe99..06ac6a4 100644 --- a/docs/user-guide/configuration.md +++ b/docs/user-guide/configuration.md @@ -1,12 +1,12 @@ -# PyKX Configurable Behaviour +# PyKX Configurable Behavior -The following document outlines how users can modify the underlying behaviour of PyKX based on their specific use-case. The [options](#options) presented are provided for use-case/performance tuned optimisations of the library itself. +The following document outlines how users can modify the underlying behavior of PyKX based on their specific use-case. The [options](#options) presented are provided for use-case/performance tuned optimisations of the library itself. Setting of these configuration options is supported via a [configuration file](#configuration-file) or [environment variables](#environment-variables) as described below. In all cases environment variable definitions will take precedence over definitions within the configuration file. ## Configuration File -Users can use a configuration file `.pykx-config` to define configuration options for PyKX initialisation. The following provides an example of a `.pykx-config` file which operates according to `*.toml` syntax: +Users can use a configuration file `.pykx-config` to define configuration options for PyKX initialization. The following provides an example of a `.pykx-config` file which operates according to `*.toml` syntax: ```bash [default] @@ -70,18 +70,18 @@ The following variables can be used to enable or disable advanced features of Py | Option | Default | Values | Description | Status | |---------------------------------|---------|-----------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------| | `PYKX_IGNORE_QHOME` | `False` | `1` or `true` | When loading PyKX on a machine with an existing q installation (and the environment variable `QHOME` set to the installation folder), PyKX will look within this directory for q scripts their dependencies. It will then symlink these files to make them available to load under PyKX. This variable instructs PyKX to not perform this symlinking. | | -| `PYKX_KEEP_LOCAL_TIMES` | `False` | `1` or `true` | When converting a Python datetime object to q, PyKX will translate the Python datetime into UTC before the conversion. This variable instructs PyKX to convert the Python datetime using the local timezone. | | +| `PYKX_KEEP_LOCAL_TIMES` | `False` | `1` or `true` | When converting a Python datetime object to q, PyKX will translate the Python datetime into UTC before the conversion. This variable instructs PyKX to convert the Python datetime using the local time zone. | | | `PYKX_ALLOCATOR` | `False` | `1` or `true` | When converting a Numpy array to q, PyKX implements a full data copy in order to translate the Numpy array to q representation in memory. When this is set PyKX implements [NEP-49](https://numpy.org/neps/nep-0049.html) which allows q to handle memory allocation of all Numpy arrays so they can be converted more efficiently to q. This avoids the need to resort to a copy where possible. | | -| `PYKX_GC` | `False` | `1` or `true` | When PYKX_ALLOCATOR is enabled, PyKX can trigger q garbage collector when Numpy arrays allocated by PyKX are deallocated. This variable enables this behavior which will release q memory to the OS following deallocation of the numpy array at the cost of a small overhead. | | +| `PYKX_GC` | `False` | `1` or `true` | When PYKX_ALLOCATOR is enabled, PyKX can trigger q garbage collector when Numpy arrays allocated by PyKX are deallocated. This variable enables this behavior which will release q memory to the OS following deallocation of the Numpy array at the cost of a small overhead. | | | `PYKX_LOAD_PYARROW_UNSAFE` | `False` | `1` or `true` | By default, PyKX uses a subprocess to import pyarrow as it can result in a crash when the version of pyarrow is incompatible. This variable will trigger a normal import of pyarrow and importing PyKX should be slightly faster. | | | `PYKX_MAX_ERROR_LENGTH` | `256` | size in characters | By default, PyKX reports IPC connection errors with a message buffer of size 256 characters. This allows the length of these error messages to be modified reducing the chance of excessive error messages polluting logs. | | | `PYKX_NOQCE` | `False` | `1` or `true` | On Linux, PyKX comes with q Cloud Edition features from Insights Core (https://code.kx.com/insights/1.2/core/). This variable allows a user to skip the loading of q Cloud Edition functionality, saving some time when importing PyKX but removing access to possibly supported additional functionality. | | | `PYKX_Q_LIB_LOCATION` | `UNSET` | Path to a directory containing q libraries necessary for loading PyKX | See [here](../release-notes/changelog.md#pykx-131) for detailed information. This allows a user to centralise the q libraries, `q.k`, `read.q`, `libq.so` etc to a managed location within their environment which is decentralised from the Python installation. This is required for some enterprise use-cases. | | | `PYKX_RELEASE_GIL` | `False` | `1` or `true` | When PYKX_RELEASE_GIL is enabled the Python Global Interpreter Lock will not be held when calling into q. | | -| `PYKX_Q_LOCK` | `False` | `1` or `true` | When PYKX_Q_LOCK is enabled a reentrant lock is added around calls into q, this lock will stop multiple threads from calling into q at the same time. This allows embedded q to be threadsafe even when using PYKX_RELEASE_GIL. | | +| `PYKX_Q_LOCK` | `False` | `1` or `true` | When PYKX_Q_LOCK is enabled a re-entrant lock is added around calls into q, this lock will stop multiple threads from calling into q at the same time. This allows embedded q to be thread safe even when using PYKX_RELEASE_GIL. | | | `PYKX_DEBUG_INSIGHTS_LIBRARIES` | `False` | `1` or `true` | If the insights libraries failed to load this variable can be used to print out the full error output for debugging purposes. | | | `IGNORE_QHOME` | `True` | `1` or `true` | When loading PyKX on a machine with an existing q installation (and the environment variable `QHOME` set to the installation folder), PyKX will look within this directory for q scripts their dependencies. It will then symlink these files to make them available to load under PyKX. This variable instructs PyKX to not perform this symlinking. | `DEPRECATED`, please use `PYKX_IGNORE_QHOME` | -| `KEEP_LOCAL_TIMES` | `False` | `1` or `true` | When converting a Python datetime object to q, PyKX will translate the Python datetime into UTC before the conversion. This variable instructs PyKX to convert the Python datetime using the local timezone. | `DEPRECATED`, please use `PYKX_KEEP_LOCAL_TIMES` | +| `KEEP_LOCAL_TIMES` | `False` | `1` or `true` | When converting a Python datetime object to q, PyKX will translate the Python datetime into UTC before the conversion. This variable instructs PyKX to convert the Python datetime using the local time zone. | `DEPRECATED`, please use `PYKX_KEEP_LOCAL_TIMES` | The variables below can be used to set the environment for q (embedded in PyKX, in licensed mode): diff --git a/docs/user-guide/fundamentals/creating.md b/docs/user-guide/fundamentals/creating.md index d64debd..88239d2 100644 --- a/docs/user-guide/fundamentals/creating.md +++ b/docs/user-guide/fundamentals/creating.md @@ -15,7 +15,11 @@ Getting the data to a PyKX format provides you with the ability to easily intera ### Explicitly converting from Pythonic objects to PyKX objects -The most simplistic method of creating a PyKX object is to convert an analagous Pythonic type to a PyKX object. This is facilitated through the use of the functions `pykx.toq` which allows conversions from Python, Numpy, Pandas and PyArrow types to PyKX objects, open the tabs which are of interest to you to see some examples of these conversions +The most simplistic method of creating a PyKX object is to convert an analogous Pythonic type to a PyKX object. This is facilitated through the use of the functions `pykx.toq` which allows conversions from Python, Numpy, Pandas and PyArrow types to PyKX objects, open the tabs which are of interest to you to see some examples of these conversions + +??? Note "Specifying target types" + + When converting Pythonic objects to PyKX types users can make use of the `ktype` named argument. Users converting lists/atomic elements should use [PyKX types](../../api/pykx-q-data/type_conversions.md), if converting Pandas DataFrames or PyArrow Tables users can make use of the `ktype` argument with a dictionary input mapping the column name to the [PyKX type](../../api/pykx-q-data/type_conversions.md). === "Python" @@ -28,11 +32,9 @@ The most simplistic method of creating a PyKX object is to convert an analagous >>> kx.toq(pyatom) pykx.LongAtom(pykx.q('2')) >>> kx.toq(pylist) - pykx.List(pykx.q(' - 1 - 2 - 3 - ')) + pykx.LongVector(pykx.q('1 2 3')) + >>> kx.toq(pylist, kx.FloatVector) + pykx.FloatVector(pykx.q('1 2 3f')) >>> kx.toq(pydict) pykx.Dictionary(pykx.q(' x| (1;2;3) @@ -51,6 +53,8 @@ The most simplistic method of creating a PyKX object is to convert an analagous >>> >>> kx.toq(nparray1) pykx.LongVector(pykx.q('1 2 3')) + >>> kx.toq(nparray1, kx.FloatVector) + pykx.FloatVector(pykx.q('1 2 3f')) >>> kx.toq(nparray2) pykx.DateVector(pykx.q('2007.07.13 2006.01.13 2010.08.13')) >>> kx.toq(nparray3) @@ -71,6 +75,8 @@ The most simplistic method of creating a PyKX object is to convert an analagous >>> df = pd.DataFrame.from_dict({'x': [1, 2], 'y': ['a', 'b']}) >>> kx.toq(pdseries1) pykx.LongVector(pykx.q('1 2 3')) + >>> kx.toq(pdseries1, kx.FloatVector) + pykx.FloatVector(pykx.q('1 2 3f')) >>> kx.toq(pdseries2) pykx.IntVector(pykx.q('1 2 3i')) >>> kx.toq(df) @@ -80,6 +86,20 @@ The most simplistic method of creating a PyKX object is to convert an analagous 1 a 2 b ')) + >>> kx.toq(df).dtypes + pykx.Table(pykx.q(' + columns type + ----------------------- + x "kx.LongAtom" + y "kx.SymbolAtom" + ')) + >>> kx.toq(df, ktype={'x': kx.FloatVector}).dtypes + pykx.Table(pykx.q(' + columns type + ----------------------- + x "kx.FloatAtom" + y "kx.SymbolAtom" + ')) ``` === "PyArrow" @@ -120,6 +140,20 @@ The most simplistic method of creating a PyKX object is to convert an analagous 5 Brittle stars 100 Centipede ')) + >>> kx.toq(tab).dtypes + pykx.Table(pykx.q(' + columns type + ----------------------- + n_legs "kx.LongAtom" + animals "kx.SymbolAtom" + ')) + >>> kx.toq(tab, {'animals': kx.CharVector}).dtypes + pykx.Table(pykx.q(' + columns type + ----------------------- + n_legs "kx.LongAtom" + animals "kx.CharVector" + ')) ``` ### Generating data using PyKX inbuilt functions diff --git a/docs/user-guide/fundamentals/indexing.md b/docs/user-guide/fundamentals/indexing.md index 4f4b595..59abe02 100644 --- a/docs/user-guide/fundamentals/indexing.md +++ b/docs/user-guide/fundamentals/indexing.md @@ -2,7 +2,7 @@ ## An introduction to indexing within PyKX -Indexing in q works differently than you may be used to, and that behaviour largely carries over into PyKX for indexing K objects. For more information about how indexing in q works (and by extension, how indexing K objects in PyKX work), refer to the following sections of the q tutorial book [Q For Mortals](https://code.kx.com/q4m3/): +Indexing in q works differently than you may be used to, and that behavior largely carries over into PyKX for indexing K objects. For more information about how indexing in q works (and by extension, how indexing K objects in PyKX work), refer to the following sections of the q tutorial book [Q For Mortals](https://code.kx.com/q4m3/): - [Indexing](https://code.kx.com/q4m3/3_Lists/#34-indexing) - [Iterated Indexing and Indexing at Depth](https://code.kx.com/q4m3/3_Lists/#38-iterated-indexing-and-indexing-at-depth) diff --git a/docs/user-guide/fundamentals/nulls_and_infinities.md b/docs/user-guide/fundamentals/nulls_and_infinities.md index 3b63eb2..7f2e291 100644 --- a/docs/user-guide/fundamentals/nulls_and_infinities.md +++ b/docs/user-guide/fundamentals/nulls_and_infinities.md @@ -65,7 +65,7 @@ Temporal vectors use `NaT` to represent null values in Numpy and Pandas, `None` When converting a table from q to Python with one of the methods above, each column will be transformed as an independent vector as described above. -The following provides an example of the masked array behaviour outlined in the `.np` method described above which is additionally exhibited by the `.pd` method. +The following provides an example of the masked array behavior outlined in the `.np` method described above which is additionally exhibited by the `.pd` method. ```python >>> import pykx as kx @@ -99,7 +99,7 @@ x x1 ')) ``` -For more information on masked numpy arrays and interactions with null representation data in Pandas see the following links +For more information on masked Numpy arrays and interactions with null representation data in Pandas see the following links - [Numpy masked arrays](https://numpy.org/doc/stable/reference/maskedarray.generic.html#filling-in-the-missing-data) - [Pandas working with missing data](https://pandas.pydata.org/docs/user_guide/missing_data.html) diff --git a/docs/user-guide/fundamentals/text.md b/docs/user-guide/fundamentals/text.md new file mode 100644 index 0000000..070e716 --- /dev/null +++ b/docs/user-guide/fundamentals/text.md @@ -0,0 +1,113 @@ +# Text representation in PyKX + +Within PyKX text can be represented in a number of ways that you will encounter when using the library. The following are the basic building blocks for text within PyKX, a deeper dive into the underlying text representation can be found [here](https://code.kx.com/q4m3/2_Basic_Data_Types_Atoms/#24-text-data): + +| Type | Description | Example Generation | +|---------------------|--------------------------------------------------------------------------------------------------|------------------------------| +| `pykx.SymbolAtom` | A symbol atom in PyKX is an irreducible atomic entity storing an arbitrary number of characters. | ```pykx.q('`test')``` | +| `pykx.SymbolVector` | A symbol vector is a collected list of symbol atoms. | ```pykx.q('`test`vector')``` | +| `pykx.CharAtom` | A char atom holds a single ASCII or 8-but unicode character stored as 1 byte. | `pykx.q('"a"')` | +| `pykx.CharVector` | A char vector is a collected list of char vectors | `pykx.q('"test"')` | + +## Converting text to/from PyKX + +Pythonic text data can be converted to PyKX objects directly through use of the `pykx.SymbolAtom` and `pykx.CharVector` functions as shown below + +```python +>>> import pykx as kx +>>> pystring = 'test string' +>>> kx.SymbolAtom(pystring) +pykx.SymbolAtom(pykx.q('`test string')) +>>> kx.CharVector(pystring) +pykx.CharVector(pykx.q('"test string"')) +``` + +Alternatively you can make use of the automatic conversion function `pykx.toq` which will take an incoming Python type and convert it to its analagous PyKX type. The following table shows the mapping which is used + +| Python Type | PyKX Type | +|-------------|-----------------------------------| +| `str` | `pykx.SymbolAtom` | +| `byte` | `pykx.CharAtom`/`pykx.CharVector` | + +```python +>>> import pykx as kx +>>> kx.toq('string') +pykx.SymbolAtom(pykx.q('`string')) +>>> kx.toq(b'bytes') +pykx.CharVector(pykx.q('"bytes"')) +>>> kx.toq(b'a') +pykx.CharAtom(pykx.q('"a"')) +``` + +When using the `pykx.toq` function it is possible to specify the target type for your data as shown below, this can be useful when selectively converting data + +```python +>>> import pykx as kx +>>> kx.toq('string', kx.CharVector) +pykx.CharVector(pykx.q('"string"')) +>>> kx.toq(b'bytes', kx.SymbolAtom) +pykx.SymbolAtom(pykx.q('`bytes')) +``` + +An important note on the above when using PyKX functions is that the `pykx.toq` conversion will be used by default when passing Python data to these functions, for example: + +```python +>>> import pykx as kx +>>> kx.q('{(x;y)}', 'string', b'bytes') +pykx.List(pykx.q(' +`string +"bytes" +')) +``` + +## Differences between `Symbol` and `Char` data objects + +While there may appear to be limited differences between `Symbol` and `Char` representations of objects, the choice of underlying representation can have an impact on the performance and memory profile of many applications of PyKX. This section will describe a number of these differences and their impact in various scenarios. + +### Text access and mutability + +The individual characters which comprise a `pykx.SymbolAtom` object are not directly accessible by a user, this limitation does not exist for `pykx.CharVector` objects. For example it is possible to retrieve slices of a `pykx.CharVector` + +```python +>>> import pykx as kx +>>> charVector = kx.CharVector('test') +>>> charVector +pykx.CharVector(pykx.q('"test"')) +>>> charVector[1:] +pykx.CharVector(pykx.q('"est"')) +>>> symbolAtom = kx.SymbolAtom('test') +>>> symbolAtom +pykx.SymbolAtom(pykx.q('`test')) +>>> symbolAtom[1:] +Traceback (most recent call last): + File "", line 1, in +TypeError: 'SymbolAtom' object is not subscriptable +``` + +Similarly `pykx.CharVector` type objects are mutable while `pykx.SymbolAtom` type objects are not + +```python +>>> import pykx as kx +>>> charVector = kx.CharVector('test') +>>> kx.q('{x[0]:"r";x}', charVector) +pykx.CharVector(pykx.q('"rest"')) +``` + +### Memory considerations + +An important point of note when dealing with Symbol type objects is that these are never deallocated once generated, this can be seen through growth of the `syms` key of `kx.q.Q.w` as follows + +```python +>>> kx.q.Q.w()['syms'] +pykx.LongAtom(pykx.q('2790')) +>>> kx.SymbolAtom('test') +pykx.SymbolAtom(pykx.q('`test')) +>>> kx.q.Q.w()['syms'] +pykx.LongAtom(pykx.q('2791')) +>>> kx.SymbolAtom('testing') +pykx.SymbolAtom(pykx.q('`testing')) +>>> kx.q.Q.w()['syms'] +pykx.LongAtom(pykx.q('2792')) +``` + +This is important as overuse of symbols can result in increased memory requirements for your processes. Symbols as such are best used when dealing with highly repetitive text data. diff --git a/docs/user-guide/index.md b/docs/user-guide/index.md index 3d4500c..df8eb04 100644 --- a/docs/user-guide/index.md +++ b/docs/user-guide/index.md @@ -26,7 +26,7 @@ The following outlines the various topics covered within the above sections: |----------------------------------------------------------------------|-------------| | [Communicating via IPC](advanced/ipc.md) | How can you interact synchronously and asynchronously with a kdb+/q server. | | [Using q functions in a Pythonic way](advanced/context_interface.md) | Evaluating and injecting q code within a Python session using a Pythonic context interface which exposes q objects as first class Python objects. | -| [Numpy integration](advanced/numpy.md) | Description of the various low-level integrations between PyKX and numpy. Principally describing NEP-49 optimisations and the evaluation of numpy functions using PyKX vectors directly. | +| [Numpy integration](advanced/numpy.md) | Description of the various low-level integrations between PyKX and Numpy. Principally describing NEP-49 optimisations and the evaluation of Numpy functions using PyKX vectors directly. | | [Modes of operation](advanced/modes.md) | A brief description of the modes of operation of PyKX outlining it's usage in the presence and absence of a license and the limitations that this imposes. | [Performance considerations](advanced/performance.md) | Guidance on how to treat management and interactions with PyKX objects to achieve the best performance possible. | | [Library limitations](advanced/limitations.md) | For users familiar with q/kdb+ and previous Python interfaces what limitations does PyKX impose. | diff --git a/examples/notebooks/interface_overview.ipynb b/examples/notebooks/interface_overview.ipynb index fa762d3..493e0ad 100644 --- a/examples/notebooks/interface_overview.ipynb +++ b/examples/notebooks/interface_overview.ipynb @@ -71,7 +71,8 @@ "warnings.filterwarnings('ignore') # Do not copy, as we are skipping symlinking pyKX to QHOME the core insights libraries will not be copied over and will raise warnings\n", "os.environ['IGNORE_QHOME'] = '1' # Ignore symlinking PyKX q libraries to QHOME \n", "os.environ['PYKX_Q_LOADED_MARKER'] = '' # Only used here for running Notebook under mkdocs-jupyter during document generation.\n", - "import pykx as kx" + "import pykx as kx\n", + "kx.q.system.console_size = [10, 80]" ] }, { @@ -197,8 +198,8 @@ " 'col3': ['Hello', 'World']})\n", "patable = pa.Table.from_pandas(pdtable)\n", "\n", - "print(kx.K(pdtable))\n", - "# print(kx.K(patable))" + "display(kx.K(pdtable))\n", + "# display(kx.K(patable))" ] }, { @@ -339,7 +340,7 @@ "### Table conversions\n", "Conversions between q keyed and unkeyed tables to an appropriate Python representation are supported for the `py()`, `np()`, `pd()` and `pa()` methods.\n", "\n", - "Round trip conversions `q -> Python -> q` are however only supported for Pandas and PyArrow. Conversions from numpy records are still to be completed and the most natural representation for a table in native python is a dictionary as such the conversion from python to q returns a q dictionary rather than a table\n", + "Round trip conversions `q -> Python -> q` are however only supported for Pandas and PyArrow. Conversions from Numpy records are still to be completed and the most natural representation for a table in native python is a dictionary as such the conversion from python to q returns a q dictionary rather than a table\n", "\n", "Define a q table containing all q data types for conversion" ] @@ -371,8 +372,8 @@ "metadata": {}, "outputs": [], "source": [ - "print(qtab.pd())\n", - "print(qtab.pa())" + "display(qtab.pd())\n", + "display(qtab.pa())" ] }, { @@ -826,7 +827,7 @@ "kx.q('`:db/2020.03/t/ set ([] a:2+til 3; b:\"bat\"; c:-3?0Ng)')\n", "kx.q(r'\\l db')\n", "t_partitioned = kx.q('t')\n", - "print(t_partitioned)" + "t_partitioned" ] }, { @@ -1072,7 +1073,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(kx.q.uj(s,t))" + "kx.q.uj(s,t)" ] }, { @@ -1194,7 +1195,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(kx.q.demo_extension.test_data)" + "kx.q.demo_extension.test_data" ] }, { @@ -1212,7 +1213,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(kx.q.demo_extension.test_function(kx.q.demo_extension.test_data))" + "kx.q.demo_extension.test_function(kx.q.demo_extension.test_data)" ] }, { @@ -1293,7 +1294,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(kx.q.qsql.select(qtab))" + "kx.q.qsql.select(qtab)" ] }, { @@ -1309,7 +1310,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(kx.q.qsql.select(qtab))" + "kx.q.qsql.select(qtab)" ] }, { @@ -1327,7 +1328,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(kx.q.qsql.select('qtab'))" + "kx.q.qsql.select('qtab')" ] }, { @@ -1347,8 +1348,8 @@ "metadata": {}, "outputs": [], "source": [ - "# print(kx.q.qsql.select(qtab, where='col1=`a'))\n", - "print(kx.q.qsql.select(qtab, where=['col3<0.5', 'col2>0.7']))" + "# kx.q.qsql.select(qtab, where='col1=`a')\n", + "kx.q.qsql.select(qtab, where=['col3<0.5', 'col2>0.7'])" ] }, { @@ -1427,8 +1428,8 @@ "metadata": {}, "outputs": [], "source": [ - "print(kx.q.qsql.delete(qtab))\n", - "print(kx.q.qsql.delete('qtab'))" + "kx.q.qsql.delete(qtab)\n", + "kx.q.qsql.delete('qtab')" ] }, { @@ -1452,8 +1453,8 @@ "metadata": {}, "outputs": [], "source": [ - "# print(kx.q.qsql.delete(qtab, columns = 'col3'))\n", - "print(kx.q.qsql.delete(qtab, columns = ['col1','col2']))" + "# kx.q.qsql.delete(qtab, columns = 'col3')\n", + "kx.q.qsql.delete(qtab, columns = ['col1','col2'])" ] }, { @@ -1477,7 +1478,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(kx.q.qsql.delete(qtab, where='col1 in `a`b'))" + "kx.q.qsql.delete(qtab, where='col1 in `a`b')" ] }, { @@ -1506,7 +1507,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(kx.q('qtab'))" + "kx.q('qtab')" ] }, { @@ -1535,10 +1536,10 @@ "metadata": {}, "outputs": [], "source": [ - "# print(kx.q.qsql.update({'avg_col2':'avg col2'}, by={'col1': 'col1'}))\n", - "# print(kx.q.qsql.update({'col3':100}, where='col1=`a'))\n", + "# kx.q.qsql.update({'avg_col2':'avg col2'}, by={'col1': 'col1'})\n", + "# kx.q.qsql.update({'col3':100}, where='col1=`a')\n", "kx.q.qsql.update('qtab', {'col2': 4.2}, 'col1=`b', modify=True)\n", - "print(kx.q['qtab'])" + "kx.q['qtab']" ] }, { diff --git a/mkdocs.yml b/mkdocs.yml index c60fc51..bc0afa1 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -139,6 +139,10 @@ theme: - content.tabs.link # Insiders - header.autohide - navigation.tabs + - navigation.tabs.sticky + - navigation.path + - navigation.top + - navigation.tracking - content.code.annotate - content.action.edit - search.suggest @@ -181,6 +185,7 @@ nav: - Interacting with PyKX objects: user-guide/fundamentals/evaluating.md - Querying data: user-guide/fundamentals/querying.md - Indexing PyKX objects: user-guide/fundamentals/indexing.md + - Text Representation in PyKX: user-guide/fundamentals/text.md - Handling nulls and infinities: user-guide/fundamentals/nulls_and_infinities.md - Advanced usage and performance considerations: - Communicating via IPC: user-guide/advanced/ipc.md @@ -213,6 +218,7 @@ nav: - Writing PyKX data to disk: api/pykx-save-load/write.md - Reading PyKX data from disk: api/pykx-save-load/read.md - Reimporter module: api/reimporting.md + - Serialization: api/serialize.md - Examples: - Subscriber: examples/subscriber/readme.md - Compression and Encryption: examples/compress_and_encrypt/readme.md diff --git a/pyproject.toml b/pyproject.toml index 11c834a..1329f28 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,8 +50,8 @@ classifiers = [ dependencies = [ "numpy~=1.22; python_version!='3.7'", "numpy~=1.20; python_version=='3.7'", - "pandas~=1.2", - "pytz~=2022.1", + "pandas>=1.2", + "pytz>=2022.1", "toml~=0.10.2", ] @@ -91,7 +91,7 @@ pyarrow = [ ] test = [ "coverage[toml]==6.3.2", - "Cython==3.0.0a11", + "Cython~=3.0.0", "plotly==5.10.0", "pytest==7.1.2", "pytest-asyncio==0.18.3", @@ -114,7 +114,7 @@ changelog = "https://code.kx.com/pykx/changelog.html" [build-system] requires = [ - "Cython==3.0.0a11", + "Cython~=3.0.0", "numpy~=1.22, <1.23; python_version!='3.7'", # Use the highest patch version of numpy 1.22.x, this will still support a user using numpy version 1.22.0 "numpy~=1.20.0; python_version=='3.7'", # Use numpy version 1.20.x for building the python 3.7 wheel "setuptools==60.9.3", @@ -169,6 +169,7 @@ exclude = [ "docs/internal", "vcpkg", "tests/win_tests/*", + "_version.py", ] show-source = "True" max-complexity = 10 diff --git a/src/pykx/__init__.py b/src/pykx/__init__.py index 4b4c7d8..6445cd9 100644 --- a/src/pykx/__init__.py +++ b/src/pykx/__init__.py @@ -136,7 +136,7 @@ def __getattr__(self, key): raise attribute_error from inner_error # __setattr__ takes precedence over data descriptors, so we implement a custom one that uses - # the default behaviour for select keys + # the default behavior for select keys def __setattr__(self, key, value): if key in self.__dict__ or key in Q.__dict__: object.__setattr__(self, key, value) @@ -247,6 +247,7 @@ def paths(self, paths: List[Union[str, Path]]): # Import order matters here, so the imports are not ordered conventionally. +from .serialize import deserialize, serialize from .console import QConsole from .ctx import default_paths, QContext from .query import Insert, QSQL, SQL, Upsert @@ -287,6 +288,7 @@ def paths(self, paths: List[Union[str, Path]]): from .license import _init as _license_init _license_init(q) + from .random import _init as _random_init _random_init(q) @@ -318,13 +320,15 @@ def install_into_QHOME(overwrite_embedpy=False, to_local_folder=False) -> None: Returns: None """ - dest = Path(".") if to_local_folder else qhome + dest = Path('.') if to_local_folder else qhome p = Path(dest)/'p.k' if not p.exists() or overwrite_embedpy: shutil.copy(Path(__file__).parent/'p.k', p) shutil.copy(Path(__file__).parent/'pykx.q', dest/'p.q' if overwrite_embedpy else dest) shutil.copy(Path(__file__).parent/'pykx_init.q_', dest) if platform.system() == 'Windows': + if dest == qhome: + dest = dest/'w64' shutil.copy(Path(__file__).parent/'lib/w64/q.dll', dest) @@ -408,6 +412,7 @@ def deactivate_numpy_allocator(): 'AsyncQConnection', 'EmbeddedQ', 'EmbeddedQFuture', + 'PyKXSerialized', 'Q', 'qargs', 'QConnection', diff --git a/src/pykx/_ipc.pxd b/src/pykx/_ipc.pxd index b7f8964..99c217a 100644 --- a/src/pykx/_ipc.pxd +++ b/src/pykx/_ipc.pxd @@ -6,9 +6,5 @@ from pykx cimport core cdef extern from 'k.h': - cdef core.I khpunc(core.S hostname, - core.I port, - core.S credentials, - core.I timeout, - core.I capability) - cdef core.V kclose(core.I x) + cdef int khpunc(char* hostname, int port, char* credentials, int timeout, int capability) + cdef void kclose(int x) diff --git a/src/pykx/_ipc.pyx b/src/pykx/_ipc.pyx index 292d4a1..eb66ef9 100644 --- a/src/pykx/_ipc.pyx +++ b/src/pykx/_ipc.pyx @@ -31,7 +31,9 @@ def init_handle(host, port, credentials, unix, tls, timeout, large_messages): ':', credentials ) - return int(q.hopen((q.hsym(''.join(parts)), int(timeout * 1000)))) + sym = q.hsym(''.join(parts)) + hsym = (sym, int(timeout * 1000)) + return int(q.hopen(hsym)) else: host = b'0.0.0.0' if unix else normalize_to_bytes(host, 'Host') return core.khpunc( diff --git a/src/pykx/_numpy.c b/src/pykx/_numpy.c index 6999949..eaec016 100644 --- a/src/pykx/_numpy.c +++ b/src/pykx/_numpy.c @@ -14,8 +14,8 @@ #define k_from_buf(x) (K)(x - offsetof(struct k0, G0)) static void (*r0_ptr)(K); -static K (*k_ptr)(I, const S, ...); -static K (*ktn_ptr)(I, J); +static K (*k_ptr)(int, const char*, ...); +static K (*ktn_ptr)(int, long long); void* q_lib; @@ -72,7 +72,7 @@ uintptr_t k_realloc(Allocator* ctx, uintptr_t p, npy_uintp sz) { k->t = KG; // Calculate the size of the vector in bytes, and temporarily set k->n to that. - J prev_size; + long long prev_size; assert(t < 20 && 0 <= t); prev_size = k->n * k_type_to_size[t]; k->n = prev_size; diff --git a/src/pykx/_wrappers.pyx b/src/pykx/_wrappers.pyx index 5e39717..6803ed0 100644 --- a/src/pykx/_wrappers.pyx +++ b/src/pykx/_wrappers.pyx @@ -139,31 +139,31 @@ cpdef inline k_t(x): return (x._addr).t -cpdef inline core.I k_r(x): +cpdef inline int k_r(x): return (x._addr).r -cpdef inline core.G k_g(x): +cpdef inline unsigned char k_g(x): return (x._addr).g -cpdef inline core.H k_h(x): +cpdef inline short k_h(x): return (x._addr).h -cpdef inline core.I k_i(x): +cpdef inline int k_i(x): return (x._addr).i -cpdef inline core.J k_j(x): +cpdef inline long long k_j(x): return (x._addr).j -cpdef inline core.E k_e(x): +cpdef inline float k_e(x): return (x._addr).e -cpdef inline core.F k_f(x): +cpdef inline double k_f(x): return (x._addr).f @@ -175,7 +175,7 @@ cpdef inline uintptr_t k_k(x): return (x._addr).k -cpdef inline core.J k_n(x): +cpdef inline long long k_n(x): return (x._addr).n @@ -226,27 +226,27 @@ def pandas_uuid_type_from_arrow(self, array): def list_unlicensed_getitem(self, Py_ssize_t index): - cdef core.J n = (self._addr).n + cdef long long n = (self._addr).n cdef uintptr_t[:] addrs = _k(self).G0 return factory(addrs[index], True) def guid_vector_unlicensed_getitem(self, Py_ssize_t index): - cdef core.J n = (self._addr).n + cdef long long n = (self._addr).n cdef char[:] vector_as_chars = _k(self).G0 item_as_bytes = bytes(vector_as_chars[index*16:(index+1)*16]) return wrappers.GUIDAtom(UUID(bytes=item_as_bytes)) def char_vector_unlicensed_getitem(self, Py_ssize_t index): - cdef core.J n = (self._addr).n + cdef long long n = (self._addr).n cdef uint8_t[:] x = _k(self).G0 cdef core.K kx = core.kc(ord(x[index])) return factory(kx, False) def symbol_vector_unlicensed_getitem(self, Py_ssize_t index): - cdef core.J n = (self._addr).n + cdef long long n = (self._addr).n cdef uintptr_t[:] addrs = _k(self).G0 return wrappers.SymbolAtom(str(addrs[index], 'utf-8')) @@ -311,8 +311,8 @@ def guid_atom_py(self, bint raw, bint has_nulls, bint stdlib): def list_np(self, bint raw, bint has_nulls): cdef uintptr_t[:] addrs, razed_addrs cdef Py_ssize_t i - cdef core.J n = (self._addr).n - cdef core.J n0 = 1 + cdef long long n = (self._addr).n + cdef long long n0 = 1 if raw: # Should use `np.NPY_UINTP`, but that isn't defined for whatever reason. It's just a # typedef for `np.NPY_UINT`, so we'll use that instead. @@ -445,6 +445,10 @@ cpdef decref_numpy_allocated_data(x): get_numpy_array(x) +cpdef decref(x): + core.r0(x) + + cdef bint is_pnull(core.K val): cdef core.K x x = core.k(0, '104h ~ type {1b}@', core.r1(val), NULL) diff --git a/src/pykx/config.py b/src/pykx/config.py index b1706d0..ce6e96d 100644 --- a/src/pykx/config.py +++ b/src/pykx/config.py @@ -10,6 +10,7 @@ import webbrowser import toml +import pandas as pd from .exceptions import PyKXWarning @@ -118,7 +119,7 @@ def _is_set(envvar): elif not license_located: modes_url = "https://code.kx.com/pykx/user-guide/advanced/modes.html" lic_url = "https://kx.com/kdb-insights-personal-edition-license-download" - unlicensed_message = '\nPyKX unlicensed mode enabled. To set this as your default behaviour '\ + unlicensed_message = '\nPyKX unlicensed mode enabled. To set this as your default behavior '\ "please set the following environment variable 'QARGS=--unlicensed'\n\n"\ 'For more information on PyKX modes of operation, please visit '\ f'{modes_url}.\nTo apply for a PyKX license please visit {lic_url}' @@ -215,6 +216,9 @@ def _is_set(envvar): no_qce = _is_enabled('PYKX_NOQCE', '--no-qce') load_pyarrow_unsafe = _is_enabled('PYKX_LOAD_PYARROW_UNSAFE', '--load-pyarrow-unsafe') +pandas_2 = pd.__version__.split('.')[0] == '2' +disable_pandas_warning = _is_enabled('PYKX_DISABLE_PANDAS_WARNING') + def find_core_lib(name: str) -> Path: suffix = '.dll' if system == 'Windows' else '.so' @@ -266,6 +270,8 @@ def _set_keep_local_times(keep_local_times_): 'load_pyarrow_unsafe', 'find_core_lib', + + 'pandas_2', ] diff --git a/src/pykx/core.pxd b/src/pykx/core.pxd index 1d942e1..58b674d 100644 --- a/src/pykx/core.pxd +++ b/src/pykx/core.pxd @@ -21,103 +21,93 @@ cdef extern from 'dlfcn.h': cdef extern from 'k.h': - ctypedef char* S - ctypedef char C - ctypedef unsigned char G - ctypedef short H - ctypedef int I - ctypedef long long J - ctypedef float E - ctypedef double F - ctypedef void V - cdef struct k0: signed char m # internal (?) signed char a # internal (?) signed char t # type - C u # attributes - I r # reference count - G g # char - H h # short - I i # int - J j # long - E e # real - F f # float - S s # symbol + char u # attributes + int r # reference count + unsigned char g # char + short h # short + int i # int + long long j # long + float e # real + double f # float + char* s # symbol k0* k # dictionary representation of a table (and more?) - J n # number of elements in a vector - G G0[1] # vector data (extends past the end of this struct) + long long n # number of elements in a vector + unsigned char G0[1] # vector data (extends past the end of this struct) cdef struct _U: - G g[16] + unsigned char g[16] ctypedef _U U ctypedef k0* K -cdef I (*qinit)(I, C**, C*, C*, C*) +cdef int (*qinit)(int, char**, char*, char*, char*) -cdef G* (*kG)(K x) -cdef G* (*kC)(K x) +cdef unsigned char* (*kG)(K x) +cdef unsigned char* (*kC)(K x) cdef U* (*kU)(K x) -cdef S* (*kS)(K x) -cdef H* (*kH)(K x) -cdef I* (*kI)(K x) -cdef J* (*kJ)(K x) -cdef E* (*kE)(K x) -cdef F* (*kF)(K x) +cdef char** (*kS)(K x) +cdef short* (*kH)(K x) +cdef int* (*kI)(K x) +cdef long long* (*kJ)(K x) +cdef float* (*kE)(K x) +cdef double* (*kF)(K x) cdef K* (*kK)(K x) -cdef K (*b9)(I mode, K x) +cdef K (*b9)(int mode, K x) cdef K (*d9)(K x) -cdef I (*dj)(I date) -cdef K (*dl)(V* f, J n) +cdef int (*dj)(int date) +cdef K (*dl)(void* f, long long n) cdef K (*dot)(K x, K y) nogil cdef K (*ee)(K x) -cdef K (*ja)(K* x, V*) +cdef K (*ja)(K* x, void*) cdef K (*jk)(K* x, K y) -cdef K (*js)(K* x, S s) +cdef K (*js)(K* x, char* s) cdef K (*jv)(K* x, K y) -cdef K (*k)(I handle, const S s, ...) nogil +cdef K (*k)(int handle, const char* s, ...) nogil cdef K (*knogil)(void* x, char* code, void* a1, void* a2, void* a3, void* a4, void* a5, void* a6, void* a7, void* a8) nogil -cdef K (*ka)(I t) -cdef K (*kb)(I x) -cdef K (*kc)(I x) -cdef V (*kclose)(I x) -cdef K (*kd)(I x) -cdef K (*ke)(F x) -cdef K (*kf)(F x) -cdef K (*kg)(I x) -cdef K (*kh)(I x) -cdef I (*khpunc)(S v, I w, S x, I y, I z) -cdef K (*ki)(I x) -cdef K (*kj)(J x) -cdef K (*knk)(I n, ...) -cdef K (*knt)(J n, K x) -cdef K (*kp)(S x) -cdef K (*kpn)(S x, J n) -cdef K (*krr)(const S s) -cdef K (*ks)(S x) -cdef K (*kt)(I x) +cdef K (*ka)(int t) +cdef K (*kb)(int x) +cdef K (*kc)(int x) +cdef void (*kclose)(int x) +cdef K (*kd)(int x) +cdef K (*ke)(double x) +cdef K (*kf)(double x) +cdef K (*kg)(int x) +cdef K (*kh)(int x) +cdef int (*khpunc)(char* v, int w, char* x, int y, int z) +cdef K (*ki)(int x) +cdef K (*kj)(long long x) +cdef K (*knk)(int n, ...) +cdef K (*knt)(long long n, K x) +cdef K (*kp)(char* x) +cdef K (*kpn)(char* x, long long n) +cdef K (*krr)(const char* s) +cdef K (*ks)(char* x) +cdef K (*kt)(int x) cdef K (*ktd)(K x) -cdef K (*ktj)(H _type, J x) -cdef K (*ktn)(I _type, J length) +cdef K (*ktj)(short _type, long long x) +cdef K (*ktn)(int _type, long long length) cdef K (*ku)(U x) -cdef K (*kz)(F x) -cdef V (*m9)() -cdef I (*okx)(K x) -cdef K (*orr)(const S) -cdef V (*r0)(K k) +cdef K (*kz)(double x) +cdef void (*m9)() +cdef int (*okx)(K x) +cdef K (*orr)(const char*) +cdef void (*r0)(K k) cdef K (*r1)(K k) -cdef V (*sd0)(I d) -cdef V (*sd0x)(I d, I f) -cdef K (*sd1)(I d, f) -cdef K (*sd1)(I d, f) -cdef S (*sn)(S s, J n) -cdef S (*ss)(S s) +cdef void (*sd0)(int d) +cdef void (*sd0x)(int d, int f) +cdef K (*sd1)(int d, f) +cdef K (*sd1)(int d, f) +cdef char* (*sn)(char* s, long long n) +cdef char* (*ss)(char* s) cdef K (*sslInfo)(K x) -cdef K (*vak)(I x, const S s, va_list l) -cdef K (*vaknk)(I, va_list l) -cdef I (*ver)() +cdef K (*vak)(int x, const char* s, va_list l) +cdef K (*vaknk)(int, va_list l) +cdef int (*ver)() cdef K (*xD)(K x, K y) cdef K (*xT)(K x) -cdef I (*ymd)(I year, I month, I day) +cdef int (*ymd)(int year, int month, int day) diff --git a/src/pykx/core.pyx b/src/pykx/core.pyx index 1ad8cda..0b0d786 100644 --- a/src/pykx/core.pyx +++ b/src/pykx/core.pyx @@ -42,7 +42,7 @@ def _normalize_qargs(user_args: List[str]) -> Tuple[bytes]: ) -cdef I _qinit(I (*qinit)(I, C**, C*, C*, C*), qhome_str: str, qlic_str: str, args: List[str]) except *: +cdef int _qinit(int (*qinit)(int, char**, char*, char*, char*), qhome_str: str, qlic_str: str, args: List[str]) except *: normalized_args = _normalize_qargs(args) cdef int argc = len(normalized_args) cdef char** argv = PyMem_Malloc(sizeof(char*) * argc) @@ -70,11 +70,11 @@ qinit_check_data = os.environ.get('PYKX_QINIT_CHECK') if qinit_check_data is not None: # nocov _core_q_lib_path, _qhome_str, _qlic_str, _qargs = qinit_check_data.split(';') # nocov import shlex # nocov - _qargs = list(shlex.split(_qargs)) # nocov + _qargs = list(shlex.split(_qargs)) # nocov _libq_path_py = _core_q_lib_path.encode() # nocov _libq_path = _libq_path_py # nocov _q_handle = dlopen(_libq_path, RTLD_NOW | RTLD_GLOBAL) # nocov - qinit = dlsym(_q_handle, 'qinit') # nocov + qinit = dlsym(_q_handle, 'qinit') # nocov os._exit(_qinit(qinit, _qhome_str, _qlic_str, _qargs)) # nocov @@ -291,7 +291,7 @@ else: if licensed: # Start in licensed mode if 'QHOME' in os.environ and not ignore_qhome: # Only link the user's QHOME to PyKX's QHOME if the user actually set $QHOME. - # Note that `pykx.qhome` has a default value of `./q`, as that is the behaviour + # Note that `pykx.qhome` has a default value of `./q`, as that is the behavior # employed by q. try: _link_qhome() @@ -302,7 +302,7 @@ else: _libq_path_py = bytes(_core_q_lib_path) _libq_path = _libq_path_py _q_handle = dlopen(_libq_path, RTLD_NOW | RTLD_GLOBAL) - qinit = dlsym(_q_handle, 'qinit') + qinit = dlsym(_q_handle, 'qinit') qinit_return_code = _qinit(qinit, str(qhome if ignore_qhome else pykx_lib_dir), str(qlic), list(qargs)) if qinit_return_code: # nocov dlclose(_q_handle) # nocov @@ -317,73 +317,73 @@ if k_gc and not licensed: -kG = dlsym(_q_handle, 'kG') -kC = dlsym(_q_handle, 'kC') +kG = dlsym(_q_handle, 'kG') +kC = dlsym(_q_handle, 'kC') kU = dlsym(_q_handle, 'kU') -kS = dlsym(_q_handle, 'kS') -kH = dlsym(_q_handle, 'kH') -kI = dlsym(_q_handle, 'kI') -kJ = dlsym(_q_handle, 'kJ') -kE = dlsym(_q_handle, 'kE') -kF = dlsym(_q_handle, 'kF') +kS = dlsym(_q_handle, 'kS') +kH = dlsym(_q_handle, 'kH') +kI = dlsym(_q_handle, 'kI') +kJ = dlsym(_q_handle, 'kJ') +kE = dlsym(_q_handle, 'kE') +kF = dlsym(_q_handle, 'kF') kK = dlsym(_q_handle, 'kK') -b9 = dlsym(_q_handle, 'b9') +b9 = dlsym(_q_handle, 'b9') d9 = dlsym(_q_handle, 'd9') -dj = dlsym(_q_handle, 'dj') -dl = dlsym(_q_handle, 'dl') +dj = dlsym(_q_handle, 'dj') +dl = dlsym(_q_handle, 'dl') dot = dlsym(_q_handle, 'dot') ee = dlsym(_q_handle, 'ee') -ja = dlsym(_q_handle, 'ja') +ja = dlsym(_q_handle, 'ja') jk = dlsym(_q_handle, 'jk') -js = dlsym(_q_handle, 'js') +js = dlsym(_q_handle, 'js') jv = dlsym(_q_handle, 'jv') -k = dlsym(_q_handle, 'k') +k = dlsym(_q_handle, 'k') cdef extern from 'include/foreign.h': K k_wrapper(void* x, char* code, void* a1, void* a2, void* a3, void* a4, void* a5, void* a6, void* a7, void* a8) nogil knogil = k_wrapper -ka = dlsym(_q_handle, 'ka') -kb = dlsym(_q_handle, 'kb') -kc = dlsym(_q_handle, 'kc') -kclose = dlsym(_q_handle, 'kclose') -kd = dlsym(_q_handle, 'kd') -ke = dlsym(_q_handle, 'ke') -kf = dlsym(_q_handle, 'kf') -kg = dlsym(_q_handle, 'kg') -kh = dlsym(_q_handle, 'kh') -khpunc = dlsym(_q_handle, 'khpunc') -ki = dlsym(_q_handle, 'ki') -kj = dlsym(_q_handle, 'kj') -knk = dlsym(_q_handle, 'knk') -knt = dlsym(_q_handle, 'knt') -kp = dlsym(_q_handle, 'kp') -kpn = dlsym(_q_handle, 'kpn') -krr = dlsym(_q_handle, 'krr') -ks = dlsym(_q_handle, 'ks') -kt = dlsym(_q_handle, 'kt') +ka = dlsym(_q_handle, 'ka') +kb = dlsym(_q_handle, 'kb') +kc = dlsym(_q_handle, 'kc') +kclose = dlsym(_q_handle, 'kclose') +kd = dlsym(_q_handle, 'kd') +ke = dlsym(_q_handle, 'ke') +kf = dlsym(_q_handle, 'kf') +kg = dlsym(_q_handle, 'kg') +kh = dlsym(_q_handle, 'kh') +khpunc = dlsym(_q_handle, 'khpunc') +ki = dlsym(_q_handle, 'ki') +kj = dlsym(_q_handle, 'kj') +knk = dlsym(_q_handle, 'knk') +knt = dlsym(_q_handle, 'knt') +kp = dlsym(_q_handle, 'kp') +kpn = dlsym(_q_handle, 'kpn') +krr = dlsym(_q_handle, 'krr') +ks = dlsym(_q_handle, 'ks') +kt = dlsym(_q_handle, 'kt') ktd = dlsym(_q_handle, 'ktd') -ktj = dlsym(_q_handle, 'ktj') -ktn = dlsym(_q_handle, 'ktn') +ktj = dlsym(_q_handle, 'ktj') +ktn = dlsym(_q_handle, 'ktn') ku = dlsym(_q_handle, 'ku') -kz = dlsym(_q_handle, 'kz') -m9 = dlsym(_q_handle, 'm9') -okx = dlsym(_q_handle, 'okx') -orr = dlsym(_q_handle, 'orr') -r0 = dlsym(_q_handle, 'r0') +kz = dlsym(_q_handle, 'kz') +m9 = dlsym(_q_handle, 'm9') +okx = dlsym(_q_handle, 'okx') +orr = dlsym(_q_handle, 'orr') +r0 = dlsym(_q_handle, 'r0') r1 = dlsym(_q_handle, 'r1') -sd0 = dlsym(_q_handle, 'sd0') -sd0x = dlsym(_q_handle, 'sd0x') -sd1 = dlsym(_q_handle, 'sd1') -sd1 = dlsym(_q_handle, 'sd1') -sn = dlsym(_q_handle, 'sn') -ss = dlsym(_q_handle, 'ss') +sd0 = dlsym(_q_handle, 'sd0') +sd0x = dlsym(_q_handle, 'sd0x') +sd1 = dlsym(_q_handle, 'sd1') +sd1 = dlsym(_q_handle, 'sd1') +sn = dlsym(_q_handle, 'sn') +ss = dlsym(_q_handle, 'ss') sslInfo = dlsym(_q_handle, 'sslInfo') -vak = dlsym(_q_handle, 'vak') -vaknk = dlsym(_q_handle, 'vaknk') -ver = dlsym(_q_handle, 'ver') +vak = dlsym(_q_handle, 'vak') +vaknk = dlsym(_q_handle, 'vaknk') +ver = dlsym(_q_handle, 'ver') xD = dlsym(_q_handle, 'xD') xT = dlsym(_q_handle, 'xT') -ymd = dlsym(_q_handle, 'ymd') +ymd = dlsym(_q_handle, 'ymd') _r0_ptr = int(r0) _k_ptr = int(k) diff --git a/src/pykx/include/foreign.h b/src/pykx/include/foreign.h index 016035b..e72686c 100644 --- a/src/pykx/include/foreign.h +++ b/src/pykx/include/foreign.h @@ -8,11 +8,11 @@ static PyObject* get_py_ptr(K f) { } -static K k_wrapper(void* k_fn, S code, void* a1, void* a2, void* a3, void* a4, void* a5, void* a6, void* a7, void* a8) { +static K k_wrapper(void* k_fn, char* code, void* a1, void* a2, void* a3, void* a4, void* a5, void* a6, void* a7, void* a8) { int gstate = PyGILState_Ensure(); K res = NULL; Py_BEGIN_ALLOW_THREADS - K (*k_func)(I, S, ...) = (K (*)(I, S, ...))k_fn; + K (*k_func)(int, char*, ...) = (K (*)(int, char*, ...))k_fn; res = k_func(0, code, a1, a2, a3, a4, a5, a6, a7, a8, NULL); Py_END_ALLOW_THREADS PyGILState_Release(gstate); @@ -51,5 +51,5 @@ static PyObject* _to_bytes_(K k, char wait) { // or if the message should be considered async and no reply is necessary // A value of 2 at index 1 implies that the message is a response kG(k)[1] = wait; - return PyMemoryView_FromMemory((S)kG(k), (Py_ssize_t)k->n, PyBUF_READ); + return PyMemoryView_FromMemory((char*)kG(k), (Py_ssize_t)k->n, PyBUF_READ); } diff --git a/src/pykx/include/k.h b/src/pykx/include/k.h index 21de7da..b0d5a36 100644 --- a/src/pykx/include/k.h +++ b/src/pykx/include/k.h @@ -1,25 +1,44 @@ #ifndef KX #define KX -typedef char*S,C;typedef unsigned char G;typedef short H;typedef int I;typedef long long J;typedef float E;typedef double F;typedef void V; #define KXVER 3 -typedef struct k0{signed char m,a,t;C u;I r;union{G g;H h;I i;J j;E e;F f;S s;struct k0*k;struct{J n;G G0[1];};};}*K; -typedef struct _U{G g[16];}U; +typedef struct k0{ + signed char m,a,t; + char u; + int r; + union{ + unsigned char g; + short h; + int i; + long long j; + float e; + double f; + char* s; + struct k0* k; + struct{ + long long n; + unsigned char G0[1]; + }; + }; +} *K; +typedef struct _U{ + unsigned char g[16]; +} U; #define kU(x) ((U*)kG(x)) #define xU ((U*)xG) -extern K ku(U),knt(J,K),ktn(I,J),kpn(S,J); -extern I setm(I),ver(); -#define DO(n,x) {J i=0,_i=(n);for(;i<_i;++i){x;}} -extern I qinit(I, C**, C*, C*, C*); +extern K ku(U),knt(long long,K),ktn(int,long long),kpn(char*,long long); +extern int setm(int),ver(); +#define DO(n,x) {long long i=0,_i=(n);for(;i<_i;++i){x;}} +extern int qinit(int, char**, char*, char*, char*); // vector accessors, e.g. kF(x)[i] for float&datetime #define kG(x) ((x)->G0) #define kC(x) kG(x) -#define kH(x) ((H*)kG(x)) -#define kI(x) ((I*)kG(x)) -#define kJ(x) ((J*)kG(x)) -#define kE(x) ((E*)kG(x)) -#define kF(x) ((F*)kG(x)) -#define kS(x) ((S*)kG(x)) +#define kH(x) ((short*)kG(x)) +#define kI(x) ((int*)kG(x)) +#define kJ(x) ((long long*)kG(x)) +#define kE(x) ((float*)kG(x)) +#define kF(x) ((double*)kG(x)) +#define kS(x) ((char**)kG(x)) #define kK(x) ((K*)kG(x)) // type bytes qtype ctype accessor @@ -52,24 +71,70 @@ extern I qinit(I, C**, C*, C*, C*); #ifdef __cplusplus #include extern"C"{ -extern V m9(); +extern void m9(); #else #include -extern V m9(V); +extern void m9(void); #endif -extern I khpunc(S,I,S,I,I),khpun(const S,I,const S,I),khpu(const S,I,const S),khp(const S,I),okx(K),ymd(I,I,I),dj(I);extern V r0(K),sd0(I),sd0x(I d,I f),kclose(I);extern S sn(S,I),ss(S); -extern K ee(K),ktj(I,J),ka(I),kb(I),kg(I),kh(I),ki(I),kj(J),ke(F),kf(F),kc(I),ks(S),kd(I),kz(F),kt(I),sd1(I,K(*)(I)),dl(V*f,J), - knk(I,...),kp(S),ja(K*,V*),js(K*,S),jk(K*,K),jv(K*k,K),k(I,const S,...),xT(K),xD(K,K),ktd(K),r1(K),krr(const S),orr(const S),dot(K,K),b9(I,K),d9(K),sslInfo(K x),vaknk(I,va_list),vak(I,const S,va_list); +extern int khpunc(char*,int,char*,int,int), + khpun(const char*,int,const char*,int), + khpu(const char*,int,const char*), + khp(const char*,int), + okx(K), + ymd(int,int,int), + dj(int); +extern void r0(K), + sd0(int), + sd0x(int d,int f), + kclose(int); +extern char* sn(char*,int), + ss(char*); +extern K ee(K), + ktj(int,long long), + ka(int), + kb(int), + kg(int), + kh(int), + ki(int), + kj(long long), + ke(double), + kf(double), + kc(int), + ks(char*), + kd(int), + kz(double), + kt(int), + sd1(int,K(*)(int)), + dl(void*f,long long), + knk(int,...), + kp(char*), + ja(K*,void*), + js(K*,char*), + jk(K*,K), + jv(K*k,K), + k(int,const char*,...), + xT(K), + xD(K,K), + ktd(K), + r1(K), + krr(const char*), + orr(const char*), + dot(K,K), + b9(int,K), + d9(K), + sslInfo(K x), + vaknk(int,va_list), + vak(int,const char*,va_list); #ifdef __cplusplus } #endif // nulls(n?) and infinities(w?) -#define nh ((I)0xFFFF8000) -#define wh ((I)0x7FFF) -#define ni ((I)0x80000000) -#define wi ((I)0x7FFFFFFF) -#define nj ((J)0x8000000000000000LL) +#define nh ((int)0xFFFF8000) +#define wh ((int)0x7FFF) +#define ni ((int)0x80000000) +#define wi ((int)0x7FFFFFFF) +#define nj ((long long)0x8000000000000000LL) #define wj 0x7FFFFFFFFFFFFFFFLL #if defined(WIN32) || defined(_WIN32) #define nf (log(-1.0)) @@ -81,10 +146,9 @@ extern double log(double); #endif // remove more clutter +/* #define O printf #define Z static -#define P(x,y) {if(x)return(y);} -#define U(x) P(!(x),0) #define SW switch #define CS(n,x) case n:x;break; #define CD default @@ -125,5 +189,8 @@ extern double log(double); #define xK ((K*)xG) #define xC xG #define xB ((G*)xG) - +*/ +#define xt x->t +#define P(x,y) {if(x)return(y);} +#define U(x) P(!(x),0) #endif diff --git a/src/pykx/include/py.h b/src/pykx/include/py.h index f90ef3f..9c87daa 100644 --- a/src/pykx/include/py.h +++ b/src/pykx/include/py.h @@ -16,8 +16,39 @@ typedef ssize_t L; #include"k.h" #define K3(f) K f(K x,K y,K z) -typedef struct _p _p,*P;struct _p{L r;P t;L n;union{P*p;P v[1];};};typedef struct{L r;P t;G*g;I n;L*c,*s;P*b;struct{L r;P t;P*o;C k,c,b,f;I n,e;}*d;I f;}*A;typedef struct{S n;V*m;I f;S d;}D; -#define ZP Z P +typedef struct _p _p,*P; +struct _p{ + L r; + P t; + L n; + union{ + P* p; + P v[1]; + }; +}; +typedef struct{ + L r; + P t; + unsigned char* g; + int n; + L*c,*s; + P*b; + struct{ + L r; + P t; + P*o; + char* k,c,b,f; + int n,e; + }*d; + int f; +}*A; +typedef struct{ + char* n; + void* m; + int f; + char* d; +}D; +#define ZP static P #define PyGILState_STATE int #define Py_ssize_t size_t #define Py_EQ 2 @@ -30,39 +61,39 @@ typedef struct _p _p,*P;struct _p{L r;P t;L n;union{P*p;P v[1];};};typedef struc //https://docs.python.org/3/c-api/ https://github.com/python/cpython/blob/3.6/PC/python3.def #define PF \ - X(V,Py_InitializeEx,(I))\ - X(V,Py_Finalize,())\ - X(V,Py_DecRef,(P))\ - X(V,Py_IncRef,(P))\ - X(V,PyErr_Clear,())\ - X(V,PyErr_Fetch,(P*,P*,P*))\ - X(V,PyErr_NormalizeException,(P*,P*,P*))\ + X(void,Py_InitializeEx,(int))\ + X(void,Py_Finalize,())\ + X(void,Py_DecRef,(P))\ + X(void,Py_IncRef,(P))\ + X(void,PyErr_Clear,())\ + X(void,PyErr_Fetch,(P*,P*,P*))\ + X(void,PyErr_NormalizeException,(P*,P*,P*))\ X(P,PyErr_BadArgument,())\ - X(P,PyErr_SetString,(P,S))\ - X(I,PyGILState_Ensure,())\ - X(V,PyGILState_Release,(I))\ - X(I,PyGILState_Check,())\ - X(V,PyEval_InitThreads,())\ - X(I,PyEval_ThreadsInitialized,())\ - X(V*,PyGILState_GetThisThreadState,())\ - X(V*,PyEval_SaveThread,())\ - X(V,PyEval_RestoreThread,(V*))\ + X(P,PyErr_SetString,(P,char*))\ + X(int,PyGILState_Ensure,())\ + X(void,PyGILState_Release,(int))\ + X(int,PyGILState_Check,())\ + X(void,PyEval_InitThreads,())\ + X(int,PyEval_ThreadsInitialized,())\ + X(void*,PyGILState_GetThisThreadState,())\ + X(void*,PyEval_SaveThread,())\ + X(void,PyEval_RestoreThread,(void*))\ X(_p,PyExc_RuntimeError,)\ X(P,PyObject_Str,(P))\ - X(wchar_t*,Py_DecodeLocale,(S,V*))\ - X(V,Py_SetPythonHome,(wchar_t*))\ - X(V,Py_SetProgramName,(wchar_t*))\ - X(P,PyImport_AddModule,(S))\ - X(P,PyImport_ImportModule,(S))\ - X(P,PyObject_GetAttrString,(P,S))\ + X(wchar_t*,Py_DecodeLocale,(char*,void*))\ + X(void,Py_SetPythonHome,(wchar_t*))\ + X(void,Py_SetProgramName,(wchar_t*))\ + X(P,PyImport_AddModule,(char*))\ + X(P,PyImport_ImportModule,(char*))\ + X(P,PyObject_GetAttrString,(P,char*))\ X(P,PyObject_Type,(P))\ X(P,PyModule_GetDict,(P))\ - X(P,PyDict_GetItemString,(P,S))\ - X(P,PyDict_SetItemString,(P,S,P))\ + X(P,PyDict_GetItemString,(P,char*))\ + X(P,PyDict_SetItemString,(P,char*,P))\ X(P,PyEval_EvalCode,(P,P,P))\ - X(P,Py_CompileString,(S,S,I))\ - X(P,PyCapsule_New,(V*,S,V*))\ - X(V*,PyCapsule_GetPointer,(P,S))\ + X(P,Py_CompileString,(char*,char*,int))\ + X(P,PyCapsule_New,(void*,char*,void*))\ + X(void*,PyCapsule_GetPointer,(P,char*))\ X(P,PyCFunction_NewEx,(D*,P,P))\ X(_p,_Py_TrueStruct,)\ X(_p,_Py_FalseStruct,)\ @@ -74,61 +105,61 @@ typedef struct _p _p,*P;struct _p{L r;P t;L n;union{P*p;P v[1];};};typedef struc X(_p,PyDict_Type,)\ X(_p,PyUnicode_Type,)\ X(_p,PyBytes_Type,)\ - X(I,PyType_IsSubtype,(P,P))\ - X(J,PyLong_AsLongLongAndOverflow,(P,I*))\ - X(F,PyFloat_AsDouble,(P))\ - X(I,PyObject_RichCompareBool,(P,P,I))\ - X(S,PyUnicode_AsUTF8AndSize,(P,L*))\ - X(I,PyBytes_AsStringAndSize,(P,S*,L*))\ - X(S,PyBytes_AsString,(P))\ + X(int,PyType_IsSubtype,(P,P))\ + X(long long,PyLong_AsLongLongAndOverflow,(P,int*))\ + X(double,PyFloat_AsDouble,(P))\ + X(int,PyObject_RichCompareBool,(P,P,int))\ + X(char*,PyUnicode_AsUTF8AndSize,(P,L*))\ + X(int,PyBytes_AsStringAndSize,(P,char**,L*))\ + X(char*,PyBytes_AsString,(P))\ X(P,PyBool_FromLong,(long))\ X(P,PyErr_Occurred,())\ - X(V,PyErr_WriteUnraisable,(P))\ - X(I,PyException_SetTraceback,(P,P))\ - X(V*,PyMem_Calloc,(size_t,size_t))\ - X(V,PyMem_Free,(V*))\ - X(V,PyErr_SetObject,(P,P))\ - X(V,PyErr_Print,())\ + X(void,PyErr_WriteUnraisable,(P))\ + X(int,PyException_SetTraceback,(P,P))\ + X(void*,PyMem_Calloc,(size_t,size_t))\ + X(void,PyMem_Free,(void*))\ + X(void,PyErr_SetObject,(P,P))\ + X(void,PyErr_Print,())\ X(P,PyObject_Repr,(P))\ - X(I,PyObject_Print,(P,FILE*,I))\ - X(P,PyLong_FromLongLong,(J))\ - X(J,PyLong_AsLongLong,(P))\ + X(int,PyObject_Print,(P,FILE*,int))\ + X(P,PyLong_FromLongLong,(long long))\ + X(long long,PyLong_AsLongLong,(P))\ X(P,PyLong_FromSize_t,(size_t))\ - X(P,PyFloat_FromDouble,(F))\ - X(P,PyUnicode_FromStringAndSize,(S,L))\ - X(P,PyUnicode_FromString,(S))\ - X(P,PyUnicode_AsEncodedString,(P,S,S))\ - X(P,PyBytes_FromStringAndSize,(S,L))\ + X(P,PyFloat_FromDouble,(double))\ + X(P,PyUnicode_FromStringAndSize,(char*,L))\ + X(P,PyUnicode_FromString,(char*))\ + X(P,PyUnicode_AsEncodedString,(P,char*,char*))\ + X(P,PyBytes_FromStringAndSize,(char*,L))\ X(P,PySequence_List,(P))\ - X(P,Py_BuildValue,(S,...))\ + X(P,Py_BuildValue,(char*,...))\ X(P,PyTuple_New,(L))\ X(P,PyList_New,(L))\ X(P,PyDict_New,())\ X(size_t,PySequence_Size,(P))\ X(P,PySequence_GetItem,(P, size_t))\ - X(I,PyList_Append,(P,P))\ + X(int,PyList_Append,(P,P))\ X(P,PyList_GetItem,(P,size_t))\ X(P,PyTuple_GetItem,(P,size_t))\ X(P,PyDict_GetItemWithError,(P,P))\ X(P,PyDict_SetItem,(P,P,P))\ - X(I,PyTuple_SetItem,(P,size_t,P))\ + X(int,PyTuple_SetItem,(P,size_t,P))\ X(P,PyDict_Keys,(P))\ X(P,PyDict_Values,(P))\ - X(I,PyDict_Update,(P,P))\ + X(int,PyDict_Update,(P,P))\ X(P,PyList_AsTuple,(P))\ X(P,PyObject_CallFunctionObjArgs,(P,...))\ - X(P,PyObject_CallFunction,(P,S,...))\ - X(P,PyObject_CallMethod,(P,S,S,...))\ + X(P,PyObject_CallFunction,(P,char*,...))\ + X(P,PyObject_CallMethod,(P,char*,char*,...))\ X(P,PyObject_Call,(P,P,P))\ X(P,PyObject_CallObject,(P,P))\ - X(I,PyObject_HasAttr,(P,P))\ + X(int,PyObject_HasAttr,(P,P))\ X(P,PyObject_GetAttr,(P,P))\ - X(I,PyObject_SetAttrString,(P,S,P))\ - X(S,PyUnicode_AsUTF8,(P))\ - X(I,PyCallable_Check,(P))\ - X(P,PyRun_String,(S,I,P,P))\ + X(int,PyObject_SetAttrString,(P,char*,P))\ + X(char*,PyUnicode_AsUTF8,(P))\ + X(int,PyCallable_Check,(P))\ + X(P,PyRun_String,(char*,int,P,P))\ X(P,PyImport_Import,(P))\ - X(I,Py_IsInitialized,())\ + X(int,Py_IsInitialized,())\ //https://docs.scipy.org/doc/numpy/reference/c-api.html https://github.com/numpy/numpy/blob/master/numpy/core/code_generators/numpy_api.py #undef PyCFunction_New @@ -136,24 +167,24 @@ typedef struct _p _p,*P;struct _p{L r;P t;L n;union{P*p;P v[1];};};typedef struc #define NF \ X(_p,PyArray_Type,,2)\ X(_p,PyGenericArrType_Type,,10)\ - X(A,PyArray_NewCopy,(A,I),85)\ - X(A,PyArray_New,(P,I,L*,I,L*,V*,I,I,P),93)\ - X(I,PyArray_SetBaseObject,(A,P),282)\ + X(A,PyArray_NewCopy,(A,int),85)\ + X(A,PyArray_New,(P,int,L*,int,L*,void*,int,int,P),93)\ + X(int,PyArray_SetBaseObject,(A,P),282)\ X(A,PyArray_FromScalar,(P,P),61)\ -#define X(r,n,a,...) typedef r T##n;Z T##n(*n)a; +#define X(r,n,a,...) typedef r T##n;static T##n(*n)a; PF NF #undef X -ZI ta(A a){I c[]={KB,-1,KG,KH,-1,KI,-1,4==sizeof(long)?KI:KJ,-1,KJ,-1,KE,KF,-1,-1,-1,-1,0,-1,-1,-1},t=a->d->n;return t>20?-1:c[t];} -ZI tk(K x){I c[]={-1,0,-1,-1,-1,3,5,9,11,12,-1,-1,9,5,5,12,9,5,5,5},t=xt>0?xt:-xt;return t>19?-1:c[t];} +static int ta(A a){int c[]={KB,-1,KG,KH,-1,KI,-1,4==sizeof(long)?KI:KJ,-1,KJ,-1,KE,KF,-1,-1,-1,-1,0,-1,-1,-1},t=a->d->n;return t>20?-1:c[t];} +static int tk(K x){int c[]={-1,0,-1,-1,-1,3,5,9,11,12,-1,-1,9,5,5,12,9,5,5,5},t=xt>0?xt:-xt;return t>19?-1:c[t];} -ZI pyl(S l){ +static int pyl(char* l){ #if _WIN32 HMODULE d=LoadLibrary(l); #define X(r,n,a) U(n=(T##n(*)a)GetProcAddress(d,#n)) #else - V*d=dlopen(l,RTLD_NOW|RTLD_GLOBAL); + void*d=dlopen(l,RTLD_NOW|RTLD_GLOBAL); #define X(r,n,a) U(n=dlsym(d,#n)) #endif P(!d,0)PF @@ -162,7 +193,7 @@ ZI pyl(S l){ #define BUFFSIZE 4096 -ZI pyn(V**v){ +static int pyn(void**v){ #define X(r,n,a,i) U(n=(T##n(*)a)v[i]) NF return 1;} diff --git a/src/pykx/include/unlicensed_getitem.h b/src/pykx/include/unlicensed_getitem.h index 0234cea..2d7bf86 100644 --- a/src/pykx/include/unlicensed_getitem.h +++ b/src/pykx/include/unlicensed_getitem.h @@ -3,32 +3,32 @@ #include "k.h" -static F get_double(K k, size_t index) { +static double get_double(K k, size_t index) { return kF(k)[index]; } -static E get_float(K k, size_t index) { +static float get_float(K k, size_t index) { return kE(k)[index]; } -static J get_long(K k, size_t index) { +static long long get_long(K k, size_t index) { return kJ(k)[index]; } -static I get_int(K k, size_t index) { +static int get_int(K k, size_t index) { return kI(k)[index]; } -static H get_short(K k, size_t index) { +static short get_short(K k, size_t index) { return kH(k)[index]; } -static G get_byte(K k, size_t index) { +static unsigned char get_byte(K k, size_t index) { return kG(k)[index]; } diff --git a/src/pykx/include/vector_conversion.h b/src/pykx/include/vector_conversion.h index cbd4c92..99a700c 100644 --- a/src/pykx/include/vector_conversion.h +++ b/src/pykx/include/vector_conversion.h @@ -4,18 +4,18 @@ static PyObject* symbol_vector_to_py(K s, int raw) { PyObject* res = PyList_New(s->n); - S* sl = kS(s); + char** sl = kS(s); if (raw == 1) { for (int i = 0; i < s->n; i++) { PyObject* py_str = NULL; - S str = sl[i]; + char* str = sl[i]; py_str = PyBytes_FromString(str); PyList_SET_ITEM(res, i, py_str); } } else { for (int i = 0; i < s->n; i++) { PyObject* py_str = NULL; - S str = sl[i]; + char* str = sl[i]; py_str = PyUnicode_FromString(str); PyList_SET_ITEM(res, i, py_str); } diff --git a/src/pykx/ipc.py b/src/pykx/ipc.py index 6f27c2d..1a69722 100644 --- a/src/pykx/ipc.py +++ b/src/pykx/ipc.py @@ -36,7 +36,7 @@ from weakref import finalize, WeakMethod import sys -from . import Q +from . import deserialize, serialize, Q from .config import max_error_length, pykx_lib_dir, system from .core import licensed from .exceptions import FutureCancelled, NoResults, PyKXException, QError, UninitializedConnection @@ -282,7 +282,7 @@ def __init__(self, Note: Creating an instance of this class returns an instance of `pykx.SyncQConnection`. Directly instantiating an instance of `pykx.SyncQConnection` is recommended, but - this behaviour will remain for backwards compatibility. + this behavior will remain for backwards compatibility. Parameters: host: The host name to which a connection is to be established. @@ -491,43 +491,35 @@ def _send_sock(self, # Find more on IPC and serialization here: # - https://code.kx.com/q/basics/ipc/ # - https://code.kx.com/q/kb/serialization/ - ptr = None - try: - k_query = K(query) - msg_view = _wrappers._to_bytes(6, k_query, 2 if error else 1 if wait else 0) - if isinstance(msg_view, tuple): - ptr = msg_view[0] - msg_view = msg_view[1] - msg_len = len(msg_view) - if error: - msg_view = list(bytes(msg_view)) - msg_view[8] = 128 - msg_view = memoryview(bytes(msg_view)) - wait=False - sent = 0 - while sent < msg_len: - try: - sent += sock.send(msg_view[sent:min(msg_len, sent + self._socket_buffer_size)]) - except BlockingIOError: # nocov - # The only way to get here is if we send too much data to the socket before it - # can be sent elsewhere, we just need to wait a moment until more data can be - # sent to the sockets buffer - pass - except BaseException: # nocov - raise RuntimeError("Failed to send query on IPC socket") - if isinstance(self, SyncQConnection) or isinstance(self, RawQConnection): - return - if wait: - q_future = QFuture(self, self._connection_info['timeout']) - self._call_stack.append(q_future) - return q_future - else: - q_future = QFuture(self, self._connection_info['timeout']) - q_future.set_result(K(None)) - return q_future - finally: - if ptr is not None: - _ipc.delete_ptr(ptr) + k_query = K(query) + msg_view = serialize(k_query, mode=6, wait=2 if error else 1 if wait else 0) + msg_len = len(msg_view) + if error: + msg_view = list(msg_view.copy()) + msg_view[8] = 128 + msg_view = memoryview(bytes(msg_view)) + wait=False + sent = 0 + while sent < msg_len: + try: + sent += sock.send(msg_view[sent:min(msg_len, sent + self._socket_buffer_size)]) + except BlockingIOError: # nocov + # The only way to get here is if we send too much data to the socket before it + # can be sent elsewhere, we just need to wait a moment until more data can be + # sent to the sockets buffer + pass + except BaseException: # nocov + raise RuntimeError("Failed to send query on IPC socket") + if isinstance(self, SyncQConnection) or isinstance(self, RawQConnection): + return + if wait: + q_future = QFuture(self, self._connection_info['timeout']) + self._call_stack.append(q_future) + return q_future + else: + q_future = QFuture(self, self._connection_info['timeout']) + q_future.set_result(K(None)) + return q_future # flake8: noqa: C901 def _recv(self, locked=False, acceptAsync=False): @@ -628,13 +620,13 @@ def _create_result(self, buff): if int(buff[2]) == 0 and int(buff[8]) == 128: raise self._create_error(buff) else: - return _wrappers.deserialize(memoryview(buff).obj) + return deserialize(memoryview(buff).obj) if int(buff[2]) == 0 and int(buff[8]) == 128: q_future = self._call_stack.pop(0) q_future.set_exception(self._create_error(buff)) else: q_future = self._call_stack.pop(0) - q_future.set_result(_wrappers.deserialize(memoryview(buff).obj)) + q_future.set_result(deserialize(memoryview(buff).obj)) def file_execute( self, @@ -1643,29 +1635,24 @@ def poll_send(self, amount: int = 1): count -= 1 def _serialize_response(self, response, level): - ptr = None error = isinstance(response, tuple) if error: response = response[1] try: - msg_view = _wrappers._to_bytes(level, response, 2) + msg = serialize(response, mode=level, wait=2) except QError as e: error = True response = SymbolAtom(f"{e}") - msg_view = _wrappers._to_bytes(level, response, 2) - if isinstance(msg_view, tuple): - ptr = msg_view[0] - msg_view = msg_view[1] + msg = serialize(response, mode=level, wait=2) if error: - msg_view = list(bytes(msg_view)) + msg_view = list(msg.copy()) msg_view[8] = 128 - msg_view = memoryview(bytes(msg_view)) - return ptr, msg_view + return memoryview(bytes(msg_view)) + return msg def _send_sock_server(self, sock, response, level): - ptr = None try: - ptr, msg_view = self._serialize_response(response, level) + msg_view = self._serialize_response(response, level) msg_len = len(msg_view) sent = 0 while sent < msg_len: @@ -1680,9 +1667,6 @@ def _send_sock_server(self, sock, response, level): raise RuntimeError("Failed to send query on IPC socket") except BaseException: # nocov pass - finally: - if ptr is not None: - _ipc.delete_ptr(ptr) def _recv_socket_server(self, sock): # noqa tot_bytes = 0 @@ -1728,7 +1712,7 @@ def _recv_socket_server(self, sock): # noqa # sent to the sockets buffer pass - return chunks[1], _wrappers.deserialize(memoryview(buff).obj) + return chunks[1], deserialize(memoryview(buff).obj) except ConnectionResetError: pass @@ -1800,21 +1784,14 @@ def _poll_server(self, amount: int = 1): # noqa def clean_open_connections(self): for i in range(len(self.open_cons) - 1, -1, -1): - ptr = None try: - msg_view = _wrappers._to_bytes(self.open_cons[i][3], q('::'), 0) - if isinstance(msg_view, tuple): - ptr = msg_view[0] - msg_view = msg_view[1] - self.open_cons[i][2].send(bytes(msg_view)) + msg = serialize(q('::'), mode=self.open_cons[i][3], wait=0) + self.open_cons[i][2].send(msg.copy()) except BaseException: self.open_cons[i][0].unregister(self.open_cons[i][2]) self.open_cons[i][1].unregister(self.open_cons[i][2]) self.open_cons[i][2].close() self.open_cons.pop(i) - finally: - if ptr is not None: - _ipc.delete_ptr(ptr) def poll_recv(self, amount: int = 1): """Recieve queries from the process connected to over IPC. diff --git a/src/pykx/lib/kxic.k b/src/pykx/lib/kxic.k index 0e90d2d..7e8eda1 100644 --- a/src/pykx/lib/kxic.k +++ b/src/pykx/lib/kxic.k @@ -9,4 +9,3 @@ if[(.z.o~`l64)&$[0=#.z.x;1b;~"-nokurl"in .z.x]; lf' (!d) @ & (.:d) in " "\:.z.l 4; / only load enabled features }[] ]; -{@[.:;"\\l ",$[#e:getenv`QINIT;e;"q.q"];::]}[]; diff --git a/src/pykx/nbextension.py b/src/pykx/nbextension.py index 5d1fc1a..e0531d4 100644 --- a/src/pykx/nbextension.py +++ b/src/pykx/nbextension.py @@ -96,15 +96,15 @@ def q(instructions, code): # noqa _q = kx.q code = [kx.CharVector(x) for x in code.split('\n')][:-1] ret = _q( - "{[ld;code;file] value (@';last file;enlist[file],/:value(ld;code))}", + "{[ld;code;file] value (@';\"q\";enlist[file],/:value(ld;code))}", ld, code, b'jupyter_cell.q' ) if not kx.licensed: ret = ret.py() - for r in ret: - print(r) + for i in range(len(ret)): + print(_q('{x y}', ret, i)) if issubclass(type(_q), kx.QConnection): _q.close() diff --git a/src/pykx/numpy_conversions.c b/src/pykx/numpy_conversions.c index 7004d68..4b25d0b 100644 --- a/src/pykx/numpy_conversions.c +++ b/src/pykx/numpy_conversions.c @@ -17,18 +17,18 @@ static PyObject* symbol_vector_to_np(PyObject* self, PyObject* args) { PyArrayObject* arr = PyArray_Zeros(1, dims, descr, 0); PyObject** data = (PyObject**)PyArray_DATA(arr); - S* sl = kS(symbol_vector); + char** sl = kS(symbol_vector); if (raw == 1) { for (int i = 0; i < dims[0]; i++){ PyObject* py_str = NULL; - S str = sl[i]; + char* str = sl[i]; py_str = PyBytes_FromString(str); data[i] = py_str; } } else { for (int i = 0; i < dims[0]; i++){ PyObject* py_str = NULL; - S str = sl[i]; + char* str = sl[i]; py_str = PyUnicode_FromString(str); data[i] = py_str; } diff --git a/src/pykx/pandas_api/pandas_indexing.py b/src/pykx/pandas_api/pandas_indexing.py index caf7bb7..954896d 100644 --- a/src/pykx/pandas_api/pandas_indexing.py +++ b/src/pykx/pandas_api/pandas_indexing.py @@ -1,4 +1,4 @@ -from ..wrappers import BooleanVector, IntVector, K, List, LongVector, ShortVector, SymbolAtom, SymbolVector # noqa +from ..wrappers import BooleanVector, IntVector, K, List, LongVector, ShortVector, SymbolAtom, SymbolVector, _idx_to_k # noqa from ..exceptions import QError from . import api_return, MetaAtomic @@ -190,6 +190,8 @@ def _iloc(tab, loc): def _loc(tab, loc): # noqa cols = None + if isinstance(loc, int): + loc = _idx_to_k(loc, len(tab)) if isinstance(loc, tuple): if 'Keyed' in str(type(tab)) and len(loc) == len(q.keys(tab)): keys = q.keys(tab).py() diff --git a/src/pykx/pandas_api/pandas_meta.py b/src/pykx/pandas_api/pandas_meta.py index 4e5dc09..d0e44ec 100644 --- a/src/pykx/pandas_api/pandas_meta.py +++ b/src/pykx/pandas_api/pandas_meta.py @@ -90,7 +90,7 @@ def inner(*args, **kwargs): 'h': b'kx.Short', 'i': b'kx.Int', 'j': b'kx.Long', - 'e': b'kx.Short', + 'e': b'kx.Real', 'f': b'kx.Float', 'p': b'kx.Timestamp', 'd': b'kx.Date', @@ -99,6 +99,7 @@ def inner(*args, **kwargs): 'u': b'kx.Minute', 'v': b'kx.Second', 't': b'kx.Time', + 'm': b'kx.Month', '': b'kx.List'} diff --git a/src/pykx/pykx.c b/src/pykx/pykx.c index bf95324..d27a1e5 100644 --- a/src/pykx/pykx.c +++ b/src/pykx/pykx.c @@ -16,14 +16,14 @@ static void (*r0_ptr)(K); static K (*r1_ptr)(K); -static K (*ki_ptr)(J); -static K (*kj_ptr)(J); -static K (*ks_ptr)(S); -static K (*ktn_ptr)(I, J); -static K (*knk_ptr)(I, ...); -static K (*kpn_ptr)(S, J); -static K (*kp_ptr)(S); -static K (*k_ptr)(I, S, ...); +static K (*ki_ptr)(long long); +static K (*kj_ptr)(long long); +static K (*ks_ptr)(char*); +static K (*ktn_ptr)(int, long long); +static K (*knk_ptr)(int, ...); +static K (*kpn_ptr)(char*, long long); +static K (*kp_ptr)(char*); +static K (*k_ptr)(int, char*, ...); void* q_lib; static PyObject* builtins; @@ -54,14 +54,14 @@ EXPORT K k_pykx_init(K k_q_lib_path) { q_lib = dlopen(k_q_lib_path->s, RTLD_NOW | RTLD_GLOBAL); r0_ptr = (void (*)(K))dlsym(q_lib, "r0"); r1_ptr = (K (*)(K))dlsym(q_lib, "r1"); - k_ptr = (K (*)(I, S, ...))dlsym(q_lib, "k"); - ki_ptr = (K (*)(J))dlsym(q_lib, "ki"); - kj_ptr = (K (*)(J))dlsym(q_lib, "kj"); - ks_ptr = (K (*)(S))dlsym(q_lib, "ks"); - ktn_ptr = (K (*)(I, J))dlsym(q_lib, "ktn"); - knk_ptr = (K (*)(I, ...))dlsym(q_lib, "knk"); - kpn_ptr = (K (*)(S, J))dlsym(q_lib, "kpn"); - kp_ptr = (K (*)(S))dlsym(q_lib, "kp"); + k_ptr = (K (*)(int, char*, ...))dlsym(q_lib, "k"); + ki_ptr = (K (*)(long long))dlsym(q_lib, "ki"); + kj_ptr = (K (*)(long long))dlsym(q_lib, "kj"); + ks_ptr = (K (*)(char*))dlsym(q_lib, "ks"); + ktn_ptr = (K (*)(int, long long))dlsym(q_lib, "ktn"); + knk_ptr = (K (*)(int, ...))dlsym(q_lib, "knk"); + kpn_ptr = (K (*)(char*, long long))dlsym(q_lib, "kpn"); + kp_ptr = (K (*)(char*))dlsym(q_lib, "kp"); Py_Initialize(); PyGILState_STATE gstate; @@ -125,7 +125,7 @@ K k_py_error() { // Build a q error object with the repr of the exception value as its message. The full // traceback is provided as the cause to the QError that will be raised. PyObject* ex_repr = PyObject_CallMethod(ex_value, "__repr__", NULL); - K k = ks_ptr((S)PyUnicode_AsUTF8(ex_repr)); + K k = ks_ptr((char*)PyUnicode_AsUTF8(ex_repr)); k->t = -128; Py_XDECREF(ex_repr); @@ -416,8 +416,8 @@ EXPORT K k_pyrun(K k_ret, K k_eval_or_exec, K as_foreign, K k_code_string) { } -inline J modpow(J base, J exp, J mod) { - J result = 1; +inline long long modpow(long long base, long long exp, long long mod) { + long long result = 1; while (exp > 0) { if (exp & 1) result = (result * base) % mod; base = (base * base) % mod; @@ -444,7 +444,7 @@ EXPORT K k_modpow(K k_base, K k_exp, K k_mod_arg) { result->t = -128; } else { result = ktn_ptr(7, k_base->n); - for (J x = 0; x < k_base->n; ++x) kJ(result)[x] = modpow(kJ(k_base)[x], kJ(k_exp)[x], kJ(k_mod)[x]); + for (long long x = 0; x < k_base->n; ++x) kJ(result)[x] = modpow(kJ(k_base)[x], kJ(k_exp)[x], kJ(k_mod)[x]); } } else if (k_base->t >= 0 && k_exp->t >= 0) { if (k_base->n != k_exp->n) { @@ -453,7 +453,7 @@ EXPORT K k_modpow(K k_base, K k_exp, K k_mod_arg) { } else { result = ktn_ptr(7, k_base->n); - for (J x = 0; x < k_base->n; ++x) kJ(result)[x] = modpow(kJ(k_base)[x], kJ(k_exp)[x], k_mod->j); + for (long long x = 0; x < k_base->n; ++x) kJ(result)[x] = modpow(kJ(k_base)[x], kJ(k_exp)[x], k_mod->j); } } else if (k_base->t >= 0 && k_mod->t >= 0) { if (k_base->n != k_mod->n) { @@ -461,10 +461,10 @@ EXPORT K k_modpow(K k_base, K k_exp, K k_mod_arg) { result->t = -128; } result = ktn_ptr(7, k_base->n); - for (J x = 0; x < k_base->n; ++x) kJ(result)[x] = modpow(kJ(k_base)[x], k_exp->j, kJ(k_mod)[x]); + for (long long x = 0; x < k_base->n; ++x) kJ(result)[x] = modpow(kJ(k_base)[x], k_exp->j, kJ(k_mod)[x]); } else if (k_base->t >= 0) { result = ktn_ptr(7, k_base->n); - for (J x = 0; x < k_base->n; ++x) kJ(result)[x] = modpow(kJ(k_base)[x], k_exp->j, k_mod->j); + for (long long x = 0; x < k_base->n; ++x) kJ(result)[x] = modpow(kJ(k_base)[x], k_exp->j, k_mod->j); } else if (k_exp->t >= 0 && k_mod->t >= 0) { if (k_exp->n != k_mod->n) { result = ks_ptr("length"); @@ -472,14 +472,14 @@ EXPORT K k_modpow(K k_base, K k_exp, K k_mod_arg) { } else { result = ktn_ptr(7, k_exp->n); - for (J x = 0; x < k_exp->n; ++x) kJ(result)[x] = modpow(k_base->j, kJ(k_exp)[x], kJ(k_mod)[x]); + for (long long x = 0; x < k_exp->n; ++x) kJ(result)[x] = modpow(k_base->j, kJ(k_exp)[x], kJ(k_mod)[x]); } } else if (k_exp->t >= 0) { result = ktn_ptr(7, k_exp->n); - for (J x = 0; x < k_exp->n; ++x) kJ(result)[x] = modpow(k_base->j, kJ(k_exp)[x], k_mod->j); + for (long long x = 0; x < k_exp->n; ++x) kJ(result)[x] = modpow(k_base->j, kJ(k_exp)[x], k_mod->j); } else if (k_mod->t >= 0) { result = ktn_ptr(7, k_mod->n); - for (J x = 0; x < k_mod->n; ++x) kJ(result)[x] = modpow(k_base->j, k_exp->j, kJ(k_mod)[x]); + for (long long x = 0; x < k_mod->n; ++x) kJ(result)[x] = modpow(k_base->j, k_exp->j, kJ(k_mod)[x]); } else { result = kj_ptr(modpow(k_base->j, k_exp->j, k_mod->j)); } diff --git a/src/pykx/pykx.q b/src/pykx/pykx.q index fa326fa..4acdee5 100644 --- a/src/pykx/pykx.q +++ b/src/pykx/pykx.q @@ -5,7 +5,7 @@ // @end // @private -// @desc Process context prior to PyKX initialisation +// @desc Process context prior to PyKX initialization .pykx.util.prevCtx:system"d"; \d .pykx @@ -29,18 +29,20 @@ util.os:first string .z.o; // @type {dict} util.startup:.Q.opt .z.x +util.whichPython:() + // @private -// @desc Retrieval of PyKX initialisation directory on first initialisation -if[not "true"~getenv`PYKX_LOADED_UNDER_Q; +// @desc Retrieval of PyKX initialization directory on first initialization +if[not "true"~lower getenv`PYKX_LOADED_UNDER_Q; util.redirect:"\" 2>",$[util.os="w";"nul Python type util.toDefault:{ $[util.isconv x;(::); - "py"~util.defaultConv;topy; - "np"~util.defaultConv;tonp; - "pd"~util.defaultConv;topd; - "pa"~util.defaultConv;topa; - "k" ~util.defaultConv;tok; + "py" ~ util.defaultConv;topy; + "np" ~ util.defaultConv;tonp; + "pd" ~ util.defaultConv;topd; + "pa" ~ util.defaultConv;topa; + "k" ~ util.defaultConv;tok; + "raw" ~ util.defaultConv;toraw; + "default" ~ util.defaultConv;todefault; (::) ]x }; @@ -637,6 +641,48 @@ tok: {x y}(`..k;;) // ``` toraw: {x y}(`..raw;;) +// @name .pykx.todefault +// @category api +// @overview +// _Tag a q object to be indicate a raw conversion when called in Python_ +// +// ```q +// .pykx.todefault[qObject] +// ``` +// +// **Parameters:** +// +// name | type | description | +// ----------|---------|-------------| +// `qObject` | `any` | A q object which is to be converted to a default form in Python. | +// +// **Return:** +// +// type | description +// -------------|------------ +// `projection` | A projection which is used to indicate that once the q object is passed to Python for evaluation is should be treated as a raw object. | +// +// !!! Note +// The `todefault` conversion is used to match embedPy conversion logic, in particular it converts q lists to Python lists when dealing with contiguous datatypes rather than to nested single value array types. Additionally it converts q tables to Pandas DataFrames +// +// ```q +// // Denote that a q object once passed to Python should be managed as a Numpy object +// q).pykx.toraw til 10 +// enlist[`..raw;;][0 1 2 3 4 5 6 7 8 9] +// +// // Pass a q object to Python with default conversions and return type +// q).pykx.print .pykx.eval["lambda x: type(x)"] .pykx.tonp (til 10;til 10) +// +// +// // Pass a q object to Python treating the Python object as a raw Object +// q).pykx.print .pykx.eval["lambda x: type(x)"] .pykx.todefault (til 10;til 10) +// +// +// // Pass a q Table to Python treating the Python table as a Pandas DataFrame +// q) +// ``` +todefault:{$[0h=type x;toraw x;$[99h~type x;98h=type each(key x;value x);0b]|98h=type x;topd x;tonp x]} + // @kind function // @name .pykx.wrap // @category api @@ -745,6 +791,8 @@ unwrap:{$[util.isw x;$[104 105h~type each u:get x;(last u)`.;x`.];x]} // [Python](https://docs.python.org/3/library/datatypes.html) | `"py", "python", "Python"` | // [PyArrow](https://arrow.apache.org/docs/python/index.html) | `"pa", "pyarrow", "PyArrow"` | // [K](type_conversions.md) | `"k", "q"` | +// raw | `"raw"` | +// default | `"default"` | // // // ```q @@ -760,13 +808,16 @@ unwrap:{$[util.isw x;$[104 105h~type each u:get x;(last u)`.;x`.];x]} setdefault:{ x:lower x; util.defaultConv:$[ - x in ("np";"numpy");"np"; - x in ("py";"python");"py"; + x in ("np";"numpy") ;"np"; + x in ("py";"python") ;"py"; x in (enlist"k" ;enlist"q");"k"; - x in ("pd";"pandas");"pd"; - x in ("pa";"pyarrow");"pa"; + x in ("pd";"pandas") ;"pd"; + x in ("pa";"pyarrow") ;"pa"; + x in enlist["raw"] ;"raw"; + x in enlist "default" ;"default"; '"unknown conversion type: ",x - ] + ]; + setenv[`PYKX_DEFAULT_CONVERSION;$[-10h=type util.defaultConv;enlist;]util.defaultConv]; } // @kind function @@ -1175,7 +1226,7 @@ version:{pyexec"import pykx as kx";string qeval"kx.__version__"} // `::` | Returns null on successful execution // // ```q -// // Set a q array of guids using default behaviour +// // Set a q array of guids using default behavior // q).pykx.set[`test;3?0Ng] // q)print .pykx.get`test // [UUID('3d13cc9e-f7f1-c0ee-782c-5346f5f7b90e') @@ -1287,7 +1338,7 @@ version:{pyexec"import pykx as kx";string qeval"kx.__version__"} // q).pykx.pyexec"aclass = type('TestClass', (object,), {'x': pykx.LongAtom(3), 'y': pykx.toq('hello')})"; // q)a:.pykx.get`aclass // -// // Retrieve an existing attribute to show defined behaviour +// // Retrieve an existing attribute to show defined behavior // q)a[`:x]` // 3 // @@ -1313,7 +1364,7 @@ version:{pyexec"import pykx as kx";string qeval"kx.__version__"} // 0 0.493183 0a3e1784-0125-1b68-5ae7-962d49f2404d mi // 1 0.578520 5aecf7c8-abba-e288-5a58-0fb6656b5e69 ig // -// // Attempt to set an attribute against an object which does not support this behaviour +// // Attempt to set an attribute against an object which does not support this behavior // q)arr:.pykx.eval"[1, 2, 3]" // q).pykx.setattr[arr;`test;5] // 'AttributeError("'list' object has no attribute 'test'") @@ -1552,5 +1603,5 @@ console:{pyexec"pykx.console.PyConsole().interact(banner='', exitmsg='')"}; // needed to ensure loading PyKX multiple times does not result in unexpected errors finalise[]; -// @desc Restore context used at initialisation of script +// @desc Restore context used at initialization of script system"d ",string .pykx.util.prevCtx; diff --git a/src/pykx/pykx_init.q_ b/src/pykx/pykx_init.q_ index 44a30c625f25159c63ab0d312b0a117c30add204..cc4b1f908a44f173ec855ed39bf8a4ea4800f0a2 100644 GIT binary patch literal 3194 zcmWlbF=!jf8pja=d0%9nVx zYcqvGWSXrKZx(~9SZ@44kermkpej-t2L$(|YkVMx4+KwO%-c8p%zX3B|NH&_e8>ir z&(;e$gds%ZJW=%y zp(6xPqt!2R&N1P*WSSbrNWdc25XGD@oas$j!aB%>6DGi&aO1<$Sn?s40=v+dU{xnX zJ%G#;61!L|BqoNUPm4d_{SDN32jhGmW0P`fS`qZ79_(`Xf{To2iiZ&ouQUDT zOe-4!g+iz+e?v$JuAmU}ZtiNgTnMfH=~Ly2Z!fza*ulCj-?+NGU4v<{p@B&#IfOEq zYB~$B6r;dPj?_|6TC|}F7*SNl&1@C72`0F?YXLBAQ5k612o+?M&?E`8$PFVNNkhdV zA;h)U;X@j!^BzD~p2-sPDGrivs+qp~^s=K5{>(nO1WIk_x>Pz!Hk5Ax@9L_7vz(X* zk9H0&p3~~#+2P+u-`{%J&RgX`GZ?F(5%HD&o4<4_sukC2qY&Ox- z2Bugt>{iTZ_B}ZvOHMhIj5sIS(S}NtYqgWh-!^cBHSV}$;=J#5Thp6jYrk;MI-P>Z zz$(FiS2oVD>nFT<@Qf}bV;+NYYNQv_s``qTF}s1?e&lYO`JF%qgs}V{NzdV0cTt%Q zdyduZ5REC4v7Mu_+{WH0zuj-Lgh)l?3UZ*RDClrdltly>7`f)phyjd*BbY zMmI}mev&a{V$S9fv>RJc7@je>WkblSl0n`AEr1XJgAz9>)uDck%^BB6rprpH5*%TD zQa;`L*tjfPm1ASPNwqN|Mp@W;3*r^K0Mt#c>MP8XzgI7x^}Q}_mi)dj6^^n zp)?iD*Er@amd87WN~AL<#Ut<3T+#_n3>YTSm!vb5FXu3v_VbDCoC1P)SPge_md2}j>V?6dc9h;sAbN&;GifowhMe42*S1!(Zac z`q&V8n#VB|*hsVpBt$tIJEVQa=L?enO(9z}a!;_fjRXFu{!X7TT#&9aZ_$!mpWV*$ zj?Izb4zaz&rOBolKhDI-g3Vp%XtcQyZ49^P<9X}Qk;b*OIi@{{Z=Mgy1+;@~&n(t66T?`L~|Em`(|0#t%+CZn6P^y&3nMiW~w?y$g(UyaTqoK&FLt|QYXu6M57_z zLO1zj*N+l6|JvX%O1FE)d&Nd0Hrf3Ff&%+W}*FwAejUPXKVN7K~* zdZvQ%YKHWZG40<+(EihJj6iW#P~Mj<{*tI>5n>x=G#JStP0J9k+xPDmfWLcFu?B-8 zLT$`dr(|rEsKHJ3)N`5x==oIlq!7!V;@Ps7{*IF*w`$$a{&u4f+tIIgi!>VJu^24$ zTPJS7POs??n4x;NEVw2TF1kafJ81TL+qd`E6E7K58ZH#l4wM9r-At=c0GW0pU8uQI z*F=(fwk?bVe;48ey5vAGrgkG1Rd#_cH)rkTbdWi(l*^}|AHT6C^)?uR>mQZ77puQ~ z{_*+K>+Sz;U4x7|YFwTiAHHoXMEf!xgoA8_V<&(!$GM`B0*JpNwj4TwqQt{xgXmF6dvjNMYW42n_gBw$)^e+_zKEBQ6%st~ z_{CVOf$;p+3;IyvG;x%>LE1Mi4u0OqKVHxMyt#R_eP?^Sx_9^}9qGhPXo2eOaZ){k zdYrfut<@Y^vDFd}|BnYAriz?!Y|(^x9vp{PP9#qI=P$-8v0At)2!gA zEXr0>m$F|Rgo(x%%1Q&F>{vk|8e?-wmW5sWgfqnLd5%RRvay)W6Ea~?gK!wwV^vkh zSjvE(4z^l@z9EM&o#&c|U#j;n^7);$>bsZg-`B;qFetf5xNp8o>8^yua^=~>v%EwqmsC+uzMW?IfF9%R{7=b0+ElaKu8c{)E>XeCwi8_L^UwWRtoEV<- zYU(kJ8%Ypw%>W7DfRE>%po?r-$@qTR?ewGUpzNEmRryu5Icy}uWGFU>+>r8o9~+LQ zIo^VUQCWQ(MOfMqr_1hP{x$Jg^4-S@b*4&Z!fj=yb3Sk27?C=%!ZvCYwV`v$eV5{) zZ0zyrNVaPC(B9Kx=x7#44xd41a24aN^Gn4l#TkE8Lny`$!<=yqUs-sJv0-V?;##ov z89b4cW!@3Oh3{ezI~GclggdviJL)=LdIw+TZy41>G;kR|v$P z;%sd~#j&l=`Jz4(p^`L|RJP&oC%KCcC%LcpzI>?;*EBxCX`a4-$+9jT7*BKN)=miuFI*747K& literal 3124 zcmXArL1^Phm&e_iY`dknL^%XhN5deCgt~?3qElyEmeSP0U`7|6g0+P~r_ahI4Gq&h zV@q!8U2pnR&?m(SA}U!uyfXQdOpn?l{tA49JBza0~gv zp%nSaY>HE!oy0_yS&MZIClLb3l?rkRb#gXB`l4MHvLsQT$&4UW^?<1pn_`(^w22~= z5S&i$QuJ4;h=Ir5$K3O}GHC;z#UN%gd&SYQ;~<5ChlCM%EX>%Ltw2i|+F0F0rK_Ukx6d@{)!VOVe^XSD*uR&1jo20?&P8FO6J8d;)=M3E^2 zji6nvDgH(zxfg{q)?;rLMeJJ^)`qYhejgsX9nkj!9JVjGGAu^2wb%H;syx;zu*o6<@Ny#FdZ_*e9I?Kw zFljZD`o*Ytz!B3hE4|SrsYN!V=M z41}gQZ!4Bk2vyyu4QMl}MI2MJIVSvP=B2n-3+Syq^(G)#;7})PI>^K^)fdP`cDgA) z6$XC!Z4qIJOsMa z6FuF(qZ=<%l!6`*TL=MXjI%^TW*Amrr2-2Dq~h#C2U(ehBTa0eqc>k@l&0sE3**&Q zD|YABdD=sq_G;6GQha@RnS1zY?`v^)_onzmwezpyo}&{BaE`u84`2?9|q^A9lLAlg|G8`^(HqNe>0C634LM=57tz zQnn_))?+BjcxC>vW+3y~5JEq@hG1)2-7hshm8v_rUyo1!*#7wAFUQ;4H^4@=ydFpB zT%#;5YFO`+f1+xM*t%!?nr-|!7r!ZSDpMXu7_)pWA7hMc#uR}5y@55$>@RFw79=aK z#ltd$jQ0D6)Rzbm8A^BQP6+{R2_jPY(IA!;j#W)YI`?b_Fv0SeQZw=N^~$4uRuLpg z$vWw8!Fd7Z#XNb;hgVQ)RjjV@{Q0vo@DmLH6&Z8ax|Y!@ zY*XzU?qnh_z*74!4FRL08_WS*?FoxsvieA*1_wIFgA8}c#!Ot_Qx4Lx2a7iSiDg zLN{cn8fSn*eBr#MC-)lN5K1&GX<^%Vrnq7=i9XFI3tMN**~3nQrWF1C7w>bE^)bU; zk{pVa$GICG)`fUsj$4JuMfgaufbE6K*DRLMcnQnCgSO!s;M z%}i^{5|iy$$!B3|ZgIzNy$_L=RW{ zh#?H`>gDoleWCjEybvO@s?l%83lqSBE1n*si?+4>BZ<&;wY?a3*g2DAHY=44xIa-w zPlfyh=9;%x$MaFGg;pF$w5j!U>ac=&7Ct+pkT8-az_u$6@HKXqL{5?>H-z_2I~N*wcBF)9B13%Q#4*tb^*xs3eZ&oG;CQjKXm0WO`$RMb^EF zlFuuOn7l}1H-h+FC`HokAOQ^HS`qsADhoetl z-)wh^XFE67t$iGF;)A5}XHE2bJ;Rg$Ds`WgPOf)OuD_O!iwDQW{THQ6`OOAAmKxpT?@xKxQY?EBNjL)uB6{jCVa5k)cL}Uencg0|!Q1iF+;?+} z)uLDhvOVGEy{m4f=I}YCLZ#9kjWBg5x)NOcCseFZQ3e+F7|~RO4UTNdQw!?G_A%6m4ypIIETD&1-BBe!ggAnM!H@F`2Uf$#2EL@r60{O zueHRd{6ICOVI6R=;0~FYC+3^o%hGygDAd}ihTvq-JZE7V z!X3C({rl~!TeX4?eF<+i)}yt?(8g7A7H(m%xETRcLKoXtk6pA*L%q zFCWNRzJl_Mz1ljDMLKD<%VNta%f3IhS*DgYq*S)qZLil-G%F7+8G(sFFy~597Rq+6 zvITX!{BBZ{mXz57oxFJY@#pQA+YiOu@#mXd>GSFFyTfNL6q=TB;`x=83G8H^?!JF< zef;V}@xwol4?rn$qC&YxA5>kPp}uO`3Gf>&6Uc^PgCu?6ePp(+RcVEmfJY7mG*vSh t+a#VFVp)-r9!PMMJP5g1z)E`aU66q(K1n+1),xG,x->n); +static char* zs(K x) { + char* s=memcpy(malloc(x->n+1),x->G0,x->n); return s[x->n]=0,s; } @@ -93,9 +93,11 @@ EXPORT K k_pykx_init(K k_q_lib_path) { } EXPORT K k_init_python(K x, K y, K z) { - ZI i=0; - I f,g; - S l,h,hh; + static int i=0; + int f,g; + char* l; + char* h; + char* hh; K n,v; P a,b,pyhome; P(i,0)l=zs(x),h=zs(y),hh=zs(z); @@ -157,7 +159,7 @@ K k_py_error() { // Build a q error object with the repr of the exception value as its message. The full // traceback is provided as the cause to the QError that will be raised. P ex_repr = PyObject_CallMethod(ex_value, "__repr__", NULL); - K k = ks((S)PyUnicode_AsUTF8(ex_repr)); + K k = ks((char*)PyUnicode_AsUTF8(ex_repr)); k->t = -128; Py_XDECREF(ex_repr); @@ -309,8 +311,8 @@ EXPORT K k_pyrun(K k_ret, K k_eval_or_exec, K as_foreign, K k_code_string) { } -inline J modpow(J base, J exp, J mod) { - J result = 1; +inline long long modpow(long long base, long long exp, long long mod) { + long long result = 1; while (exp > 0) { if (exp & 1) result = (result * base) % mod; base = (base * base) % mod; @@ -337,7 +339,7 @@ EXPORT K k_modpow(K k_base, K k_exp, K k_mod_arg) { result->t = -128; } else { result = ktn(7, k_base->n); - for (J x = 0; x < k_base->n; ++x) kJ(result)[x] = modpow(kJ(k_base)[x], kJ(k_exp)[x], kJ(k_mod)[x]); + for (long long x = 0; x < k_base->n; ++x) kJ(result)[x] = modpow(kJ(k_base)[x], kJ(k_exp)[x], kJ(k_mod)[x]); } } else if (k_base->t >= 0 && k_exp->t >= 0) { if (k_base->n != k_exp->n) { @@ -346,7 +348,7 @@ EXPORT K k_modpow(K k_base, K k_exp, K k_mod_arg) { } else { result = ktn(7, k_base->n); - for (J x = 0; x < k_base->n; ++x) kJ(result)[x] = modpow(kJ(k_base)[x], kJ(k_exp)[x], k_mod->j); + for (long long x = 0; x < k_base->n; ++x) kJ(result)[x] = modpow(kJ(k_base)[x], kJ(k_exp)[x], k_mod->j); } } else if (k_base->t >= 0 && k_mod->t >= 0) { if (k_base->n != k_mod->n) { @@ -354,10 +356,10 @@ EXPORT K k_modpow(K k_base, K k_exp, K k_mod_arg) { result->t = -128; } result = ktn(7, k_base->n); - for (J x = 0; x < k_base->n; ++x) kJ(result)[x] = modpow(kJ(k_base)[x], k_exp->j, kJ(k_mod)[x]); + for (long long x = 0; x < k_base->n; ++x) kJ(result)[x] = modpow(kJ(k_base)[x], k_exp->j, kJ(k_mod)[x]); } else if (k_base->t >= 0) { result = ktn(7, k_base->n); - for (J x = 0; x < k_base->n; ++x) kJ(result)[x] = modpow(kJ(k_base)[x], k_exp->j, k_mod->j); + for (long long x = 0; x < k_base->n; ++x) kJ(result)[x] = modpow(kJ(k_base)[x], k_exp->j, k_mod->j); } else if (k_exp->t >= 0 && k_mod->t >= 0) { if (k_exp->n != k_mod->n) { result = ks("length"); @@ -365,14 +367,14 @@ EXPORT K k_modpow(K k_base, K k_exp, K k_mod_arg) { } else { result = ktn(7, k_exp->n); - for (J x = 0; x < k_exp->n; ++x) kJ(result)[x] = modpow(k_base->j, kJ(k_exp)[x], kJ(k_mod)[x]); + for (long long x = 0; x < k_exp->n; ++x) kJ(result)[x] = modpow(k_base->j, kJ(k_exp)[x], kJ(k_mod)[x]); } } else if (k_exp->t >= 0) { result = ktn(7, k_exp->n); - for (J x = 0; x < k_exp->n; ++x) kJ(result)[x] = modpow(k_base->j, kJ(k_exp)[x], k_mod->j); + for (long long x = 0; x < k_exp->n; ++x) kJ(result)[x] = modpow(k_base->j, kJ(k_exp)[x], k_mod->j); } else if (k_mod->t >= 0) { result = ktn(7, k_mod->n); - for (J x = 0; x < k_mod->n; ++x) kJ(result)[x] = modpow(k_base->j, k_exp->j, kJ(k_mod)[x]); + for (long long x = 0; x < k_mod->n; ++x) kJ(result)[x] = modpow(k_base->j, k_exp->j, kJ(k_mod)[x]); } else { result = kj(modpow(k_base->j, k_exp->j, k_mod->j)); } diff --git a/src/pykx/read.py b/src/pykx/read.py index 302a326..0fd5f25 100644 --- a/src/pykx/read.py +++ b/src/pykx/read.py @@ -15,6 +15,28 @@ def __dir__(): return __all__ +_type_mapping = { + 'List': "*", + 'GUID': "G", + 'Boolean': "B", + 'Byte': "X", + 'Short': "H", + 'Int': "I", + 'Long': "J", + 'Real': "E", + 'Float': "F", + 'Char': "C", + 'Symbol': "S", + 'Timestamp': "P", + 'Month': "M", + 'Date': "D", + 'Datetime': "Z", + 'Timespan': "N", + 'Minute': "U", + 'Second': "V", + 'Time': "T", +} + JSONKTypes = Union[ k.Table, k.Dictionary, k.BooleanAtom, k.BooleanVector, k.FloatAtom, k.FloatVector, k.CharVector, k.List @@ -27,6 +49,23 @@ class QReader: def __init__(self, q): self._q = q + def update_types(self, types): + upd_types = [] + for i in types: + t = str(i) + if len(t) == 1: + upd_types.append(i) + else: + found = False + for key in _type_mapping.keys(): + if key in t: + found = True + upd_types.append(_type_mapping[key]) + break + if not found: + raise TypeError(f'Unsupported type: {type(i)} supplied') + return upd_types + def csv(self, path: Union[str, Path, k.SymbolAtom], types: Optional[Union[bytes, k.CharAtom, k.CharVector]] = None, @@ -39,8 +78,9 @@ def csv(self, Parameters: path: The path to the CSV file. - types: A `str`-like object of uppercase characters representing the types. Space is - used to drop a column. If `None`, the types will be guessed using `.csvutil.info`. + types: Can be a dictionary of columns and their types or a `str`-like object of + uppercase characters representing the types. Space is used to drop a column. + If `None`, the types will be guessed using `.csvutil.info`. delimiter: A single character representing the delimiter between values. as_table: `True` if the first line of the CSV file should be treated as column names, in which case a `pykx.Table` is returned. If `False` a `pykx.List` of @@ -74,25 +114,41 @@ def csv(self, ```python table = q.read.csv('example.csv', None, None, False) ``` + + Read a comma separated CSV file specifying the type of the three columns + named `x1`, `x2` and `x3` to be of type `Integer`, `GUID` and `Timestamp`. + + ```python + table = q.read.csv('example.csv', {'x1':kx.IntAtom,'x2':kx.GUIDAtom,'x3':kx.TimestampAtom}) + ``` """ as_table = 'enlist' if as_table else '' - if types is None: + dict_conversion = None + if types is None or isinstance(types, dict): if not licensed: raise LicenseException('guess CSV column types') if isinstance(self._q, QConnection): raise ValueError('Cannot guess types of CSV columns over IPC.') + if isinstance(types, dict): + dict_conversion = types + types = None types = self._q.csvutil.info(k.SymbolAtom(path))['t'] elif isinstance(types, k.CharAtom): # Because of the conversion to `CharVector` later, converting the char atom to bytes # here essentially causes `types` to be enlisted without executing any q code. types = bytes(types) - return self._q( + elif isinstance(types, list): + types = self.update_types(types) + res = self._q( f'{{(x; {as_table} y) 0: hsym z}}', k.CharVector(types), k.CharAtom(delimiter), k.SymbolAtom(path), wait=True, ) + if dict_conversion is not None: + return res.astype(dict_conversion) + return res def splayed(self, root: Union[str, Path, k.SymbolAtom], diff --git a/src/pykx/reimporter.py b/src/pykx/reimporter.py index b3c9ac9..199500c 100644 --- a/src/pykx/reimporter.py +++ b/src/pykx/reimporter.py @@ -31,6 +31,7 @@ class PyKXReimport: """ def __init__(self): + self.defaultconv = str(os.getenv('PYKX_DEFAULT_CONVERSION')) self.pykxunderq = str(os.getenv('PYKX_UNDER_Q')) self.skipunderq = str(os.getenv('SKIP_UNDERQ')) self.underpython = str(os.getenv('UNDER_PYTHON')) @@ -48,6 +49,7 @@ def reset(self): Note: It is not reccomended to use this function directly instead use the `with` syntax. This will automatically manage setting and restoring the environment variables for you. """ + os.unsetenv("PYKX_DEFAULT_CONVERSION") os.unsetenv("PYKX_UNDER_Q") os.unsetenv("SKIP_UNDERQ") os.unsetenv("UNDER_PYTHON") @@ -61,6 +63,7 @@ def restore(self): Note: It is not reccomended to use this function directly instead use the `with` syntax. This will automatically manage setting and restoring the environment variables for you. """ + os.environ['PYKX_DEFAULT_CONVERSION'] = self.defaultconv os.environ['PYKX_UNDER_Q'] = self.pykxunderq os.environ['SKIP_UNDERQ'] = self.skipunderq os.environ['UNDER_PYTHON'] = self.underpython diff --git a/src/pykx/serialize.py b/src/pykx/serialize.py new file mode 100644 index 0000000..42066ed --- /dev/null +++ b/src/pykx/serialize.py @@ -0,0 +1,123 @@ +""" +Module to help with serializing K objects without copying the data. +""" +from typing import Any, Union + +from ._wrappers import _to_bytes, decref, deserialize as _deserialize +from .wrappers import K + + +class serialize: + def __init__(self, obj: Any, mode: int = 6, wait: int = 0): + """Helper class to manage making 0 copy serialized `K` objects. + + Parameters: + obj: The object to serialize. + mode: The [capability level](https://code.kx.com/q/basics/ipc/#handshake) + to use for serialization, defaluts to the maximum value of 6. + wait: The message type to use, defaults to 0. + + Note: The available message types to use are 0, 1, and 2. + - 0: async + - 1: sync + - 2: response\n + More information about the serialization of `K` objects can be found + [here](https://code.kx.com/pykx/2.0/user-guide/advanced/serialization.html). + + Note: To access the memory view of the serialized object you can use the `data` property. + If you need a copy of the data instead you can use the `copy` method. + + Warning: Passing just the `data` property of this class to a function may invalidate data. + This can be avoided by passing the whole `PyKXSerialized` object instead. + + Examples: + + Serializing a `K` object and copying the serialized data. + + ``` + >>> k_obj = kx.q('til 10') + >>> ser = kx.serialize(k_obj) + # The 0-copy memoryview of the data can be accessed through the `data` property + >>> ser.data + + # The underlying bytes can be copied with the `copy` method. + >>> k_obj_copy = ser.copy() + >>> k_obj_copy + b'\\x01\\x00\\x00\\x00^\\x00\\x00\\x00\\x07\\x00\\n\\x00\\x00...' + ``` + + You can also directly index into the serialized object. + + ``` + >>> k_obj = kx.q('til 10') + >>> ser = kx.serialize(k_obj) + >>> ser[0] + 1 + >>> bytes(ser[0:5]) + b'\\x01\\x00\\x00\\x00^' + ``` + """ + d = _to_bytes(mode, K(obj), wait) + self.data = d[1] + self._ptr = d[0] + + def __len__(self): + return self.data.__len__() + + def __getitem__(self, key): + return self.data[key] + + def __del__(self): + decref(self._ptr) + + def copy(self): + """Returns a copy of the bytes making up the serialized object. + + Examples: + + Serializing a `K` object and then copying the serialized data to a new variable. + + ``` + >>> k_obj = kx.q('til 10') + >>> ser = kx.serialize(k_obj) + >>> k_obj_copy = ser.copy() + >>> k_obj_copy + b'\\x01\\x00\\x00\\x00^\\x00\\x00\\x00\\x07\\x00\\n\\x00\\x00...' + ``` + """ + return bytes(self.data) + + +def deserialize(data: Union[bytes, serialize, memoryview]): + """Helper method to deserialize `K` objects from bytes. + + Parameters: + obj: The object to deserialize. + + Examples: + + Deserialize a serialized `K` object. + + ``` + >>> k_obj = kx.q('til 10') + >>> ser = kx.serialize(k_obj) + >>> kx.deserialize(ser) + pykx.LongVector(pykx.q('0 1 2 3 4 5 6 7 8 9')) + ``` + + You can also directly deserialize a bytes object. + + ``` + >>> k_obj = kx.q('til 10') + >>> ser = kx.serialize(k_obj).copy() + >>> ser + b'\\x01\\x00\\x00\\x00^\\x00\\x00\\x00\\x07\\x00\\n\\x00\\x00...' + >>> kx.deserialize(ser) + pykx.LongVector(pykx.q('0 1 2 3 4 5 6 7 8 9')) + ``` + """ + if isinstance(data, serialize): + return _deserialize(data.data.tobytes()) + elif isinstance(data, memoryview): + return _deserialize(data.tobytes()) + return _deserialize(data) diff --git a/src/pykx/system.py b/src/pykx/system.py index 640a7fc..f3b9ddf 100644 --- a/src/pykx/system.py +++ b/src/pykx/system.py @@ -1,6 +1,6 @@ """System command wrappers for PyKX.""" -from . import Q +from . import Q, wrappers as k from .exceptions import QError @@ -21,6 +21,9 @@ class SystemCommands: def __init__(self, q: Q): self._q = q + def __call__(self, x): + return self._q('{system x}', k.CharVector(x)) + def tables(self, namespace=None): """Lists the tables in the current namespace or in the provided namespace.""" if namespace is not None: diff --git a/src/pykx/toq.pyx b/src/pykx/toq.pyx index c71d1c7..5d72169 100644 --- a/src/pykx/toq.pyx +++ b/src/pykx/toq.pyx @@ -17,33 +17,54 @@ Examples: ```python >>> import pykx as kx +>>> import pandas as pd >>> kx.toq('grok') pykx.SymbolAtom(pykx.q('`grok')) >>> kx.toq('grok', ktype=kx.CharVector) pykx.CharVector(pykx.q('"grok"')) +>>> df = pd.DataFrame.from_dict({'x': [1, 2], 'y': ['a', 'b']}) +>>> kx.toq(df) +pykx.Table(pykx.q(' +x y +--- +1 a +2 b +')) +>>> kx.toq(df, ktype={'x': kx.CharVector}) +pykx.Table(pykx.q(' +x y +------ +,"1" a +,"2" b +')) ``` **Parameters:** -+---------------+--------------------------------+---------------------------------------+-------------+ -| **Name** | **Type** | **Description** | **Default** | -+===============+================================+=======================================+=============+ -| `x` | `Any` | A Python object which is to be | *required* | -| | | converted into a `pykx.K` object. | | -+---------------+--------------------------------+---------------------------------------+-------------+ -| `ktype` | `Optional[Union[pykx.K, int]]` | Desired `pykx.K` subclass (or type | `None` | -| | | number) for the returned value. If | | -| | | `None`, the type is inferred from | | -| | | `x`. | | -+---------------+--------------------------------+---------------------------------------+-------------+ -| `cast` | `bool` | Cast the input Python object to the | `False` | -| | | closest conforming Python type before | | -| | | converting to a `pykx.K` object. | | -+---------------+--------------------------------+---------------------------------------+-------------+ -| `handle_nulls | `bool` | Convert `pd.NaT` to corresponding q | `False` | -| | | null values in Pandas dataframes and | | -| | | Numpy arrays. | | -+---------------+--------------------------------+---------------------------------------+-------------+ ++---------------+---------------------------+---------------------------------------+-------------+ +| **Name** | **Type** | **Description** | **Default** | ++===============+===========================+=======================================+=============+ +| `x` | `Any` | A Python object which is to be | *required* | +| | | converted into a `pykx.K` object. | | ++---------------+---------------------------+---------------------------------------+-------------+ +| `ktype` | `Optional[Union[pykx.K,` | Desired `pykx.K` subclass (or type | `None` | +| | `int, dict]]` | number) for the returned value. If | | +| | | `None`, the type is inferred from | | +| | | `x`. If specified as a dictionary | | +| | | will convert tabular data based on | | +| | | mapping of column name to type. Note | | +| | | that dictionary based conversion is | | +| | | only supported when operating in | | +| | | licensed mode. | | ++---------------+---------------------------+---------------------------------------+-------------+ +| `cast` | `bool` | Cast the input Python object to the | `False` | +| | | closest conforming Python type before | | +| | | converting to a `pykx.K` object. | | ++---------------+---------------------------+---------------------------------------+-------------+ +| `handle_nulls | `bool` | Convert `pd.NaT` to corresponding q | `False` | +| | | null values in Pandas dataframes and | | +| | | Numpy arrays. | | ++---------------+---------------------------+---------------------------------------+-------------+ **Returns:** @@ -74,6 +95,7 @@ import re from types import ModuleType from typing import Any, Callable, Optional, Union from uuid import UUID, uuid4 as random_uuid +from warnings import warn import numpy as np import pandas as pd @@ -82,7 +104,7 @@ from . import wrappers as k from ._pyarrow import pyarrow as pa from .cast import * from . import config -from .config import find_core_lib, k_allocator, licensed, system +from .config import disable_pandas_warning, find_core_lib, k_allocator, licensed, pandas_2, system from .constants import INF_INT16, INF_INT32, INF_INT64, NULL_INT16, NULL_INT32, NULL_INT64 from .exceptions import LicenseException, PyArrowUnavailable, PyKXException, QError from .util import df_from_arrays, slice_to_range @@ -227,6 +249,8 @@ def _resolve_k_type(ktype: KType) -> Optional[k.K]: """Resolve the pykx.K type represented by the ktype parameter.""" if ktype is None: return None + elif isinstance(ktype, dict): + return ktype elif isinstance(ktype, int): try: return type_number_to_pykx_k_type[ktype] @@ -834,7 +858,8 @@ def from_list(x: list, cdef core.K kx = core.ktn(0, len(x)) for i, item in enumerate(x): # No good way to specify the ktype for nested types - (kx.G0)[i] = core.r1(_k(toq(item, cast=cast, handle_nulls=handle_nulls))) + kk = toq(item, cast=cast, handle_nulls=handle_nulls) + (kx.G0)[i] = core.r1(_k(kk)) res = factory(kx, False) if licensed: try: @@ -1248,7 +1273,7 @@ def from_numpy_ndarray(x: np.ndarray, return from_list(x.tolist(), ktype=k.List, cast=None, handle_nulls=None) raise _conversion_TypeError(x, repr('numpy.ndarray'), ktype) - cdef core.J n = x.size + cdef long long n = x.size cdef core.K kx = NULL cdef bytes as_bytes cdef uintptr_t data @@ -1358,14 +1383,34 @@ _size_to_nan = { } -def _to_numpy_or_categorical(x): +def _to_numpy_or_categorical(x, col_name=None, df=None): # Arrays taken from Pandas can come in many forms. If they come from Pandas series, arrays, or # indexes, then we need to set an appropriate value to fill in for `pd.NA`. if isinstance(x, np.ndarray): return x elif isinstance(x, (pd.Series, pd.Index)): if isinstance(x.values, pd.Categorical): - return from_pandas_categorical(x.values, name=x.name) + return from_pandas_categorical( + x.values, + name=col_name if pandas_2 and col_name is not None else x.name + ) + elif pandas_2 and x.dtype == np.dtype('datetime64[s]'): + if df is not None and col_name is not None: + if ( + '_PyKX_base_types' in df.attrs.keys() + and col_name in df.attrs['_PyKX_base_types'].keys() + ): + if df.attrs['_PyKX_base_types'][col_name] == 'MonthVector': + return _to_numpy_or_categorical(x.values.astype(np.dtype('kx, False) + if convert_dict == None: + return factory(kx, False) + return factory(kx, False).astype(convert_dict) def from_pandas_series(x: pd.Series, @@ -1503,11 +1566,17 @@ def from_pandas_series(x: pd.Series, return arr -_supported_pandas_index_types_via_numpy = ( - pd.core.indexes.base.Index, - pd.core.indexes.numeric.NumericIndex, - pd.core.indexes.extension.NDArrayBackedExtensionIndex, -) +if not pandas_2: + _supported_pandas_index_types_via_numpy = ( + pd.core.indexes.base.Index, + pd.core.indexes.numeric.NumericIndex, + pd.core.indexes.extension.NDArrayBackedExtensionIndex, + ) +else: + _supported_pandas_index_types_via_numpy = ( + pd.core.indexes.base.Index, + pd.core.indexes.extension.NDArrayBackedExtensionIndex, + ) def from_pandas_index(x: pd.Index, @@ -1580,6 +1649,7 @@ def from_pandas_categorical(x: pd.Categorical, name: The name of the resulting q enumeration. cast: Unused. handle_nulls: Unused. + Returns: An instance of pykx.EnumVector. """ @@ -1769,10 +1839,10 @@ def from_datetime_datetime(x: Any, ) -> k.TemporalFixedAtom: """Converts a `datetime.datetime` into an instance of a subclass of `pykx.TemporalFixedAtom`. - Note: Setting environment variable `KEEP_LOCAL_TIMES` will result in the use of local timezones not UTC time. - By default this function will convert any `datetime.datetime` objects with timezone + Note: Setting environment variable `KEEP_LOCAL_TIMES` will result in the use of local time zones not UTC time. + By default this function will convert any `datetime.datetime` objects with time zone information to UTC before converting it to `q`. If you set the environment vairable to 1, - true or True, then the objects with timezone information will not be converted to UTC and + true or True, then the objects with time zone information will not be converted to UTC and instead will be converted to `q` with no changes. Parameters: @@ -2494,8 +2564,6 @@ _converter_from_python_type = { pd.DataFrame: from_pandas_dataframe, pd.Series: from_pandas_series, pd.Index: from_pandas_index, - pd.core.indexes.numeric.Int64Index: from_pandas_index, - pd.core.indexes.numeric.Float64Index: from_pandas_index, pd.core.indexes.range.RangeIndex: from_pandas_index, pd.core.indexes.datetimes.DatetimeIndex: from_pandas_index, pd.core.indexes.multi.MultiIndex: from_pandas_index, @@ -2504,27 +2572,45 @@ _converter_from_python_type = { } +if not pandas_2: + _converter_from_python_type[pd.core.indexes.numeric.Int64Index] = from_pandas_index + _converter_from_python_type[pd.core.indexes.numeric.Float64Index] = from_pandas_index + + + class ToqModule(ModuleType): # TODO: `cast` should be set to False at the next major release (KXI-12945) def __call__(self, x: Any, ktype: Optional[KType] = None, *, cast: bool = None, handle_nulls: bool = False) -> k.K: ktype = _resolve_k_type(ktype) - if x is not None and ktype is not None \ - and issubclass(ktype, k.Vector) \ - and not hasattr(x, '__iter__') \ + check_ktype = False + try: + check_ktype = ktype is not None \ + and issubclass(ktype, k.Vector) + except TypeError: + check_ktype = False + + if x is not None and check_ktype \ + and not hasattr(x, '__iter__') \ and type(x) is not slice: x = [x] + ktype_conversion=False + try: + if ktype is not None and ktype in _converter_from_ktype: + converter = _converter_from_ktype[ktype] + ktype_conversion = True + except BaseException: + pass + if x is None: converter = from_none elif isinstance(x, type(pd.NaT)): converter = from_pandas_nat elif isinstance(x, k.K): converter = from_pykx_k - - elif ktype is not None and ktype in _converter_from_ktype: - converter = _converter_from_ktype[ktype] - + elif ktype_conversion: + pass else: if type(x) in _converter_from_python_type: converter = _converter_from_python_type[type(x)] @@ -2543,6 +2629,15 @@ class ToqModule(ModuleType): return self(x.tab, ktype=ktype, cast=cast, handle_nulls=handle_nulls) else: converter = _default_converter + if type(ktype)==dict: + if not licensed: + raise PyKXException("Use of dictionary based conversion unsupported in unlicensed mode") + if pa is not None: + if not type(x) in [pd.DataFrame, pa.Table]: + raise TypeError(f"'ktype' not supported as dictionary for {type(x)}") + else: + if not type(x) == pd.DataFrame: + raise TypeError(f"'ktype' not supported as dictionary for {type(x)}") return converter(x, ktype, cast=cast, handle_nulls=handle_nulls) diff --git a/src/pykx/wrappers.py b/src/pykx/wrappers.py index 62511d7..65adfe1 100644 --- a/src/pykx/wrappers.py +++ b/src/pykx/wrappers.py @@ -178,7 +178,7 @@ from . import _wrappers from ._pyarrow import pyarrow as pa -from .config import k_gc, licensed +from .config import k_gc, licensed, pandas_2 from .core import keval as _keval from .constants import INF_INT16, INF_INT32, INF_INT64, NULL_INT16, NULL_INT32, NULL_INT64 from .exceptions import LicenseException, PyArrowUnavailable, PyKXException, QError @@ -214,7 +214,7 @@ def _idx_to_k(key, n): raise IndexError('index out of range') elif isinstance(key, slice) and key.stop is None: # ensure slices have a stop set - # TODO: Ensure this produces index k objects from slices whose behaviour matches indexing + # TODO: Ensure this produces index k objects from slices whose behavior matches indexing # Python lists (KXI-9723). key = slice(key.start, n if (key.step or 1) > 0 else -1, @@ -980,7 +980,7 @@ def __ceil__(self): def _py_null_or_inf(self, default, raw: bool): if not raw and (self.is_null or self.is_inf): # By returning the wrapper around the q null/inf when a Python object is requested, we - # propagate q's behaviour around them - for better and for worse. Notably this ensures + # propagate q's behavior around them - for better and for worse. Notably this ensures # symmetric conversions. return self return default @@ -1218,6 +1218,32 @@ def pa(self, *, raw: bool = False, has_nulls: Optional[bool] = None): raise PyArrowUnavailable # nocov return pa.array(self.np(raw=raw, has_nulls=has_nulls)) + def apply(self, func, *args, **kwargs): + if not callable(func): + raise RuntimeError("Provided value 'func' is not callable") + + return q( + '{[f; data; args; kwargs] ' + ' func: $[.pykx.util.isw f;' + ' f[; pyarglist args; pykwargs kwargs];' + ' [' + ' if[0c[0];?[t;enlist(=;`i;(last;`i));0b;{x!x}cls];()]; + h + }''', console, self) + df = pd.read_json(qtab.py().decode("utf-8"), orient='records', + convert_dates=False, dtype=False) + if len(df) == 0: + columns = self.columns.py() + if len(columns)>console[1]: + columns = (lambda x: x[:console[1]-1] + ['...'] + [x[-1]])(columns) + df = pd.DataFrame(columns=columns) + else: + df.set_index(['pykxTableIndex'], inplace=True) + df.index.names = [''] + ht = CharVector(df.to_html()) + ht = q('''{[c;t;h] + $[c[0]",{reverse "," sv 3 cut reverse string x}[n]," rows × ", + {reverse "," sv 3 cut reverse string x}[count cols t]," columns

";h] + }''', console, self, ht).py().decode("utf-8") + return ht + class SplayedTable(Table): """Wrapper for q splayed tables.""" @@ -2399,6 +2478,48 @@ def pd(self, *, raw: bool = False, has_nulls: Optional[bool] = None): def py(self, *, raw: bool = False, has_nulls: Optional[bool] = None, stdlib: bool = True): raise NotImplementedError + def _repr_html_(self): + if not licensed: + return self.__repr__() + console = q.system.console_size.py() + qtab = q('''{[c;t] + n:count t; + cls:$[c[1]c[0];?[t;enlist(=;`i;(last;`i));0b;{x!x}cls];()]; + h + }''', console, self) + df = pd.read_json(qtab.py().decode("utf-8"), orient='records', + convert_dates=False, dtype=False) + if len(df) == 0: + columns = self.columns.py() + if len(columns)>console[1]: + columns = (lambda x: x[:console[1]-1] + ['...'] + [x[-1]])(columns) + df = pd.DataFrame(columns=columns) + else: + df.set_index(['pykxTableIndex'], inplace=True) + df.index.names = [''] + ht = CharVector(df.to_html()) + ht = q('''{[c;t;h] + $[c[0]",{reverse "," sv 3 cut reverse string x}[n]," rows × ", + {reverse "," sv 3 cut reverse string x}[count cols t]," columns

";h] + }''', console, self, ht).py().decode("utf-8") + return ht + class PartitionedTable(SplayedTable): """Wrapper for q partitioned tables.""" @@ -2427,6 +2548,70 @@ def pd(self, *, raw: bool = False, has_nulls: Optional[bool] = None): def py(self, *, raw: bool = False, has_nulls: Optional[bool] = None, stdlib: bool = True): raise NotImplementedError + def _repr_html_(self): + if not licensed: + return self.__repr__() + console = q.system.console_size.py() + qtab = q('''{[c;t] + t:value flip t; + if[not count .Q.pn t;.Q.cn get t]; + ps:sums .Q.pn t;n:last ps; + cls:$[c[1]=n;:.j.j $[c[1]=c[0];r:(); + if[fp~0;r:?[t;((=;.Q.pf;first .Q.pv);(<;`i;c[0]-1));0b;{x!x}cls]]; + if[fp>0; + r:?[t;enlist(in;.Q.pf;fp#.Q.pv);0b;{x!x}cls]; + r:r,?[t;((=;.Q.pf;.Q.pv fp);(<;`i;-1+c[0]-ps[fp-1]));0b;{x!x}cls]; + ]; + if[c[0]console[1]: + columns = (lambda x: x[:console[1]-1] + ['...'] + [x[-1]])(columns) + df = pd.DataFrame(columns=columns) + else: + df.set_index(['pykxTableIndex'], inplace=True) + df.index.names = [''] + ht = CharVector(df.to_html()) + ht = q('''{[c;t;h] + $[c[0]",{reverse "," sv 3 cut reverse string x}[n]," rows × ", + {reverse "," sv 3 cut reverse string x}[count cols t]," columns

";h] + }''', console, self, ht).py().decode("utf-8") + return ht + class Dictionary(Mapping): """Wrapper for q dictionaries, including regular dictionaries, and keyed tables.""" @@ -2455,6 +2640,46 @@ def __getitem__(self, key): _check_k_mapping_key(original_key, key, self._keys) return super().__getitem__(key) + def _repr_html_(self): + if not licensed: + return self.__repr__() + if 0 == len(self.keys()): + return '

Empty pykx.Dictionary: ' + q('.Q.s1', self).py().decode("utf-8") + '

' + console = q.system.console_size.py() + qtab = q('''{[c;d] + $[98h=type value d; + t:([] pykxDictionaryKeys:key d),'value d; + t:([] pykxDictionaryKeys:key d;pykxDictionaryValues:value d)]; + cls:$[c[1]",{reverse "," sv 3 cut reverse string x}[n]," keys

";h] + }''', console, self, ht).py().decode("utf-8") + return ht + def _idx_col_name_generator(): name = 'idx' @@ -2599,6 +2824,10 @@ def pd(self, *, raw: bool = False, has_nulls: Optional[bool] = None): vk = self._values._keys kvg = self._keys._values._unlicensed_getitem vvg = self._values._values._unlicensed_getitem + if len(self) == 0: + df = pd.DataFrame(columns=kk.py() + vk.py()) + df = df.set_index(kk.py()) + return df idx = [np.stack(kvg(i).np(raw=raw, has_nulls=has_nulls)).reshape(-1) for i in range(len(kk))] cols = [vvg(i).np(raw=raw, has_nulls=has_nulls) @@ -2607,14 +2836,18 @@ def pd(self, *, raw: bool = False, has_nulls: Optional[bool] = None): columns = idx + cols index = pd.Index(np.arange(len(self))) df = df_from_arrays(column_names, columns, index) - if not raw: - for i, col in enumerate(kk.py()): - if isinstance(kvg(i), EnumVector): - df[col] = df[col].astype('category') - for i, col in enumerate(vk.py()): - if isinstance(vvg(i), EnumVector): - df[col] = df[col].astype('category') + + _pykx_base_types = {} + for i, col in enumerate(kk.py()): + if not raw and isinstance(kvg(i), EnumVector): + df[col] = df[col].astype('category') + _pykx_base_types[col] = str(type(kvg(i))).split('.')[-1] + for i, col in enumerate(vk.py()): + if not raw and isinstance(vvg(i), EnumVector): + df[col] = df[col].astype('category') + _pykx_base_types[col] = str(type(vvg(i))).split('.')[-1] df.set_index(kk.py(), inplace=True) + df.attrs['_PyKX_base_types'] = _pykx_base_types return df def pa(self): @@ -2788,6 +3021,48 @@ def grouped(self, cols: Union[List, str] = ''): else: raise e + def _repr_html_(self): + if not licensed: + return self.__repr__() + keys = q('{cols key x}', self).py() + console = q.system.console_size.py() + qtab=q('''{[c;t] + n:count t:t; + cls:$[c[1]c[0];?[t;enlist(=;`i;(last;`i));0b;{x!x}cls];()]; + h + }''', console, self) + df = pd.read_json(qtab.py().decode("utf-8"), orient='records', + convert_dates=False, dtype=False) + columns = q('cols', self).py() + if len(keys)>=console[1]: + keys = keys[:console[1]-1] + if len(df) == 0: + if len(columns)>console[1]: + columns = (lambda x: x[:console[1]-1] + ['...'] + [x[-1]])(columns) + df = pd.DataFrame(columns=columns) + df.set_index(keys, inplace=True) + ht = CharVector(df.to_html()) + ht = q('''{[c;t;h] + $[c[0]",{reverse "," sv 3 cut reverse string x}[n]," rows × ", + {reverse "," sv 3 cut reverse string x}[count cols t]," columns

";h] + }''', console, self, ht).py().decode("utf-8") + return ht + class GroupbyTable(PandasAPI): @@ -3262,7 +3537,7 @@ def py(self, stdlib=None): """Turns the pointer stored within the Foreign back into a Python Object. Note: The resulting object is a reference to the same memory location as the initial object. - This can result in unexpected behaviour and it is recommended to only modify the + This can result in unexpected behavior and it is recommended to only modify the original python object passed into the `Foreign` """ return _wrappers.from_foreign_to_pyobject(self) diff --git a/tests/__init__.py b/tests/__init__.py index 65ffd69..6d31cca 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -15,7 +15,7 @@ # Addition of configuration toml used in testing # The configuration values set here are the default values for the PyKX so should not -# overwrite test behaviour +# overwrite test behavior config_file = open(Path.home()/".pykx.config", "w") config_content = {"default": {"PYKX_KEEP_LOCAL_TIMES", 0}} toml.dump(config_content, config_file) diff --git a/tests/qcumber_tests/conversions.quke b/tests/qcumber_tests/conversions.quke index 95fcb8b..2bb3f5a 100644 --- a/tests/qcumber_tests/conversions.quke +++ b/tests/qcumber_tests/conversions.quke @@ -40,7 +40,7 @@ feature default conversions before each t::.pykx.eval["lambda x: bytes(str(type(x)), 'utf-8')"][<]; after each - .pykx.setdefault["numpy"]; + .pykx.setdefault["default"]; should support python default expect python default .pykx.setdefault["python"]; @@ -49,6 +49,9 @@ feature default conversions expect numpy default .pykx.setdefault["numpy"]; .qu.compare[""; t til 10]; + expect differences in list support for default and numpy + all(t[.pykx.tonp (10?1f;10?1f)]like""; + t[.pykx.todefault (10?1f;10?1f)]like"") should support pandas default expect pandas default .pykx.setdefault["pandas"]; diff --git a/tests/qinit.q b/tests/qinit.q new file mode 100644 index 0000000..ab6678c --- /dev/null +++ b/tests/qinit.q @@ -0,0 +1 @@ +show til 10 diff --git a/tests/test_license.py b/tests/test_license.py index c55b620..0a5e526 100644 --- a/tests/test_license.py +++ b/tests/test_license.py @@ -9,7 +9,7 @@ from unittest.mock import patch -def test_initialisation_using_unlicensed_mode(tmp_path, q): +def test_initialization_using_unlicensed_mode(tmp_path, q): os.environ['QLIC'] = os.environ['QHOME'] = str(tmp_path.absolute()) os.environ['QARGS'] = '--unlicensed' import pykx as kx diff --git a/tests/test_pandas_api.py b/tests/test_pandas_api.py index d3851ca..acfe55f 100644 --- a/tests/test_pandas_api.py +++ b/tests/test_pandas_api.py @@ -25,10 +25,10 @@ def test_df_columns(q): def test_df_dtypes(q): - df = q('([] til 10; 10?0Ng; 10?1f;0f,til 9;10?("abc";"def"))') + df = q('([] til 10; 10?0Ng; 10?1f;0f,til 9;10?("abc";"def");10?1e)') assert all(df.dtypes.columns == ['columns', 'type']) assert q('{x~y}', - q('("kx.LongAtom";"kx.GUIDAtom";"kx.FloatAtom";"kx.List";"kx.CharVector")'), + q('("kx.LongAtom";"kx.GUIDAtom";"kx.FloatAtom";"kx.List";"kx.CharVector";"kx.RealAtom")'), # noqa: E501 df.dtypes['type']) diff --git a/tests/test_pykx.py b/tests/test_pykx.py index 66d8bc2..13f18dd 100644 --- a/tests/test_pykx.py +++ b/tests/test_pykx.py @@ -39,6 +39,23 @@ def test_qargs_q_flag(): assert kx.q('2 + 2') == 4 +@pytest.mark.isolate +def test_qinit_startup(): + # PyKX would not initialise appropriately if QINIT was set to a file containing show statement + os.environ['QINIT'] = 'tests/qinit.q' + import pykx as kx + assert kx.q('2 + 2') == 4 + + +@pytest.mark.isolate +def test_qinit_qq_startup(): + # PyKX would not initialise appropriately if q.q exists in QHOME containing a show statement + shutil.copy('tests/qinit.q', os.environ['QHOME']+'/q.q') + import pykx as kx + os.remove(os.environ['QHOME']+'/q.q') + assert kx.q('2 + 2') == 4 + + @disposable_env_only @pytest.mark.isolate def test_QHOME_symlinks(): diff --git a/tests/test_read.py b/tests/test_read.py index e42805a..3d771df 100644 --- a/tests/test_read.py +++ b/tests/test_read.py @@ -38,6 +38,21 @@ def test_read_csv(kx, q, tmp_csv_path_1, tmp_csv_path_2): assert isinstance(q.read.csv(tmp_csv_path_2, kx.CharAtom('J')), kx.Table) assert isinstance(q.read.csv(tmp_csv_path_2, b'J', b','), kx.Table) assert isinstance(q.read.csv(tmp_csv_path_2, kx.CharVector('J'), b',', False), kx.List) + assert isinstance(q.read.csv(tmp_csv_path_1, [kx.LongAtom, kx.LongAtom, kx.LongAtom]), kx.Table) + if not kx.licensed: + ctx = pytest.raises(kx.LicenseException) + elif isinstance(q, kx.QConnection): + ctx = pytest.raises(ValueError) + else: + ctx = nullcontext() + with ctx: + assert isinstance( + q.read.csv(tmp_csv_path_1, {'a': kx.LongAtom, 'b': kx.LongAtom, 'c': kx.LongAtom}), + kx.Table + ) + tab = q.read.csv(tmp_csv_path_1, [kx.LongAtom, ' ', kx.LongAtom]) + assert isinstance(tab, kx.Table) + assert len(tab.columns) == 2 @pytest.mark.ipc diff --git a/tests/test_repr_html_.ipynb b/tests/test_repr_html_.ipynb new file mode 100644 index 0000000..dbe7d75 --- /dev/null +++ b/tests/test_repr_html_.ipynb @@ -0,0 +1,15878 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "024e2a14-65bd-4ff2-8cf1-2319d6d84eb7", + "metadata": {}, + "outputs": [], + "source": [ + "import pykx as kx\n", + "from pykx import q\n", + "H = 10\n", + "W = 20\n", + "q.system.console_size = [H, W]" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "a38594f0-9df4-4bcf-9677-d5b165a87473", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
bgxhijefcspmdnuvtB...S
00b00000000-0000-000..0x000Nh00N0Ne0n\" \"0Np0Nm0Nd0Nn0Nu0Nv0Nt00b...
10b00000000-0000-000..0x000Nh10N0Ne0n\" \"0Np0Nm0Nd0Nn0Nu0Nv0Nt00b...
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "b g ..\n", + "-----------------..\n", + "0 00000000-0000-0..\n", + "0 00000000-0000-0..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Many datatypes\n", + "q('t:flip {(`$/:t)!2#/:(t:{x where not x in \" z\"}.Q.t)$\\\\:()}[]')\n", + "q('T:flip {(`$/:upper t)!2#/:enlist each 2#/:(t:{x where not x in \" z\"}.Q.t)$\\\\:()}[]')\n", + "q('wideManyDatatypes:t,\\'T')\n", + "display(q('wideManyDatatypes'))" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "91b9638b-e531-4ff9-a79e-99c60ad9c8fb", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a\n", + "-\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
02023.10.06
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a \n", + "----------\n", + "2023.10.06\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
02023.10.06
12023.10.05
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a \n", + "----------\n", + "2023.10.06\n", + "2023.10.05\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
02023.10.06
12023.10.05
22023.10.04
32023.10.03
42023.10.02
52023.10.01
62023.09.30
72023.09.29
82023.09.28
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a \n", + "----------\n", + "2023.10.06\n", + "2023.10.05\n", + "2023.10.04\n", + "2023.10.03\n", + "2023.10.02\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
02023.10.06
12023.10.05
22023.10.04
32023.10.03
42023.10.02
52023.10.01
62023.09.30
72023.09.29
82023.09.28
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a \n", + "----------\n", + "2023.10.06\n", + "2023.10.05\n", + "2023.10.04\n", + "2023.10.03\n", + "2023.10.02\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
02023.10.06
12023.10.05
22023.10.04
32023.10.03
42023.10.02
52023.10.01
62023.09.30
72023.09.29
......
102023.09.26
\n", + "

11 rows × 1 columns

" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a \n", + "----------\n", + "2023.10.06\n", + "2023.10.05\n", + "2023.10.04\n", + "2023.10.03\n", + "2023.10.02\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
02023.10.06
12023.10.05
22023.10.04
32023.10.03
42023.10.02
52023.10.01
62023.09.30
72023.09.29
......
112023.09.25
\n", + "

12 rows × 1 columns

" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a \n", + "----------\n", + "2023.10.06\n", + "2023.10.05\n", + "2023.10.04\n", + "2023.10.03\n", + "2023.10.02\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Single column table\n", + "q('singleColTab:([] a:.z.d-til 2000)')\n", + "display(q('0#singleColTab'))\n", + "display(q('1#singleColTab'))\n", + "display(q('2#singleColTab'))\n", + "display(q('9#singleColTab'))\n", + "display(q('10#singleColTab'))\n", + "display(q('11#singleColTab'))\n", + "display(q('12#singleColTab'))" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "042e7253-0cbd-4a4b-ab0a-91aeae661279", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
asym
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a sym\n", + "-----\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
asym
02023.10.06milglie
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a sym \n", + "------------------\n", + "2023.10.06 milglie\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
asym
02023.10.06milglie
12023.10.05igfbage
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a sym \n", + "------------------\n", + "2023.10.06 milglie\n", + "2023.10.05 igfbage\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
asym
02023.10.06milglie
12023.10.05igfbage
22023.10.04kaodhbe
32023.10.03bafclbi
42023.10.02kfhogjn
52023.10.01jecpaen
62023.09.30kfmohpi
72023.09.29lkklcoi
82023.09.28kfifpag
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a sym \n", + "------------------\n", + "2023.10.06 milglie\n", + "2023.10.05 igfbage\n", + "2023.10.04 kaodhbe\n", + "2023.10.03 bafclbi\n", + "2023.10.02 kfhogjn\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
asym
02023.10.06milglie
12023.10.05igfbage
22023.10.04kaodhbe
32023.10.03bafclbi
42023.10.02kfhogjn
52023.10.01jecpaen
62023.09.30kfmohpi
72023.09.29lkklcoi
.........
102023.09.26enfebeo
\n", + "

11 rows × 2 columns

" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a sym \n", + "------------------\n", + "2023.10.06 milglie\n", + "2023.10.05 igfbage\n", + "2023.10.04 kaodhbe\n", + "2023.10.03 bafclbi\n", + "2023.10.02 kfhogjn\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Multi column table\n", + "q('multiColTab:([] a:.z.d-til 2000; sym:2000?`7)')\n", + "display(q('0#multiColTab'))\n", + "display(q('1#multiColTab'))\n", + "display(q('2#multiColTab'))\n", + "display(q('10#multiColTab'))\n", + "display(q('11#multiColTab'))" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "6e2ce31a-6bbb-440d-9577-b6615f8aec9d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19
00000000000000000000
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19
00000000000000000000
11111111111111111111
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19
00000000000000000000
11111111111111111111
22222222222222222222
33333333333333333333
44444444444444444444
55555555555555555555
66666666666666666666
77777777777777777777
88888888888888888888
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "2 2 2 2 ..\n", + "3 3 3 3 ..\n", + "4 4 4 4 ..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19
00000000000000000000
11111111111111111111
22222222222222222222
33333333333333333333
44444444444444444444
55555555555555555555
66666666666666666666
77777777777777777777
............................................................
1010101010101010101010101010101010101010
\n", + "

11 rows × 19 columns

" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "2 2 2 2 ..\n", + "3 3 3 3 ..\n", + "4 4 4 4 ..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "q('n:-1+last system\"c\";extraWide:flip (`$\"col\",/:string 1+til n)!n#enlist til 1000')\n", + "display(q('0#extraWide'))\n", + "display(q('1#extraWide'))\n", + "display(q('2#extraWide'))\n", + "display(q('10#extraWide'))\n", + "display(q('11#extraWide'))" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "3f579d0a-5da6-4141-921b-a5150a349632", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19col20
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19col20
000000000000000000000
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19col20
000000000000000000000
111111111111111111111
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19col20
000000000000000000000
111111111111111111111
222222222222222222222
333333333333333333333
444444444444444444444
555555555555555555555
666666666666666666666
777777777777777777777
888888888888888888888
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "2 2 2 2 ..\n", + "3 3 3 3 ..\n", + "4 4 4 4 ..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19col20
000000000000000000000
111111111111111111111
222222222222222222222
333333333333333333333
444444444444444444444
555555555555555555555
666666666666666666666
777777777777777777777
...............................................................
101010101010101010101010101010101010101010
\n", + "

11 rows × 20 columns

" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "2 2 2 2 ..\n", + "3 3 3 3 ..\n", + "4 4 4 4 ..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "q('n:last system\"c\";extraWide:flip (`$\"col\",/:string 1+til n)!n#enlist til 1000')\n", + "display(q('0#extraWide'))\n", + "display(q('1#extraWide'))\n", + "display(q('2#extraWide'))\n", + "display(q('10#extraWide'))\n", + "display(q('11#extraWide'))" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "cec04d13-61ed-4b40-9bdb-a9685f1e5473", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19...col21
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19...col21
00000000000000000000...0
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19...col21
00000000000000000000...0
11111111111111111111...1
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19...col21
00000000000000000000...0
11111111111111111111...1
22222222222222222222...2
33333333333333333333...3
44444444444444444444...4
55555555555555555555...5
66666666666666666666...6
77777777777777777777...7
88888888888888888888...8
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "2 2 2 2 ..\n", + "3 3 3 3 ..\n", + "4 4 4 4 ..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19...col21
00000000000000000000...0
11111111111111111111...1
22222222222222222222...2
33333333333333333333...3
44444444444444444444...4
55555555555555555555...5
66666666666666666666...6
77777777777777777777...7
..................................................................
1010101010101010101010101010101010101010...10
\n", + "

11 rows × 21 columns

" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "2 2 2 2 ..\n", + "3 3 3 3 ..\n", + "4 4 4 4 ..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "q('n:1+last system\"c\";extraWide:flip (`$\"col\",/:string 1+til n)!n#enlist til 1000')\n", + "display(q('0#extraWide'))\n", + "display(q('1#extraWide'))\n", + "display(q('2#extraWide'))\n", + "display(q('10#extraWide'))\n", + "display(q('11#extraWide'))" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "665c64b2-6fc4-4d9d-9f30-91dde0128edd", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19...col70
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19...col70
00000000000000000000...0
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19...col70
00000000000000000000...0
11111111111111111111...1
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19...col70
00000000000000000000...0
11111111111111111111...1
22222222222222222222...2
33333333333333333333...3
44444444444444444444...4
55555555555555555555...5
66666666666666666666...6
77777777777777777777...7
88888888888888888888...8
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "2 2 2 2 ..\n", + "3 3 3 3 ..\n", + "4 4 4 4 ..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19...col70
00000000000000000000...0
11111111111111111111...1
22222222222222222222...2
33333333333333333333...3
44444444444444444444...4
55555555555555555555...5
66666666666666666666...6
77777777777777777777...7
..................................................................
1010101010101010101010101010101010101010...10
\n", + "

11 rows × 70 columns

" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "2 2 2 2 ..\n", + "3 3 3 3 ..\n", + "4 4 4 4 ..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "q('n:50+last system\"c\";extraWide:flip (`$\"col\",/:string 1+til n)!n#enlist til 1000')\n", + "display(q('0#extraWide'))\n", + "display(q('1#extraWide'))\n", + "display(q('2#extraWide'))\n", + "display(q('10#extraWide'))\n", + "display(q('11#extraWide'))" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "c1d95dd3-53e7-46a3-a58f-e4120e943ca4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
...col70
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19
" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
...col70
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19
0000000000000000000...0
" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
...col70
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19
0000000000000000000...0
1111111111111111111...1
" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
...col70
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19
0000000000000000000...0
1111111111111111111...1
2222222222222222222...2
3333333333333333333...3
4444444444444444444...4
5555555555555555555...5
6666666666666666666...6
7777777777777777777...7
8888888888888888888...8
" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "2 2 2 2 ..\n", + "3 3 3 3 ..\n", + "4 4 4 4 ..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
...col70
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19
0000000000000000000...0
1111111111111111111...1
2222222222222222222...2
3333333333333333333...3
4444444444444444444...4
5555555555555555555...5
6666666666666666666...6
7777777777777777777...7
...............................................................
10101010101010101010101010101010101010...10
\n", + "

11 rows × 70 columns

" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "2 2 2 2 ..\n", + "3 3 3 3 ..\n", + "4 4 4 4 ..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#Many keys\n", + "display(q('(-1+last system\"c\")!0#extraWide'))\n", + "display(q('(-1+last system\"c\")!1#extraWide'))\n", + "display(q('(-1+last system\"c\")!2#extraWide'))\n", + "display(q('(-1+last system\"c\")!10#extraWide'))\n", + "display(q('(-1+last system\"c\")!11#extraWide'))" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "859af5e6-3958-41b7-8ce9-6300f82e3e83", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
...col70
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19
" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
...col70
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19
0000000000000000000...0
" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
...col70
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19
0000000000000000000...0
1111111111111111111...1
" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
...col70
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19
0000000000000000000...0
1111111111111111111...1
2222222222222222222...2
3333333333333333333...3
4444444444444444444...4
5555555555555555555...5
6666666666666666666...6
7777777777777777777...7
8888888888888888888...8
" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "2 2 2 2 ..\n", + "3 3 3 3 ..\n", + "4 4 4 4 ..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
...col70
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19
0000000000000000000...0
1111111111111111111...1
2222222222222222222...2
3333333333333333333...3
4444444444444444444...4
5555555555555555555...5
6666666666666666666...6
7777777777777777777...7
...............................................................
10101010101010101010101010101010101010...10
\n", + "

11 rows × 70 columns

" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "2 2 2 2 ..\n", + "3 3 3 3 ..\n", + "4 4 4 4 ..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "display(q('(last system\"c\")!0#extraWide'))\n", + "display(q('(last system\"c\")!1#extraWide'))\n", + "display(q('(last system\"c\")!2#extraWide'))\n", + "display(q('(last system\"c\")!10#extraWide'))\n", + "display(q('(last system\"c\")!11#extraWide'))" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "6b4c6689-8677-4f84-86b6-9dcb81b8a3f7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
...col70
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19
" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
...col70
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19
0000000000000000000...0
" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
...col70
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19
0000000000000000000...0
1111111111111111111...1
" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
...col70
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19
0000000000000000000...0
1111111111111111111...1
2222222222222222222...2
3333333333333333333...3
4444444444444444444...4
5555555555555555555...5
6666666666666666666...6
7777777777777777777...7
8888888888888888888...8
" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "2 2 2 2 ..\n", + "3 3 3 3 ..\n", + "4 4 4 4 ..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
...col70
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19
0000000000000000000...0
1111111111111111111...1
2222222222222222222...2
3333333333333333333...3
4444444444444444444...4
5555555555555555555...5
6666666666666666666...6
7777777777777777777...7
...............................................................
10101010101010101010101010101010101010...10
\n", + "

11 rows × 70 columns

" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "2 2 2 2 ..\n", + "3 3 3 3 ..\n", + "4 4 4 4 ..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "display(q('(1+last system\"c\")!0#extraWide'))\n", + "display(q('(1+last system\"c\")!1#extraWide'))\n", + "display(q('(1+last system\"c\")!2#extraWide'))\n", + "display(q('(1+last system\"c\")!10#extraWide'))\n", + "display(q('(1+last system\"c\")!11#extraWide'))" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "2381d3da-dff2-4bbc-8e70-95c1c2342922", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "

Empty pykx.Dictionary: ()!()

" + ], + "text/plain": [ + "pykx.Dictionary(pykx.q(''))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
b2
" + ], + "text/plain": [ + "pykx.Dictionary(pykx.q('b| 2'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a1
b2
" + ], + "text/plain": [ + "pykx.Dictionary(pykx.q('\n", + "a| 1\n", + "b| 2\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
bahmjm0
jjbkce1
ihmiil2
cobokk3
edjipe4
kegfkl5
pmifbc6
dgchig7
efjoab8
kkbama9
" + ], + "text/plain": [ + "pykx.Dictionary(pykx.q('\n", + "bahmjm| 0\n", + "jjbkce| 1\n", + "ihmiil| 2\n", + "cobokk| 3\n", + "edjipe| 4\n", + "kegfkl| 5\n", + "pmifbc| 6\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
gdbeam0
fffcoh1
jhkpmf2
abggec3
lmjikf4
ihnkfc5
iflcka6
fclmkn7
hhfkaj8
......
\n", + "

11 keys

" + ], + "text/plain": [ + "pykx.Dictionary(pykx.q('\n", + "gdbeam| 0\n", + "fffcoh| 1\n", + "jhkpmf| 2\n", + "abggec| 3\n", + "lmjikf| 4\n", + "ihnkfc| 5\n", + "iflcka| 6\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Dictionaries \n", + "display(q('()!()'))\n", + "display(q('(enlist `b)!(enlist 2)'))\n", + "display(q('(`a`b)!(1 2)'))\n", + "display(q('(10?`6)!(til 10)'))\n", + "display(q('(11?`6)!(til 11)'))" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "023538af-7a1c-4a8c-a36a-7bb38d5f0a3b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
b1
" + ], + "text/plain": [ + "pykx.Dictionary(pykx.q('\n", + " | a\n", + "-| -\n", + "b| 1\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ab
b12
" + ], + "text/plain": [ + "pykx.Dictionary(pykx.q('\n", + " | a b\n", + "-| ---\n", + "b| 1 2\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ab
b12
" + ], + "text/plain": [ + "pykx.Dictionary(pykx.q('\n", + " | a b\n", + "-| ---\n", + "b| 1 2\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "display(q('(enlist `b)!([] a:enlist 1)'))\n", + "display(q('(enlist `b)!([] a:enlist 1;b:enlist 2)'))\n", + "display(q('(enlist `b)!([] a:enlist 1;b:enlist 2)'))" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "9a8066f1-7e6d-453a-86f5-87d3fa3ec4eb", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col0col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18
nedelj0000000000000000000
lmlfnb1111111111111111111
modehh2222222222222222222
gpknga3333333333333333333
hidmlp4444444444444444444
dfaegp5555555555555555555
ekbajm6666666666666666666
lomgdc7777777777777777777
dolemm8888888888888888888
" + ], + "text/plain": [ + "pykx.Dictionary(pykx.q('\n", + " | col0 col1..\n", + "------| ---------..\n", + "nedelj| 0 0 ..\n", + "lmlfnb| 1 1 ..\n", + "modehh| 2 2 ..\n", + "gpknga| 3 3 ..\n", + "hidmlp| 4 4 ..\n", + "dfaegp| 5 5 ..\n", + "ekbajm| 6 6 ..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col0col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17...col19
kngolp000000000000000000...0
hpengg111111111111111111...1
hjgfdn222222222222222222...2
okdjpp333333333333333333...3
iccnpe444444444444444444...4
pafmko555555555555555555...5
igiofo666666666666666666...6
pjgeho777777777777777777...7
filmhn888888888888888888...8
fpkagh999999999999999999...9
" + ], + "text/plain": [ + "pykx.Dictionary(pykx.q('\n", + " | col0 col1..\n", + "------| ---------..\n", + "kngolp| 0 0 ..\n", + "hpengg| 1 1 ..\n", + "hjgfdn| 2 2 ..\n", + "okdjpp| 3 3 ..\n", + "iccnpe| 4 4 ..\n", + "pafmko| 5 5 ..\n", + "igiofo| 6 6 ..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col0col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17...col20
ghckdi000000000000000000...0
colako111111111111111111...1
pdpkjj222222222222222222...2
dpaaom333333333333333333...3
cboooo444444444444444444...4
cobfma555555555555555555...5
daeknb666666666666666666...6
ngjcga777777777777777777...7
mbnood888888888888888888...8
...............................................................
\n", + "

11 keys

" + ], + "text/plain": [ + "pykx.Dictionary(pykx.q('\n", + " | col0 col1..\n", + "------| ---------..\n", + "ghckdi| 0 0 ..\n", + "colako| 1 1 ..\n", + "pdpkjj| 2 2 ..\n", + "dpaaom| 3 3 ..\n", + "cboooo| 4 4 ..\n", + "cobfma| 5 5 ..\n", + "daeknb| 6 6 ..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "display(q('(9?`6)!flip (`$\"col\",/:string til 19)!(19#enlist til 9)'))\n", + "display(q('(10?`6)!flip (`$\"col\",/:string til 20)!(20#enlist til 10)'))\n", + "display(q('(11?`6)!flip (`$\"col\",/:string til 21)!(21#enlist til 11)'))" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "9a332b6f-9b72-4b60-b12f-f13c0fc1fec4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
sym
" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "sym| a\n", + "---| -\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
sym
amlcebj2023.10.06
" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "sym | a \n", + "-------| ----------\n", + "amlcebj| 2023.10.06\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
sym
amlcebj2023.10.06
kmdgghe2023.10.05
" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "sym | a \n", + "-------| ----------\n", + "amlcebj| 2023.10.06\n", + "kmdgghe| 2023.10.05\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
sym
amlcebj2023.10.06
kmdgghe2023.10.05
echhjlb2023.10.04
ikoceld2023.10.03
jdfkhoj2023.10.02
akeedab2023.10.01
bgpfgcf2023.09.30
jchgdgo2023.09.29
caniemd2023.09.28
" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "sym | a \n", + "-------| ----------\n", + "amlcebj| 2023.10.06\n", + "kmdgghe| 2023.10.05\n", + "echhjlb| 2023.10.04\n", + "ikoceld| 2023.10.03\n", + "jdfkhoj| 2023.10.02\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
sym
amlcebj2023.10.06
kmdgghe2023.10.05
echhjlb2023.10.04
ikoceld2023.10.03
jdfkhoj2023.10.02
akeedab2023.10.01
bgpfgcf2023.09.30
jchgdgo2023.09.29
......
kebpbjf2023.09.26
\n", + "

11 rows × 2 columns

" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "sym | a \n", + "-------| ----------\n", + "amlcebj| 2023.10.06\n", + "kmdgghe| 2023.10.05\n", + "echhjlb| 2023.10.04\n", + "ikoceld| 2023.10.03\n", + "jdfkhoj| 2023.10.02\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Single Key\n", + "q('singleKeyTab:`sym xkey ([] a:.z.d-til 2000; sym:2000?`7)')\n", + "display(q('0#singleKeyTab'))\n", + "display(q('1#singleKeyTab'))\n", + "display(q('2#singleKeyTab'))\n", + "display(q('10#singleKeyTab'))\n", + "display(q('11#singleKeyTab'))" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "d2b77659-58cb-4c62-9639-b53590a3fd2b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
symblah
" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "sym blah| a\n", + "--------| -\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
symblah
almhhdb9294892023.10.06
" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "sym blah | a..\n", + "--------------| -..\n", + "almhhdb 929489| 2..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
symblah
almhhdb9294892023.10.06
makdpab648922023.10.05
" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "sym blah | a..\n", + "--------------| -..\n", + "almhhdb 929489| 2..\n", + "makdpab 64892 | 2..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
symblah
almhhdb9294892023.10.06
makdpab648922023.10.05
ppniapd4699152023.10.04
bkjcbfb2805912023.10.03
afpcfih7645862023.10.02
pgeldjj3862822023.10.01
okjmalh1771512023.09.30
oolming9319832023.09.29
emfambc5222722023.09.28
" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "sym blah | a..\n", + "--------------| -..\n", + "almhhdb 929489| 2..\n", + "makdpab 64892 | 2..\n", + "ppniapd 469915| 2..\n", + "bkjcbfb 280591| 2..\n", + "afpcfih 764586| 2..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
symblah
almhhdb9294892023.10.06
makdpab648922023.10.05
ppniapd4699152023.10.04
bkjcbfb2805912023.10.03
afpcfih7645862023.10.02
pgeldjj3862822023.10.01
okjmalh1771512023.09.30
oolming9319832023.09.29
.........
fiihlfa2249342023.09.26
\n", + "

11 rows × 3 columns

" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "sym blah | a..\n", + "--------------| -..\n", + "almhhdb 929489| 2..\n", + "makdpab 64892 | 2..\n", + "ppniapd 469915| 2..\n", + "bkjcbfb 280591| 2..\n", + "afpcfih 764586| 2..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Multi Key\n", + "q('multiKeyTab:`sym`blah xkey ([] a:.z.d-til 2000; sym:2000?`7;blah:-2000?1000000)')\n", + "display(q('0#multiKeyTab'))\n", + "display(q('1#multiKeyTab'))\n", + "display(q('2#multiKeyTab'))\n", + "display(q('10#multiKeyTab'))\n", + "display(q('11#multiKeyTab'))" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "9e211e82-eb45-4f48-9a16-a2b706ae4269", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
symblah
almhhdb9294892023-10-06
makdpab648922023-10-05
ppniapd4699152023-10-04
bkjcbfb2805912023-10-03
afpcfih7645862023-10-02
pgeldjj3862822023-10-01
okjmalh1771512023-09-30
oolming9319832023-09-29
emfambc5222722023-09-28
denjgia1539922023-09-27
fiihlfa2249342023-09-26
\n", + "
" + ], + "text/plain": [ + " a\n", + "sym blah \n", + "almhhdb 929489 2023-10-06\n", + "makdpab 64892 2023-10-05\n", + "ppniapd 469915 2023-10-04\n", + "bkjcbfb 280591 2023-10-03\n", + "afpcfih 764586 2023-10-02\n", + "pgeldjj 386282 2023-10-01\n", + "okjmalh 177151 2023-09-30\n", + "oolming 931983 2023-09-29\n", + "emfambc 522272 2023-09-28\n", + "denjgia 153992 2023-09-27\n", + "fiihlfa 224934 2023-09-26" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "q('11#multiKeyTab').pd()" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "eb79402d-0bf6-40b2-88bc-cd127a4f9a93", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "a\n", + "-\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
02023.10.06
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "a \n", + "----------\n", + "2023.10.06\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
02023.10.06
12023.10.05
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "a \n", + "----------\n", + "2023.10.06\n", + "2023.10.05\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
02023.10.06
12023.10.05
22023.10.04
32023.10.03
42023.10.02
52023.10.01
62023.09.30
72023.09.29
82023.09.28
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "a \n", + "----------\n", + "2023.10.06\n", + "2023.10.05\n", + "2023.10.04\n", + "2023.10.03\n", + "2023.10.02\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
02023.10.06
12023.10.05
22023.10.04
32023.10.03
42023.10.02
52023.10.01
62023.09.30
72023.09.29
......
102023.09.26
\n", + "

11 rows × 1 columns

" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "a \n", + "----------\n", + "2023.10.06\n", + "2023.10.05\n", + "2023.10.04\n", + "2023.10.03\n", + "2023.10.02\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Single column splay table\n", + "display(q('{x set 0#([] a:.z.d-til 2000);get x}`:singleColSplay/'))\n", + "display(q('{x set 1#([] a:.z.d-til 2000);get x}`:singleColSplay/'))\n", + "display(q('{x set 2#([] a:.z.d-til 2000);get x}`:singleColSplay/'))\n", + "display(q('{x set 10#([] a:.z.d-til 2000);get x}`:singleColSplay/'))\n", + "display(q('{x set 11#([] a:.z.d-til 2000);get x}`:singleColSplay/'))" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "2de510a0-a719-40ae-a652-7c77d953878d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ab
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "a b\n", + "---\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ab
02023.10.060
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "a b\n", + "------------\n", + "2023.10.06 0\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ab
02023.10.060
12023.10.051
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "a b\n", + "------------\n", + "2023.10.06 0\n", + "2023.10.05 1\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ab
02023.10.060
12023.10.051
22023.10.042
32023.10.033
42023.10.024
52023.10.015
62023.09.306
72023.09.297
82023.09.288
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "a b\n", + "------------\n", + "2023.10.06 0\n", + "2023.10.05 1\n", + "2023.10.04 2\n", + "2023.10.03 3\n", + "2023.10.02 4\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ab
02023.10.060
12023.10.051
22023.10.042
32023.10.033
42023.10.024
52023.10.015
62023.09.306
72023.09.297
.........
102023.09.2610
\n", + "

11 rows × 2 columns

" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "a b\n", + "------------\n", + "2023.10.06 0\n", + "2023.10.05 1\n", + "2023.10.04 2\n", + "2023.10.03 3\n", + "2023.10.02 4\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Multi column splay\n", + "display(q('{x set 0#([] a:.z.d-til 2000; b:til 2000);get x}`:multiColSplay/'))\n", + "display(q('{x set 1#([] a:.z.d-til 2000; b:til 2000);get x}`:multiColSplay/'))\n", + "display(q('{x set 2#([] a:.z.d-til 2000; b:til 2000);get x}`:multiColSplay/'))\n", + "display(q('{x set 10#([] a:.z.d-til 2000; b:til 2000);get x}`:multiColSplay/'))\n", + "display(q('{x set 11#([] a:.z.d-til 2000; b:til 2000);get x}`:multiColSplay/'))" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "403f400e-13cf-43d0-b611-3eca677b7c3d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19
00000000000000000000
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19
00000000000000000000
11111111111111111111
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19
00000000000000000000
11111111111111111111
22222222222222222222
33333333333333333333
44444444444444444444
55555555555555555555
66666666666666666666
77777777777777777777
88888888888888888888
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "2 2 2 2 ..\n", + "3 3 3 3 ..\n", + "4 4 4 4 ..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19
00000000000000000000
11111111111111111111
22222222222222222222
33333333333333333333
44444444444444444444
55555555555555555555
66666666666666666666
77777777777777777777
............................................................
1010101010101010101010101010101010101010
\n", + "

11 rows × 19 columns

" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "2 2 2 2 ..\n", + "3 3 3 3 ..\n", + "4 4 4 4 ..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "q('n:-1+last system\"c\";extraWide:flip (`$\"col\",/:string 1+til n)!n#enlist til 1000')\n", + "display(q('{x set y;get x}[`:multiColSplay/]0#extraWide'))\n", + "display(q('{x set y;get x}[`:multiColSplay/]1#extraWide'))\n", + "display(q('{x set y;get x}[`:multiColSplay/]2#extraWide'))\n", + "display(q('{x set y;get x}[`:multiColSplay/]10#extraWide'))\n", + "display(q('{x set y;get x}[`:multiColSplay/]11#extraWide'))" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "dbc7da0f-7ccd-4356-9a6b-975e0953591e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19col20
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19col20
000000000000000000000
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19col20
000000000000000000000
111111111111111111111
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19col20
000000000000000000000
111111111111111111111
222222222222222222222
333333333333333333333
444444444444444444444
555555555555555555555
666666666666666666666
777777777777777777777
888888888888888888888
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "2 2 2 2 ..\n", + "3 3 3 3 ..\n", + "4 4 4 4 ..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19col20
000000000000000000000
111111111111111111111
222222222222222222222
333333333333333333333
444444444444444444444
555555555555555555555
666666666666666666666
777777777777777777777
...............................................................
101010101010101010101010101010101010101010
\n", + "

11 rows × 20 columns

" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "2 2 2 2 ..\n", + "3 3 3 3 ..\n", + "4 4 4 4 ..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "q('n:last system\"c\";extraWide:flip (`$\"col\",/:string 1+til n)!n#enlist til 1000')\n", + "display(q('{x set y;get x}[`:multiColSplay/]0#extraWide'))\n", + "display(q('{x set y;get x}[`:multiColSplay/]1#extraWide'))\n", + "display(q('{x set y;get x}[`:multiColSplay/]2#extraWide'))\n", + "display(q('{x set y;get x}[`:multiColSplay/]10#extraWide'))\n", + "display(q('{x set y;get x}[`:multiColSplay/]11#extraWide'))" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "b7453508-76ee-4f9e-ac50-c8ada3292c05", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19...col21
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19...col21
00000000000000000000...0
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19...col21
00000000000000000000...0
11111111111111111111...1
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19...col21
00000000000000000000...0
11111111111111111111...1
22222222222222222222...2
33333333333333333333...3
44444444444444444444...4
55555555555555555555...5
66666666666666666666...6
77777777777777777777...7
88888888888888888888...8
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "2 2 2 2 ..\n", + "3 3 3 3 ..\n", + "4 4 4 4 ..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19...col21
00000000000000000000...0
11111111111111111111...1
22222222222222222222...2
33333333333333333333...3
44444444444444444444...4
55555555555555555555...5
66666666666666666666...6
77777777777777777777...7
..................................................................
1010101010101010101010101010101010101010...10
\n", + "

11 rows × 21 columns

" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "2 2 2 2 ..\n", + "3 3 3 3 ..\n", + "4 4 4 4 ..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "q('n:1+last system\"c\";extraWide:flip (`$\"col\",/:string 1+til n)!n#enlist til 1000')\n", + "display(q('{x set y;get x}[`:multiColSplay/]0#extraWide'))\n", + "display(q('{x set y;get x}[`:multiColSplay/]1#extraWide'))\n", + "display(q('{x set y;get x}[`:multiColSplay/]2#extraWide'))\n", + "display(q('{x set y;get x}[`:multiColSplay/]10#extraWide'))\n", + "display(q('{x set y;get x}[`:multiColSplay/]11#extraWide'))" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "dd91e726-7a94-4aa4-92d7-c2f04414829d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19...col70
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19...col70
00000000000000000000...0
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19...col70
00000000000000000000...0
11111111111111111111...1
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19...col70
00000000000000000000...0
11111111111111111111...1
22222222222222222222...2
33333333333333333333...3
44444444444444444444...4
55555555555555555555...5
66666666666666666666...6
77777777777777777777...7
88888888888888888888...8
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "2 2 2 2 ..\n", + "3 3 3 3 ..\n", + "4 4 4 4 ..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18col19...col70
00000000000000000000...0
11111111111111111111...1
22222222222222222222...2
33333333333333333333...3
44444444444444444444...4
55555555555555555555...5
66666666666666666666...6
77777777777777777777...7
..................................................................
1010101010101010101010101010101010101010...10
\n", + "

11 rows × 70 columns

" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "col1 col2 col3 co..\n", + "-----------------..\n", + "0 0 0 0 ..\n", + "1 1 1 1 ..\n", + "2 2 2 2 ..\n", + "3 3 3 3 ..\n", + "4 4 4 4 ..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "q('n:50+last system\"c\";extraWide:flip (`$\"col\",/:string 1+til n)!n#enlist til 1000')\n", + "display(q('{x set y;get x}[`:multiColSplay/]0#extraWide'))\n", + "display(q('{x set y;get x}[`:multiColSplay/]1#extraWide'))\n", + "display(q('{x set y;get x}[`:multiColSplay/]2#extraWide'))\n", + "display(q('{x set y;get x}[`:multiColSplay/]10#extraWide'))\n", + "display(q('{x set y;get x}[`:multiColSplay/]11#extraWide'))" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "18d50dd9-b4d6-4cab-a8c2-9cdfe49e244a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
0`aa
1`aa`bb
2,`aa`bb
3`sym$`aa
4`sym$`aa`cc`bb
5,`sym$`aa`cc`bb
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a \n", + "---------------\n", + "`aa \n", + "`aa`bb \n", + ",`aa`bb \n", + "`sym$`aa \n", + "`sym$`aa`cc`bb \n", + ",`sym$`aa`cc`bb\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
0`aa
1`aa`bb
2,`aa`bb
3`sym$`aa
4`sym$`aa`cc`bb
5,`sym$`aa`cc`bb
6`aa
7`aa`bb
......
29,`sym$`aa`cc`bb
\n", + "

30 rows × 1 columns

" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a \n", + "--------------\n", + "`aa \n", + "`aa`bb \n", + ",`aa`bb \n", + "`sym$`aa \n", + "`sym$`aa`cc`bb\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
0aa
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a \n", + "--\n", + "aa\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
0aa bb
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a \n", + "-----\n", + "aa bb\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
0,`aa`bb
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a \n", + "-----\n", + "aa bb\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
0aa
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a \n", + "--\n", + "aa\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
0aa cc bb
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a \n", + "--------\n", + "aa cc bb\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
0,`sym$`aa`cc`bb
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a \n", + "--------\n", + "aa cc bb\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Syms and enums\n", + "q('enums:`sym?`aa`cc`bb')\n", + "q('symsEnums:([] a:(`aa;`aa`bb;enlist `aa`bb;first enums;enums;enlist enums))')\n", + "display(q('symsEnums'))\n", + "display(q('30#symsEnums'))\n", + "display(q('symsEnums (),0'))\n", + "display(q('symsEnums (),1'))\n", + "display(q('symsEnums (),2'))\n", + "display(q('symsEnums (),3'))\n", + "display(q('symsEnums (),4'))\n", + "display(q('symsEnums (),5'))" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "dcf9429d-b9c9-4db4-9d48-ff45c9dd2fc8", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
0`aa
1`aa`bb
2,`aa`bb
3`sym!0
4`sym!0 1 2
5,`sym!0 1 2
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a \n", + "-----------\n", + "`aa \n", + "`aa`bb \n", + ",`aa`bb \n", + "`sym!0 \n", + "`sym!0 1 2 \n", + ",`sym!0 1 2\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
0`aa
1`aa`bb
2,`aa`bb
3`sym!0
4`sym!0 1 2
5,`sym!0 1 2
6`aa
7`aa`bb
......
29,`sym!0 1 2
\n", + "

30 rows × 1 columns

" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a \n", + "----------\n", + "`aa \n", + "`aa`bb \n", + ",`aa`bb \n", + "`sym!0 \n", + "`sym!0 1 2\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
0aa
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a \n", + "--\n", + "aa\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
0aa bb
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a \n", + "-----\n", + "aa bb\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
0,`aa`bb
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a \n", + "-----\n", + "aa bb\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
00
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a\n", + "-\n", + "0\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
00 1 2
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a \n", + "-----\n", + "0 1 2\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
0,`sym!0 1 2
" + ], + "text/plain": [ + "pykx.Table(pykx.q('\n", + "a \n", + "-----\n", + "0 1 2\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "q('delete sym from `.')\n", + "display(q('symsEnums'))\n", + "display(q('30#symsEnums'))\n", + "display(q('symsEnums (),0'))\n", + "display(q('symsEnums (),1'))\n", + "display(q('symsEnums (),2'))\n", + "display(q('symsEnums (),3'))\n", + "display(q('symsEnums (),4'))\n", + "display(q('symsEnums (),5'))" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "ef8d6c6d-0297-45fa-9d4a-3acb9051e88b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
0`aa
1`aa`bb
2,`aa`bb
3`sym!0
4`sym!0 1 2
5,`sym!0 1 2
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "a \n", + "-----------\n", + "`aa \n", + "`aa`bb \n", + ",`aa`bb \n", + "`sym!0 \n", + "`sym!0 1 2 \n", + ",`sym!0 1 2\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
0`aa
1`aa`bb
2,`aa`bb
3`sym!0
4`sym!0 1 2
5,`sym!0 1 2
6`aa
7`aa`bb
......
29,`sym!0 1 2
\n", + "

30 rows × 1 columns

" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "a \n", + "----------\n", + "`aa \n", + "`aa`bb \n", + ",`aa`bb \n", + "`sym!0 \n", + "`sym!0 1 2\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
0aa
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "a \n", + "--\n", + "aa\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
0aa bb
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "a \n", + "-----\n", + "aa bb\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
0,`aa`bb
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "a \n", + "-----\n", + "aa bb\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
0aa
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "a \n", + "--\n", + "aa\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
0aa bb
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "a \n", + "------\n", + "aa bb \n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
0,`sym$`aa`bb`
" + ], + "text/plain": [ + "pykx.SplayedTable(pykx.q('\n", + "a \n", + "------\n", + "aa bb \n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "display(q('`:symsEnumsSplay/ set .Q.en[`:.] symsEnums;get `:symsEnumsSplay/'))\n", + "display(q('`:symsEnumsSplay/ set .Q.en[`:.] 30#symsEnums;get `:symsEnumsSplay/'))\n", + "display(q('`:symsEnumsSplay/ set .Q.en[`:.] symsEnums (),0;get `:symsEnumsSplay/'))\n", + "display(q('`:symsEnumsSplay/ set .Q.en[`:.] symsEnums (),1;get `:symsEnumsSplay/'))\n", + "display(q('`:symsEnumsSplay/ set .Q.en[`:.] symsEnums (),2;get `:symsEnumsSplay/'))\n", + "display(q('`:symsEnumsSplay/ set .Q.en[`:.] symsEnums (),3;get `:symsEnumsSplay/'))\n", + "display(q('`:symsEnumsSplay/ set .Q.en[`:.] symsEnums (),4;get `:symsEnumsSplay/'))\n", + "display(q('`:symsEnumsSplay/ set .Q.en[`:.] symsEnums (),5;get `:symsEnumsSplay/'))" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "142cdfdc-dc71-462f-9336-1e636d0966cd", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
b
0`aa
1`aa`bb
2,`aa`bb
3`sym$`aa
4`sym$`aa`bb`
5,`sym$`aa`bb`
" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "b| a \n", + "-| -------------\n", + "0| `aa \n", + "1| `aa`bb \n", + "2| ,`aa`bb \n", + "3| `sym$`aa \n", + "4| `sym$`aa`bb` \n", + "5| ,`sym$`aa`bb`\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
b
0`aa
1`aa`bb
2,`aa`bb
3`sym$`aa
4`sym$`aa`bb`
5,`sym$`aa`bb`
0`aa
1`aa`bb
......
5,`sym$`aa`bb`
\n", + "

30 rows × 2 columns

" + ], + "text/plain": [ + "pykx.KeyedTable(pykx.q('\n", + "b| a \n", + "-| ------------\n", + "0| `aa \n", + "1| `aa`bb \n", + "2| ,`aa`bb \n", + "3| `sym$`aa \n", + "4| `sym$`aa`bb`\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
aaa
" + ], + "text/plain": [ + "pykx.Dictionary(pykx.q('a| aa'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
aaa bb
" + ], + "text/plain": [ + "pykx.Dictionary(pykx.q('a| aa bb'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a,`aa`bb
" + ], + "text/plain": [ + "pykx.Dictionary(pykx.q('a| aa bb'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
aaa
" + ], + "text/plain": [ + "pykx.Dictionary(pykx.q('a| aa'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
aaa bb
" + ], + "text/plain": [ + "pykx.Dictionary(pykx.q('a| aa bb '))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a,`sym$`aa`bb`
" + ], + "text/plain": [ + "pykx.Dictionary(pykx.q('a| aa bb '))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "q('keyedSymsEnums:`b xkey update b:i from symsEnums')\n", + "display(q('keyedSymsEnums'))\n", + "display(q('30#keyedSymsEnums'))\n", + "display(q('keyedSymsEnums (),0'))\n", + "display(q('keyedSymsEnums (),1'))\n", + "display(q('keyedSymsEnums (),2'))\n", + "display(q('keyedSymsEnums (),3'))\n", + "display(q('keyedSymsEnums (),4'))\n", + "display(q('keyedSymsEnums (),5'))" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "ae3dfd09-1a49-4283-88d2-ffa608f4f610", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "if not 'HDB' == os.path.basename(os.getcwd()):\n", + " os.makedirs('HDB', exist_ok=True)\n", + " os.chdir('HDB')" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "11077549-2e50-4c36-81de-154f4736c7b1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
datea
02001.01.01`aa
12001.01.01`aa`bb
22001.01.01,`aa`bb
32001.01.01`sym$`aa
42001.01.01`sym$`aa`bb`
52001.01.01,`sym$`aa`bb`
" + ], + "text/plain": [ + "pykx.PartitionedTable(pykx.q('\n", + "date a ..\n", + "-----------------..\n", + "2001.01.01 `aa ..\n", + "2001.01.01 `aa`bb..\n", + "2001.01.01 ,`aa`b..\n", + "2001.01.01 `sym$`..\n", + "2001.01.01 `sym$`..\n", + "2001.01.01 ,`sym$..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
datea
02001.01.01`aa
12001.01.01`aa`bb
22001.01.01,`aa`bb
32001.01.01`sym$`aa
42001.01.01`sym$`aa`bb`
52001.01.01,`sym$`aa`bb`
62001.01.01`aa
72001.01.01`aa`bb
.........
292001.01.01,`sym$`aa`bb`
\n", + "

30 rows × 2 columns

" + ], + "text/plain": [ + "pykx.PartitionedTable(pykx.q('\n", + "date a ..\n", + "-----------------..\n", + "2001.01.01 `aa ..\n", + "2001.01.01 `aa`bb..\n", + "2001.01.01 ,`aa`b..\n", + "2001.01.01 `sym$`..\n", + "2001.01.01 `sym$`..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
datea
02001.01.01aa
" + ], + "text/plain": [ + "pykx.PartitionedTable(pykx.q('\n", + "date a \n", + "-------------\n", + "2001.01.01 aa\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
datea
02001.01.01aa bb
" + ], + "text/plain": [ + "pykx.PartitionedTable(pykx.q('\n", + "date a \n", + "----------------\n", + "2001.01.01 aa bb\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
datea
02001.01.01,`aa`bb
" + ], + "text/plain": [ + "pykx.PartitionedTable(pykx.q('\n", + "date a \n", + "----------------\n", + "2001.01.01 aa bb\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
datea
02001.01.01aa
" + ], + "text/plain": [ + "pykx.PartitionedTable(pykx.q('\n", + "date a \n", + "-------------\n", + "2001.01.01 aa\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
datea
02001.01.01aa bb
" + ], + "text/plain": [ + "pykx.PartitionedTable(pykx.q('\n", + "date a \n", + "-----------------\n", + "2001.01.01 aa bb \n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
datea
02001.01.01,`sym$`aa`bb`
" + ], + "text/plain": [ + "pykx.PartitionedTable(pykx.q('\n", + "date a \n", + "-----------------\n", + "2001.01.01 aa bb \n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Partitioned syms and enums\n", + "q('(`$\":2001.01.02/partitionedTab/\") set .Q.en[`:.] 0#symsEnums')\n", + "display(q('(`$\":2001.01.01/partitionedTab/\") set .Q.en[`:.] symsEnums;system\"l .\";partitionedTab'))\n", + "display(q('(`$\":2001.01.01/partitionedTab/\") set .Q.en[`:.] 30#symsEnums;system\"l .\";partitionedTab'))\n", + "display(q('(`$\":2001.01.01/partitionedTab/\") set .Q.en[`:.] symsEnums (),0;system\"l .\";partitionedTab'))\n", + "display(q('(`$\":2001.01.01/partitionedTab/\") set .Q.en[`:.] symsEnums (),1;system\"l .\";partitionedTab'))\n", + "display(q('(`$\":2001.01.01/partitionedTab/\") set .Q.en[`:.] symsEnums (),2;system\"l .\";partitionedTab'))\n", + "display(q('(`$\":2001.01.01/partitionedTab/\") set .Q.en[`:.] symsEnums (),3;system\"l .\";partitionedTab'))\n", + "display(q('(`$\":2001.01.01/partitionedTab/\") set .Q.en[`:.] symsEnums (),4;system\"l .\";partitionedTab'))\n", + "display(q('(`$\":2001.01.01/partitionedTab/\") set .Q.en[`:.] symsEnums (),5;system\"l .\";partitionedTab'))" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "b7fc4d74-d492-488c-96df-bce24114acdb", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
datea
" + ], + "text/plain": [ + "pykx.PartitionedTable(pykx.q(''))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Partitioned\n", + "q('(`$\":2001.01.01/partitionedTab/\") set 0#([] a:.z.d-til 2000;b:til 2000)')\n", + "q('system\"l .\"')\n", + "display(q('partitionedTab'))" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "9c8d4c7f-811a-48a2-bc82-6bde3324a89e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
datea
02001.01.012023.10.06
" + ], + "text/plain": [ + "pykx.PartitionedTable(pykx.q('\n", + "date a ..\n", + "-----------------..\n", + "2001.01.01 2023.1..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "q('(`$\":2001.01.01/partitionedTab/\") set 1#([] a:.z.d-til 2000;b:til 2000)')\n", + "q('system\"l .\"')\n", + "display(q('partitionedTab'))" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "424326eb-7065-4df5-bdfb-395280ada0a3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
datea
02001.01.012023.10.06
12001.01.012023.10.05
" + ], + "text/plain": [ + "pykx.PartitionedTable(pykx.q('\n", + "date a ..\n", + "-----------------..\n", + "2001.01.01 2023.1..\n", + "2001.01.01 2023.1..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "q('(`$\":2001.01.01/partitionedTab/\") set 2#([] a:.z.d-til 2000;b:til 2000)')\n", + "q('system\"l .\"')\n", + "display(q('partitionedTab'))" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "675bb2ab-416f-4db6-8bcb-9426b1881404", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
dateab
02001.01.012023.10.060
12001.01.012023.10.051
22001.01.012023.10.042
32001.01.012023.10.033
42001.01.012023.10.024
52001.01.012023.10.015
62001.01.012023.09.306
72001.01.012023.09.297
82001.01.012023.09.288
92001.01.012023.09.279
" + ], + "text/plain": [ + "pykx.PartitionedTable(pykx.q('\n", + "date a ..\n", + "-----------------..\n", + "2001.01.01 2023.1..\n", + "2001.01.01 2023.1..\n", + "2001.01.01 2023.1..\n", + "2001.01.01 2023.1..\n", + "2001.01.01 2023.1..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "q('(`$\":2001.01.01/partitionedTab/\") set 10#([] a:.z.d-til 2000;b:til 2000)')\n", + "q('(`$\":2001.01.02/partitionedTab/\") set 0#([] a:.z.d-til 2000;b:til 2000)')\n", + "q('system\"l .\"')\n", + "display(q('partitionedTab'))" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "9a73bd26-5b81-4bed-bbbe-542450e4f793", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
dateab
02001.01.012023.10.060
12001.01.012023.10.051
22001.01.012023.10.042
32001.01.012023.10.033
42001.01.012023.10.024
52001.01.012023.10.015
62001.01.012023.09.306
72001.01.012023.09.297
............
102001.01.012023.09.2610
\n", + "

11 rows × 3 columns

" + ], + "text/plain": [ + "pykx.PartitionedTable(pykx.q('\n", + "date a ..\n", + "-----------------..\n", + "2001.01.01 2023.1..\n", + "2001.01.01 2023.1..\n", + "2001.01.01 2023.1..\n", + "2001.01.01 2023.1..\n", + "2001.01.01 2023.1..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "q('(`$\":2001.01.01/partitionedTab/\") set 11#([] a:.z.d-til 2000;b:til 2000)')\n", + "q('system\"l .\"')\n", + "display(q('partitionedTab'))" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "c3f0aca1-4a95-40bb-8ee1-6baa943030c5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
dateab
" + ], + "text/plain": [ + "pykx.PartitionedTable(pykx.q(''))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "q('(`$\":2001.01.01/partitionedTab/\") set 0#([] a:.z.d-til 2000;b:til 2000)')\n", + "q('(`$\":2001.01.02/partitionedTab/\") set 0#([] a:.z.d-til 2000;b:til 2000)')\n", + "q('system\"l .\"')\n", + "display(q('partitionedTab'))" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "96a30bc5-5866-4926-a77b-04dc42254a5d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
dateab
02001.01.022023.10.060
" + ], + "text/plain": [ + "pykx.PartitionedTable(pykx.q('\n", + "date a ..\n", + "-----------------..\n", + "2001.01.02 2023.1..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "q('(`$\":2001.01.01/partitionedTab/\") set 0#([] a:.z.d-til 2000;b:til 2000)')\n", + "q('(`$\":2001.01.02/partitionedTab/\") set 1#([] a:.z.d-til 2000;b:til 2000)')\n", + "q('system\"l .\"')\n", + "display(q('partitionedTab'))" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "5e2447c3-3429-4f65-8e3e-ee302ffe0f1a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
dateab
02001.01.012023.10.060
12001.01.012023.10.051
22001.01.012023.10.042
32001.01.012023.10.033
42001.01.012023.10.024
52001.01.012023.10.015
62001.01.012023.09.306
72001.01.012023.09.297
............
192001.01.022023.09.279
\n", + "

20 rows × 3 columns

" + ], + "text/plain": [ + "pykx.PartitionedTable(pykx.q('\n", + "date a ..\n", + "-----------------..\n", + "2001.01.01 2023.1..\n", + "2001.01.01 2023.1..\n", + "2001.01.01 2023.1..\n", + "2001.01.01 2023.1..\n", + "2001.01.01 2023.1..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "q('(`$\":2001.01.01/partitionedTab/\") set 10#([] a:.z.d-til 2000;b:til 2000)')\n", + "q('(`$\":2001.01.02/partitionedTab/\") set 10#([] a:.z.d-til 2000;b:til 2000)')\n", + "q('system\"l .\"')\n", + "display(q('partitionedTab'))" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "31420115-d81c-4b20-8234-c82cdbf0a468", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
dateab
02001.01.012023.10.060
" + ], + "text/plain": [ + "pykx.PartitionedTable(pykx.q('\n", + "date a ..\n", + "-----------------..\n", + "2001.01.01 2023.1..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "q('(`$\":2001.01.01/partitionedTab/\") set 1#([] a:.z.d-til 2000;b:til 2000)')\n", + "q('(`$\":2001.01.02/partitionedTab/\") set 0#([] a:.z.d-til 2000;b:til 2000)')\n", + "q('system\"l .\"')\n", + "display(q('partitionedTab'))" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "65b51538-86c0-4528-9e44-5069d50e0caa", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
dateab
02001.01.012023.10.060
12001.01.012023.10.051
22001.01.012023.10.042
32001.01.012023.10.033
42001.01.012023.10.024
52001.01.012023.10.015
62001.01.012023.09.306
72001.01.012023.09.297
............
342001.01.012023.09.0234
\n", + "

35 rows × 3 columns

" + ], + "text/plain": [ + "pykx.PartitionedTable(pykx.q('\n", + "date a ..\n", + "-----------------..\n", + "2001.01.01 2023.1..\n", + "2001.01.01 2023.1..\n", + "2001.01.01 2023.1..\n", + "2001.01.01 2023.1..\n", + "2001.01.01 2023.1..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "q('(`$\":2001.01.01/partitionedTab/\") set 35#([] a:.z.d-til 2000;b:til 2000)')\n", + "q('(`$\":2001.01.02/partitionedTab/\") set 0#([] a:.z.d-til 2000;b:til 2000)')\n", + "q('system\"l .\"')\n", + "display(q('partitionedTab'))" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "4abab75e-86ce-410b-b5e8-eb026a7c2bc8", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
dateab
02001.01.022023.10.060
12001.01.022023.10.051
22001.01.022023.10.042
32001.01.022023.10.033
42001.01.022023.10.024
52001.01.022023.10.015
62001.01.022023.09.306
72001.01.022023.09.297
............
342001.01.022023.09.0234
\n", + "

35 rows × 3 columns

" + ], + "text/plain": [ + "pykx.PartitionedTable(pykx.q('\n", + "date a ..\n", + "-----------------..\n", + "2001.01.02 2023.1..\n", + "2001.01.02 2023.1..\n", + "2001.01.02 2023.1..\n", + "2001.01.02 2023.1..\n", + "2001.01.02 2023.1..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "q('(`$\":2001.01.01/partitionedTab/\") set 0#([] a:.z.d-til 2000;b:til 2000)')\n", + "q('(`$\":2001.01.02/partitionedTab/\") set 35#([] a:.z.d-til 2000;b:til 2000)')\n", + "q('system\"l .\"')\n", + "display(q('partitionedTab'))" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "9543a33b-8f15-4239-8d8c-9638ce17440e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
dateab
02001.01.012023.10.060
12001.01.012023.10.051
22001.01.012023.10.042
32001.01.012023.10.033
42001.01.012023.10.024
52001.01.012023.10.015
62001.01.012023.09.306
72001.01.012023.09.297
............
212001.01.022023.09.2610
\n", + "

22 rows × 3 columns

" + ], + "text/plain": [ + "pykx.PartitionedTable(pykx.q('\n", + "date a ..\n", + "-----------------..\n", + "2001.01.01 2023.1..\n", + "2001.01.01 2023.1..\n", + "2001.01.01 2023.1..\n", + "2001.01.01 2023.1..\n", + "2001.01.01 2023.1..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "q('(`$\":2001.01.01/partitionedTab/\") set 11#([] a:.z.d-til 2000;b:til 2000)')\n", + "q('(`$\":2001.01.02/partitionedTab/\") set 11#([] a:.z.d-til 2000;b:til 2000)')\n", + "q('system\"l .\"')\n", + "display(q('partitionedTab'))" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "id": "129163ae-570e-4329-a40c-e5133320fce7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
datecol1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18...col70
" + ], + "text/plain": [ + "pykx.PartitionedTable(pykx.q(''))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "q('(`$\":2001.01.01/partitionedTab/\") set 0#extraWide')\n", + "q('(`$\":2001.01.02/partitionedTab/\") set 0#extraWide')\n", + "q('system\"l .\"')\n", + "display(q('partitionedTab'))" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "id": "52bd855d-5b8a-4b69-8f36-d08fc5bf02db", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
datecol1col2col3col4col5col6col7col8col9col10col11col12col13col14col15col16col17col18...col70
02001.01.01000000000000000000...0
12001.01.01111111111111111111...1
22001.01.01222222222222222222...2
32001.01.01333333333333333333...3
42001.01.01444444444444444444...4
52001.01.01555555555555555555...5
62001.01.01666666666666666666...6
72001.01.01777777777777777777...7
..................................................................
122001.01.01121212121212121212121212121212121212...12
\n", + "

13 rows × 71 columns

" + ], + "text/plain": [ + "pykx.PartitionedTable(pykx.q('\n", + "date col1 c..\n", + "-----------------..\n", + "2001.01.01 0 0..\n", + "2001.01.01 1 1..\n", + "2001.01.01 2 2..\n", + "2001.01.01 3 3..\n", + "2001.01.01 4 4..\n", + "..\n", + "'))" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "q('(`$\":2001.01.01/partitionedTab/\") set 13#extraWide')\n", + "q('(`$\":2001.01.02/partitionedTab/\") set 0#extraWide')\n", + "q('system\"l .\"')\n", + "display(q('partitionedTab'))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/tests/test_system.py b/tests/test_system.py index 4643493..d2d482e 100644 --- a/tests/test_system.py +++ b/tests/test_system.py @@ -4,6 +4,11 @@ import pytest +@pytest.mark.isolate +def test_system_call(q): + assert (q.system('echo "1"') == q('"1"')).all() + + @pytest.mark.isolate @pytest.mark.parametrize('num_threads', range(3)) def test_qargs_s_flag(num_threads): diff --git a/tests/test_toq.py b/tests/test_toq.py index 2d1448d..f61fccc 100644 --- a/tests/test_toq.py +++ b/tests/test_toq.py @@ -789,6 +789,7 @@ def test_from_pandas_dataframe(kx, pd): @pytest.mark.nep49 def test_from_pandas_dataframe_licensed(q, kx): + q.system.console_size = [25, 80] t = q('([] a:til 4; b:"abcd"; c:`w`x`y`z; d:100+til 4)').pd() assert t.equals(kx.K(t).pd()) @@ -809,6 +810,19 @@ def test_from_pandas_dataframe_licensed(q, kx): assert time_tab.equals(kx.K(time_tab).pd()) +@pytest.mark.nep49 +def test_from_pandas_dataframe_licensed_warning(q, kx): + if pd.__version__.split('.')[0] == '2': + q('N:100') + gen_q_datatypes_table(q, 'dset_1D', int(q('N'))) + q('gen_names:{"dset_",/:x,/:string til count y}') + type_tab = q('flip (`$gen_names["tab";dset_1D])!N#\'dset_1D') + df = type_tab.pd() + del df.attrs['_PyKX_base_types'] + with pytest.warns(RuntimeWarning): + kx.K(df) + + @pytest.mark.unlicensed @pytest.mark.nep49 def test_from_complex_pandas_dataframe(kx, pd): @@ -993,6 +1007,51 @@ def test_from_pandas_categorical(q, kx, pd): assert kx.toq.ENUMS == ['enum0', 'cat', 'index', 'series', 'sym'] +@pytest.mark.nep49 +def test_toq_pd_tabular_ktype(q, kx): + df = pd.DataFrame.from_dict({'x': [1, 2], 'y': ['a', 'b']}) + assert kx.toq(df).dtypes['type'].py() == [b'kx.LongAtom', b'kx.SymbolAtom'] + kval = {'x': kx.FloatVector} + assert kx.toq(df, ktype=kval).dtypes['type'].py() == [b'kx.FloatAtom', b'kx.SymbolAtom'] + kval = {'x': kx.FloatVector, 'y': kx.CharVector} + assert kx.toq(df, ktype=kval).dtypes['type'].py() == [b'kx.FloatAtom', b'kx.CharVector'] + with pytest.raises(ValueError, match="Column name passed in dictionary not present in df table"): # noqa: E501 + kx.toq(df, ktype={'x1': kx.FloatVector}) + with pytest.raises(kx.QError, match="Not supported:.*"): + kx.toq(df, ktype={'x': kx.GUIDVector}) + + +@pytest.mark.nep49 +def test_toq_pa_tabular_ktype(q, kx, pa): + pdtab = pd.DataFrame.from_dict({'x': [1, 2], 'y': ['a', 'b']}) + df = pa.Table.from_pandas(pdtab) + assert kx.toq(df).dtypes['type'].py() == [b'kx.LongAtom', b'kx.SymbolAtom'] + kval = {'x': kx.FloatVector} + assert kx.toq(df, ktype=kval).dtypes['type'].py() == [b'kx.FloatAtom', b'kx.SymbolAtom'] + kval = {'x': kx.FloatVector, 'y': kx.CharVector} + assert kx.toq(df, ktype=kval).dtypes['type'].py() == [b'kx.FloatAtom', b'kx.CharVector'] + with pytest.raises(ValueError, match="Column name passed in dictionary not present in df table"): # noqa: E501 + kx.toq(df, ktype={'x1': kx.FloatVector}) + with pytest.raises(kx.QError, match="Not supported:.*"): + kx.toq(df, ktype={'x': kx.GUIDVector}) + + +@pytest.mark.unlicensed +def test_toq_dict_error(q, kx): + pdSeries = q('1 2 3').pd() + with pytest.raises(TypeError, match=r"'ktype' .*"): + kx.toq(pdSeries, {'x': kx.LongVector}) + paArray = q('1 2 3').pa() + with pytest.raises(TypeError, match=r"'ktype' .*"): + kx.toq(paArray, {'x': kx.LongVector}) + npArray = q('1 2 3').np() + with pytest.raises(TypeError, match=r"'ktype' .*"): + kx.toq(npArray, {'x': kx.LongVector}) + pydict = {'x': 1, 'y': 2} + with pytest.raises(TypeError, match=r"'ktype' .*"): + kx.toq(pydict, {'x': kx.LongVector}) + + # TODO: Add this mark back once this test is consitently passing again, adding more calls to it # each test pass just increases the chance of the tests failing. @pytest.mark.nep49 diff --git a/tests/test_wrappers.py b/tests/test_wrappers.py index 792ab77..67ef283 100644 --- a/tests/test_wrappers.py +++ b/tests/test_wrappers.py @@ -60,19 +60,19 @@ def test_eval_repr_unlicensed(kx): @pytest.mark.embedded def test_pykx_q_get(kx, q): with pytest.raises(kx.QError): - kx.q('.pykx.get`blorp') + q('.pykx.get`blorp') @pytest.mark.embedded def test_pykx_q_getattr(kx, q): - kx.q("af:.pykx.eval\"type('Car', (object,), {'speed': 200, 'color': 'red'})\"") - kx.q('af[`:speed]`') + q("af:.pykx.eval\"type('Car', (object,), {'speed': 200, 'color': 'red'})\"") + q('af[`:speed]`') with pytest.raises(kx.QError): - kx.q('af[`:boourns]`') + q('af[`:boourns]`') - kx.q('arr:.pykx.eval"[1, 2, 3]"') + q('arr:.pykx.eval"[1, 2, 3]"') with pytest.raises(kx.QError): - kx.q('.pykx.getattr[.pykx.unwrap arr;`foobarbaz]') + q('.pykx.getattr[.pykx.unwrap arr;`foobarbaz]') # TODO: Once PYKX_RELEASE_GIL is fixed this should be uncommented # @pytest.mark.embedded @@ -116,6 +116,7 @@ def test_refcounting_q_vars(self, kx, q): assert q('-16!a') == kx._wrappers.k_r(q('a'))== 1 def test_repr(self, q, kx): + q.system.console_size = [25, 80] pykx = kx # noqa: F401 rand_shorts = q('5?0Wh') assert all(rand_shorts == eval(repr(rand_shorts), globals(), locals())) @@ -1999,9 +2000,10 @@ def test_pd_null_time_conversion(self, q, pd): x = q('([]a:(.z.t;0Nt))').pd() y = q('([]a:(.z.D;0Nd))').pd() z = q('([]a:(2000.01;0Nm))').pd() + pandas_2 = pd.__version__.split('.')[0] == 2 assert w.dtypes['a'] == np.dtype(' q behaviour + assert (q('`a`b`c!til 3')[q('`b`z')] == q('1 0N')).all() # q index -> q behavior with pytest.raises(KeyError): - q('`a`b`c!til 3')['b', 'z'] # Python index -> Python behaviour + q('`a`b`c!til 3')['b', 'z'] # Python index -> Python behavior assert q('`a`b`c!til 3')[q('`a`b')].py() == [0, 1] def test_py(self, q): @@ -2374,6 +2387,22 @@ def test_multi_keyed_pd(self, q): assert mkt_pd['y'][('b', 101)] == 'keyed' assert mkt_pd['y'][('a', 102)] == 'table' + def test_empty_keyed_table(self, q, kx): + q_mkt_empty = q('0#`a xkey ([] a:1 2 3;b:3 4 5)') + q_mkt_multi_empty = q('0#`a`b xkey ([] a:1 2 3;b:3 4 5;c:6 7 8)') + mkt_empty = q_mkt_empty.pd() + mkt_multi_empty = q_mkt_multi_empty.pd() + assert len(mkt_empty) == 0 + assert len(mkt_multi_empty) == 0 + assert mkt_empty.index.name == 'a' + assert mkt_multi_empty.index.names == ['a', 'b'] + assert list(mkt_empty.columns) == ['b'] + assert list(mkt_multi_empty.columns) == ['c'] + assert type(kx.toq(mkt_empty)) == kx.KeyedTable + assert type(kx.toq(mkt_multi_empty)) == kx.KeyedTable + assert len(kx.toq(mkt_empty)) == 0 + assert len(kx.toq(mkt_multi_empty)) == 0 + def test_py(self, q): assert q(self.kt).py() == { (100,): {'x': 0, 'y': 'singly'}, @@ -2787,7 +2816,7 @@ def test_symbolic_function(self, kx, q, q_port): # Conversions of nested K lists requires a license, We need to be able to call -# __getitem__ on the list to get correctly typed numpy arrays to use. +# __getitem__ on the list to get correctly typed Numpy arrays to use. @pytest.mark.licensed @pytest.mark.nep49 def test_numpy_ufuncs(kx, q): @@ -3023,7 +3052,7 @@ def test_numpy_ufuncs_reduceat(kx, q): # Conversions of nested K lists requires a license, We need to be able to call -# __getitem__ on the list to get correctly typed numpy arrays to use. +# __getitem__ on the list to get correctly typed Numpy arrays to use. @pytest.mark.licensed @pytest.mark.nep49 def test_numpy_functions(kx, q): @@ -3057,9 +3086,9 @@ def test_numpy_equals(kx, q): assert False == (np.array([[1, 2, 3], [4, 5, 6]]) == q('(1 1 1 7;2 2 5 2)')).py() else: with pytest.raises(kx.QError): - assert np.array([[1, 2, 3], [4, 5, 6]]) == kx.q('(1 1 1;2 2 5 2)') + assert np.array([[1, 2, 3], [4, 5, 6]]) == q('(1 1 1;2 2 5 2)') with pytest.raises(ValueError): - assert np.array([[1, 2, 3], [4, 5, 6]]) == kx.q('(1 1 1 7;2 2 5 2)') + assert np.array([[1, 2, 3], [4, 5, 6]]) == q('(1 1 1 7;2 2 5 2)') @pytest.mark.licensed @@ -3217,3 +3246,429 @@ def test_attributes_keyed_table(kx, q): with pytest.raises(kx.QError): tab.parted(['x', 'x1']) + + +def test_apply_vector(q, kx): + longvec = q('til 10') + assert (longvec.apply(lambda x: x+1) == q('1+til 10')).all() + assert longvec.apply(q.sum) == q('45') + + def func(x): + return x+1 + assert (longvec.apply(func) == q('1+til 10')).all() + assert longvec.apply(np.sum) == q('45') + + def func_args(x, y): + return x+y + assert (longvec.apply(func_args, 2) == q('2+til 10')).all() + assert (longvec.apply(q('{x+y}'), 2) == q('2+til 10')).all() + + guidvec = q('-10?0Ng') + assert 10 == len(guidvec.apply(np.unique)) + assert 10 == len(guidvec.apply(q.distinct)) + + def func(x): + return q.string(x) + assert isinstance(guidvec.apply(func), kx.List) + + with pytest.raises(RuntimeError): + longvec.apply(10) + + with pytest.raises(kx.QError): + longvec.apply(q('{x+y}'), y=1) + + +def checkHTML(tab): + html = tab._repr_html_() + return (html.count(''), html.count(''), html.count('')) + + +@pytest.mark.licensed +def test_repr_html(kx, q): + H = 10 + W = 20 + q.system.console_size = [H, W] + + # Many datatypes + q('t:flip {(`$/:t)!2#/:(t:{x where not x in " z"}.Q.t)$\\:()}[]') + q('T:flip {(`$/:upper t)!2#/:enlist each 2#/:(t:{x where not x in " z"}.Q.t)$\\:()}[]') + q('wideManyDatatypes:t,\'T') + tab = q('wideManyDatatypes') + + # (rows, headers, details) + assert (3, 44, 40) == checkHTML(tab) + + # Single column table + q('singleColTab:([] a:.z.d-til 2000)') + tab = q('0#singleColTab') + assert (0, 2, 0) == checkHTML(tab) + tab = q('1#singleColTab') + assert (2, 5, 1) == checkHTML(tab) + tab = q('2#singleColTab') + assert (3, 6, 2) == checkHTML(tab) + tab = q('10#singleColTab') + assert (H, 13, 9) == checkHTML(tab) + tab = q('11#singleColTab') + assert (H+1, 14, 10) == checkHTML(tab) + + # Multi column table + q('multiColTab:([] a:.z.d-til 2000; sym:2000?`7)') + tab = q('0#multiColTab') + assert (0, 3, 0) == checkHTML(tab) + tab = q('1#multiColTab') + assert (2, 7, 2) == checkHTML(tab) + tab = q('2#multiColTab') + assert (3, 8, 4) == checkHTML(tab) + tab = q('10#multiColTab') + assert (H, 15, 18) == checkHTML(tab) + tab = q('11#multiColTab') + assert (H+1, 16, 20) == checkHTML(tab) + + q('n:-1+last system"c";extraWide:flip (`$"col",/:string 1+til n)!n#enlist til 1000') + tab = q('0#extraWide') + assert (0, 20, 0) == checkHTML(tab) + tab = q('1#extraWide') + assert (2, 41, 19) == checkHTML(tab) + tab = q('2#extraWide') + assert (3, 42, 38) == checkHTML(tab) + tab = q('10#extraWide') + assert (H, 49, 171) == checkHTML(tab) + tab = q('11#extraWide') + assert (H+1, 50, 190) == checkHTML(tab) + + q('n:last system"c";extraWide:flip (`$"col",/:string 1+til n)!n#enlist til 1000') + tab = q('0#extraWide') + assert (0, 21, 0) == checkHTML(tab) + tab = q('1#extraWide') + assert (2, 43, 20) == checkHTML(tab) + tab = q('2#extraWide') + assert (3, 44, 40) == checkHTML(tab) + tab = q('10#extraWide') + assert (H, 51, 180) == checkHTML(tab) + tab = q('11#extraWide') + assert (H+1, 52, 200) == checkHTML(tab) + + q('n:1+last system"c";extraWide:flip (`$"col",/:string 1+til n)!n#enlist til 1000') + tab = q('0#extraWide') + assert (0, 22, 0) == checkHTML(tab) + tab = q('1#extraWide') + assert (2, 45, 21) == checkHTML(tab) + tab = q('2#extraWide') + assert (3, 46, 42) == checkHTML(tab) + tab = q('10#extraWide') + assert (H, 53, 189) == checkHTML(tab) + tab = q('11#extraWide') + assert (H+1, 54, 210) == checkHTML(tab) + + q('n:50+last system"c";extraWide:flip (`$"col",/:string 1+til n)!n#enlist til 1000') + tab = q('0#extraWide') + assert (0, 22, 0) == checkHTML(tab) + tab = q('1#extraWide') + assert (2, 45, 21) == checkHTML(tab) + tab = q('2#extraWide') + assert (3, 46, 42) == checkHTML(tab) + tab = q('10#extraWide') + assert (H, 53, 189) == checkHTML(tab) + tab = q('11#extraWide') + assert (H+1, 54, 210) == checkHTML(tab) + + # Many keys + tab = q('(-1+last system"c")!0#extraWide') + assert (1, 42, 0) == checkHTML(tab) + tab = q('(-1+last system"c")!1#extraWide') + assert (2, 61, 2) == checkHTML(tab) + tab = q('(-1+last system"c")!2#extraWide') + assert (3, 80, 4) == checkHTML(tab) + tab = q('(-1+last system"c")!10#extraWide') + assert (H, 213, 18) == checkHTML(tab) + tab = q('(-1+last system"c")!11#extraWide') + assert (H+1, 232, 20) == checkHTML(tab) + + tab = q('(last system"c")!0#extraWide') + assert (1, 42, 0) == checkHTML(tab) + tab = q('(last system"c")!1#extraWide') + assert (2, 61, 2) == checkHTML(tab) + tab = q('(last system"c")!2#extraWide') + assert (3, 80, 4) == checkHTML(tab) + tab = q('(last system"c")!10#extraWide') + assert (H, 213, 18) == checkHTML(tab) + tab = q('(last system"c")!11#extraWide') + assert (H+1, 232, 20) == checkHTML(tab) + + tab = q('(1+last system"c")!0#extraWide') + assert (1, 42, 0) == checkHTML(tab) + tab = q('(1+last system"c")!1#extraWide') + assert (2, 61, 2) == checkHTML(tab) + tab = q('(1+last system"c")!2#extraWide') + assert (3, 80, 4) == checkHTML(tab) + tab = q('(1+last system"c")!10#extraWide') + assert (H, 213, 18) == checkHTML(tab) + tab = q('(1+last system"c")!11#extraWide') + assert (H+1, 232, 20) == checkHTML(tab) + + # Dictionaries + assert '

Empty pykx.Dictionary: ' == q('()!()')._repr_html_()[:26] + + dict = q('(enlist `b)!(enlist 2)') + assert (2, 5, 1) == checkHTML(dict) + dict = q('(`a`b)!(1 2)') + assert (3, 6, 2) == checkHTML(dict) + dict = q('(10?`6)!(til 10)') + assert (11, 14, 10) == checkHTML(dict) + dict = q('(11?`6)!(til 11)') + assert (11, 14, 10) == checkHTML(dict) + + dict = q('(enlist `b)!([] a:enlist 1)') + assert (2, 5, 1) == checkHTML(dict) + dict = q('(enlist `b)!([] a:enlist 1;b:enlist 2)') + assert (2, 7, 2) == checkHTML(dict) + dict = q('(enlist `b)!([] a:enlist 1;b:enlist 2)') + assert (2, 7, 2) == checkHTML(dict) + + dict = q('(9?`6)!flip (`$"col",/:string til 19)!(19#enlist til 9)') + assert (10, 49, 171) == checkHTML(dict) + dict = q('(10?`6)!flip (`$"col",/:string til 20)!(20#enlist til 10)') + assert (11, 52, 200) == checkHTML(dict) + dict = q('(11?`6)!flip (`$"col",/:string til 21)!(21#enlist til 11)') + assert (11, 52, 200) == checkHTML(dict) + + # Single Key + q('singleKeyTab:`sym xkey ([] a:.z.d-til 2000; sym:2000?`7)') + tab = q('0#singleKeyTab') + assert (1, 4, 0) == checkHTML(tab) + tab = q('1#singleKeyTab') + assert (2, 5, 1) == checkHTML(tab) + tab = q('2#singleKeyTab') + assert (3, 6, 2) == checkHTML(tab) + tab = q('10#singleKeyTab') + assert (H, 13, 9) == checkHTML(tab) + tab = q('11#singleKeyTab') + assert (H+1, 14, 10) == checkHTML(tab) + + # Multi Key + q('multiKeyTab:`sym`blah xkey ([] a:.z.d-til 2000; sym:2000?`7;blah:-2000?1000000)') + tab = q('0#multiKeyTab') + assert (1, 6, 0) == checkHTML(tab) + tab = q('1#multiKeyTab') + assert (2, 8, 1) == checkHTML(tab) + tab = q('2#multiKeyTab') + assert (3, 10, 2) == checkHTML(tab) + tab = q('10#multiKeyTab') + assert (H, 24, 9) == checkHTML(tab) + tab = q('11#multiKeyTab') + assert (H+1, 26, 10) == checkHTML(tab) + + # Single column splay table + tab = q('{x set 0#([] a:.z.d-til 2000);get x}`:singleColSplay/') + assert (0, 2, 0) == checkHTML(tab) + tab = q('{x set 1#([] a:.z.d-til 2000);get x}`:singleColSplay/') + assert (2, 5, 1) == checkHTML(tab) + tab = q('{x set 2#([] a:.z.d-til 2000);get x}`:singleColSplay/') + assert (3, 6, 2) == checkHTML(tab) + tab = q('{x set 10#([] a:.z.d-til 2000);get x}`:singleColSplay/') + assert (H, 13, 9) == checkHTML(tab) + tab = q('{x set 11#([] a:.z.d-til 2000);get x}`:singleColSplay/') + assert (H+1, 14, 10) == checkHTML(tab) + + # Multi column splay + tab = q('{x set 0#([] a:.z.d-til 2000; b:til 2000);get x}`:multiColSplay/') + assert (0, 3, 0) == checkHTML(tab) + tab = q('{x set 1#([] a:.z.d-til 2000; b:til 2000);get x}`:multiColSplay/') + assert (2, 7, 2) == checkHTML(tab) + tab = q('{x set 2#([] a:.z.d-til 2000; b:til 2000);get x}`:multiColSplay/') + assert (3, 8, 4) == checkHTML(tab) + tab = q('{x set 10#([] a:.z.d-til 2000; b:til 2000);get x}`:multiColSplay/') + assert (H, 15, 18) == checkHTML(tab) + tab = q('{x set 11#([] a:.z.d-til 2000; b:til 2000);get x}`:multiColSplay/') + assert (H+1, 16, 20) == checkHTML(tab) + + q('n:-1+last system"c";extraWide:flip (`$"col",/:string 1+til n)!n#enlist til 1000') + tab = q('{x set y;get x}[`:multiColSplay/]0#extraWide') + assert (0, 20, 0) == checkHTML(tab) + tab = q('{x set y;get x}[`:multiColSplay/]1#extraWide') + assert (2, 41, 19) == checkHTML(tab) + tab = q('{x set y;get x}[`:multiColSplay/]2#extraWide') + assert (3, 42, 38) == checkHTML(tab) + tab = q('{x set y;get x}[`:multiColSplay/]10#extraWide') + assert (H, 49, 171) == checkHTML(tab) + tab = q('{x set y;get x}[`:multiColSplay/]11#extraWide') + assert (H+1, 50, 190) == checkHTML(tab) + + q('n:last system"c";extraWide:flip (`$"col",/:string 1+til n)!n#enlist til 1000') + tab = q('{x set y;get x}[`:multiColSplay/]0#extraWide') + assert (0, 21, 0) == checkHTML(tab) + tab = q('{x set y;get x}[`:multiColSplay/]1#extraWide') + assert (2, 43, 20) == checkHTML(tab) + tab = q('{x set y;get x}[`:multiColSplay/]2#extraWide') + assert (3, 44, 40) == checkHTML(tab) + tab = q('{x set y;get x}[`:multiColSplay/]10#extraWide') + assert (H, 51, 180) == checkHTML(tab) + tab = q('{x set y;get x}[`:multiColSplay/]11#extraWide') + assert (H+1, 52, 200) == checkHTML(tab) + + q('n:1+last system"c";extraWide:flip (`$"col",/:string 1+til n)!n#enlist til 1000') + tab = q('{x set y;get x}[`:multiColSplay/]0#extraWide') + assert (0, 22, 0) == checkHTML(tab) + tab = q('{x set y;get x}[`:multiColSplay/]1#extraWide') + assert (2, 45, 21) == checkHTML(tab) + tab = q('{x set y;get x}[`:multiColSplay/]2#extraWide') + assert (3, 46, 42) == checkHTML(tab) + tab = q('{x set y;get x}[`:multiColSplay/]10#extraWide') + assert (H, 53, 189) == checkHTML(tab) + tab = q('{x set y;get x}[`:multiColSplay/]11#extraWide') + assert (H+1, 54, 210) == checkHTML(tab) + + q('n:50+last system"c";extraWide:flip (`$"col",/:string 1+til n)!n#enlist til 1000') + tab = q('{x set y;get x}[`:multiColSplay/]0#extraWide') + assert (0, 22, 0) == checkHTML(tab) + tab = q('{x set y;get x}[`:multiColSplay/]1#extraWide') + assert (2, 45, 21) == checkHTML(tab) + tab = q('{x set y;get x}[`:multiColSplay/]2#extraWide') + assert (3, 46, 42) == checkHTML(tab) + tab = q('{x set y;get x}[`:multiColSplay/]10#extraWide') + assert (H, 53, 189) == checkHTML(tab) + tab = q('{x set y;get x}[`:multiColSplay/]11#extraWide') + assert (H+1, 54, 210) == checkHTML(tab) + + # Syms and enums + q('enums:`sym?`aa`cc`bb') + q('symsEnums:([] a:(`aa;`aa`bb;enlist `aa`bb;first enums;enums;enlist enums))') + q('symsEnums')._repr_html_() + q('30#symsEnums')._repr_html_() + q('symsEnums (),0')._repr_html_() + q('symsEnums (),1')._repr_html_() + q('symsEnums (),2')._repr_html_() + q('symsEnums (),3')._repr_html_() + q('symsEnums (),4')._repr_html_() + q('symsEnums (),5')._repr_html_() + q('delete sym from `.') + q('symsEnums')._repr_html_() + q('30#symsEnums')._repr_html_() + q('symsEnums (),0')._repr_html_() + q('symsEnums (),1')._repr_html_() + q('symsEnums (),2')._repr_html_() + q('symsEnums (),3')._repr_html_() + q('symsEnums (),4')._repr_html_() + q('symsEnums (),5')._repr_html_() + + q('`:symsEnumsSplay/ set .Q.en[`:.] symsEnums;get `:symsEnumsSplay/')._repr_html_() + q('`:symsEnumsSplay/ set .Q.en[`:.] 30#symsEnums;get `:symsEnumsSplay/')._repr_html_() + q('`:symsEnumsSplay/ set .Q.en[`:.] symsEnums (),0;get `:symsEnumsSplay/')._repr_html_() + q('`:symsEnumsSplay/ set .Q.en[`:.] symsEnums (),1;get `:symsEnumsSplay/')._repr_html_() + q('`:symsEnumsSplay/ set .Q.en[`:.] symsEnums (),2;get `:symsEnumsSplay/')._repr_html_() + q('`:symsEnumsSplay/ set .Q.en[`:.] symsEnums (),3;get `:symsEnumsSplay/')._repr_html_() + q('`:symsEnumsSplay/ set .Q.en[`:.] symsEnums (),4;get `:symsEnumsSplay/')._repr_html_() + q('`:symsEnumsSplay/ set .Q.en[`:.] symsEnums (),5;get `:symsEnumsSplay/')._repr_html_() + + q('keyedSymsEnums:`b xkey update b:i from symsEnums') + q('keyedSymsEnums')._repr_html_() + q('30#keyedSymsEnums')._repr_html_() + q('keyedSymsEnums (),0')._repr_html_() + q('keyedSymsEnums (),1')._repr_html_() + q('keyedSymsEnums (),2')._repr_html_() + q('keyedSymsEnums (),3')._repr_html_() + q('keyedSymsEnums (),4')._repr_html_() + q('keyedSymsEnums (),5')._repr_html_() + + import os + os.makedirs('HDB', exist_ok=True) + os.chdir('HDB') + + # Partitioned syms and enums + q('(`$":2001.01.02/partitionedTab/") set .Q.en[`:.] 0#symsEnums') + q('(`$":2001.01.01/partitionedTab/") set .Q.en[`:.] symsEnums;system"l .";partitionedTab' + )._repr_html_() + q('(`$":2001.01.01/partitionedTab/") set .Q.en[`:.] 30#symsEnums;system"l .";partitionedTab' + )._repr_html_() + q('(`$":2001.01.01/partitionedTab/") set .Q.en[`:.] symsEnums (),0;system"l .";partitionedTab' + )._repr_html_() + q('(`$":2001.01.01/partitionedTab/") set .Q.en[`:.] symsEnums (),1;system"l .";partitionedTab' + )._repr_html_() + q('(`$":2001.01.01/partitionedTab/") set .Q.en[`:.] symsEnums (),2;system"l .";partitionedTab' + )._repr_html_() + q('(`$":2001.01.01/partitionedTab/") set .Q.en[`:.] symsEnums (),3;system"l .";partitionedTab' + )._repr_html_() + q('(`$":2001.01.01/partitionedTab/") set .Q.en[`:.] symsEnums (),4;system"l .";partitionedTab' + )._repr_html_() + q('(`$":2001.01.01/partitionedTab/") set .Q.en[`:.] symsEnums (),5;system"l .";partitionedTab' + )._repr_html_() + + # Partitioned + q('(`$":2001.01.01/partitionedTab/") set 0#([] a:.z.d-til 2000;b:til 2000)') + q('system"l ."') + tab = q('partitionedTab') + assert (0, 3, 0) == checkHTML(tab) + + q('(`$":2001.01.01/partitionedTab/") set 1#([] a:.z.d-til 2000;b:til 2000)') + q('system"l ."') + tab = q('partitionedTab') + assert (2, 7, 2) == checkHTML(tab) + + q('(`$":2001.01.01/partitionedTab/") set 2#([] a:.z.d-til 2000;b:til 2000)') + q('system"l ."') + tab = q('partitionedTab') + assert (3, 8, 4) == checkHTML(tab) + + q('(`$":2001.01.01/partitionedTab/") set 10#([] a:.z.d-til 2000;b:til 2000)') + q('system"l ."') + tab = q('partitionedTab') + assert (H+1, 16, 20) == checkHTML(tab) + + q('(`$":2001.01.01/partitionedTab/") set 11#([] a:.z.d-til 2000;b:til 2000)') + q('system"l ."') + tab = q('partitionedTab') + assert (H+1, 16, 20) == checkHTML(tab) + + q('(`$":2001.01.01/partitionedTab/") set 0#([] a:.z.d-til 2000;b:til 2000)') + q('(`$":2001.01.02/partitionedTab/") set 0#([] a:.z.d-til 2000;b:til 2000)') + q('system"l ."') + tab = q('partitionedTab') + assert (0, 4, 0) == checkHTML(tab) + + q('(`$":2001.01.01/partitionedTab/") set 0#([] a:.z.d-til 2000;b:til 2000)') + q('(`$":2001.01.02/partitionedTab/") set 1#([] a:.z.d-til 2000;b:til 2000)') + q('system"l ."') + tab = q('partitionedTab') + assert (2, 9, 3) == checkHTML(tab) + + q('(`$":2001.01.01/partitionedTab/") set 10#([] a:.z.d-til 2000;b:til 2000)') + q('(`$":2001.01.02/partitionedTab/") set 10#([] a:.z.d-til 2000;b:til 2000)') + q('system"l ."') + tab = q('partitionedTab') + assert (H+1, 18, 30) == checkHTML(tab) + + q('(`$":2001.01.01/partitionedTab/") set 1#([] a:.z.d-til 2000;b:til 2000)') + q('(`$":2001.01.02/partitionedTab/") set 0#([] a:.z.d-til 2000;b:til 2000)') + q('system"l ."') + tab = q('partitionedTab') + assert (2, 9, 3) == checkHTML(tab) + + q('(`$":2001.01.01/partitionedTab/") set 35#([] a:.z.d-til 2000;b:til 2000)') + q('(`$":2001.01.02/partitionedTab/") set 0#([] a:.z.d-til 2000;b:til 2000)') + q('system"l ."') + tab = q('partitionedTab') + assert (H+1, 18, 30) == checkHTML(tab) + + q('(`$":2001.01.01/partitionedTab/") set 0#([] a:.z.d-til 2000;b:til 2000)') + q('(`$":2001.01.02/partitionedTab/") set 35#([] a:.z.d-til 2000;b:til 2000)') + q('system"l ."') + tab = q('partitionedTab') + assert (H+1, 18, 30) == checkHTML(tab) + + q('(`$":2001.01.01/partitionedTab/") set 11#([] a:.z.d-til 2000;b:til 2000)') + q('(`$":2001.01.02/partitionedTab/") set 11#([] a:.z.d-til 2000;b:til 2000)') + q('system"l ."') + tab = q('partitionedTab') + assert (H+1, 18, 30) == checkHTML(tab) + + q('(`$":2001.01.01/partitionedTab/") set 0#extraWide') + q('(`$":2001.01.02/partitionedTab/") set 0#extraWide') + q('system"l ."') + tab = q('partitionedTab') + assert (0, 22, 0) == checkHTML(tab) + + q('(`$":2001.01.01/partitionedTab/") set 5#extraWide') + q('(`$":2001.01.02/partitionedTab/") set 0#extraWide') + q('system"l ."') + tab = q('partitionedTab') + assert (6, 49, 105) == checkHTML(tab)