From 0855137908e36dba817d951c2cd677fab2ed5894 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rian=20=C3=93=20Cuinneag=C3=A1in?= Date: Tue, 2 Dec 2025 12:17:41 +0000 Subject: [PATCH] 3.1.4 --- docs/release-notes/changelog.md | 11 +++++++++ docs/release-notes/underq-changelog.md | 31 +++++++++++++++++++++++++ docs/user-guide/advanced/ipc.md | 2 +- docs/user-guide/advanced/numpy.md | 2 +- pyproject.toml | 1 + src/pykx/core.pyx | 2 +- src/pykx/embedded_q.py | 2 +- src/pykx/nbextension.py | 2 +- src/pykx/pykx.c | 20 ++++++++-------- src/pykx/pykx_init.q_ | Bin 4994 -> 0 bytes src/pykx/q.so/qk/pykx_init.q_ | Bin 4994 -> 5004 bytes src/pykx/toq.pyx | 2 +- src/pykx/wrappers.py | 2 +- tests/__init__.py | 10 -------- tests/qcumber_tests/import.quke | 7 ++++++ tests/test_cloud_edition.py | 24 +++++++++++++++++++ tests/test_sql.py | 5 ++++ tests/win_tests.bat | 16 ++++++------- 18 files changed, 104 insertions(+), 35 deletions(-) delete mode 100644 src/pykx/pykx_init.q_ diff --git a/docs/release-notes/changelog.md b/docs/release-notes/changelog.md index 4964b33..74757c2 100644 --- a/docs/release-notes/changelog.md +++ b/docs/release-notes/changelog.md @@ -4,6 +4,17 @@ 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 3.1.4 + +#### Release Date + +2025-07-17 + +### Fixes and Improvements + +- Resolved error on import when `PYKX_THREADING` was set. +- Fixed an issue where data could be corrupted in keyed columns of PyArrow backed Pandas dataframes. + ## PyKX 3.1.3 #### Release Date diff --git a/docs/release-notes/underq-changelog.md b/docs/release-notes/underq-changelog.md index 4d788c2..69ddac5 100644 --- a/docs/release-notes/underq-changelog.md +++ b/docs/release-notes/underq-changelog.md @@ -6,6 +6,37 @@ 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 3.1.4 + +#### Release Date + +2025-07-17 + +### Fixes and Improvements + +- Resolved `object has no attribute 't'` error for certain conversions + + === "Behaviour prior to change" + + ```python + q).pykx.setdefault (),"k"; + q).pykx.import[`numpy.random][`:choice][01b; 10] + 'AttributeError("'numpy.int64' object has no attribute 't'") + [2] /home/user/q/pykx.q:241: .pykx.util.pykx: + ]; + wrap pyfunc[f] . x]; + ^ + ":"~first a0:string x0; + ``` + + === "Behaviour post change" + + ```python + q).pykx.setdefault (),"k"; + q).pykx.import[`numpy.random][`:choice][01b; 10] + 1011111110b + ``` + ## PyKX 3.1.3 #### Release Date diff --git a/docs/user-guide/advanced/ipc.md b/docs/user-guide/advanced/ipc.md index 7b450fa..1086a29 100644 --- a/docs/user-guide/advanced/ipc.md +++ b/docs/user-guide/advanced/ipc.md @@ -92,7 +92,7 @@ In the below examples you can connect to a process on port 5050 and run a query. ```python >>> conn = await kx.AsyncQConnection('localhost', 5050) - >>> print(await conn('til 10').py()) + >>> print((await conn('til 10')).py()) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> conn.close() ``` diff --git a/docs/user-guide/advanced/numpy.md b/docs/user-guide/advanced/numpy.md index cf49338..c534d1e 100644 --- a/docs/user-guide/advanced/numpy.md +++ b/docs/user-guide/advanced/numpy.md @@ -11,7 +11,7 @@ _This page explains how to integrate PyKX with NumPy._ PyKX is designed for advanced integration with NumPy. This integration is built on three pillars: -- [NEP-49](https://numpy.org/neps/nep-0049.html) +- [NEP-49](https://numpy.org/neps/nep-0049-data-allocation-strategies.html) - the NumPy [array interface](https://numpy.org/doc/stable/reference/arrays.interface.html) - [universal functions](https://numpy.org/doc/stable/reference/ufuncs.html) diff --git a/pyproject.toml b/pyproject.toml index 28d33f7..ee5dc89 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -126,6 +126,7 @@ test = [ "pytest-randomly==3.11.0", "pytest-xdist==2.5.0", "pytest-order==1.1.0", + "pytest-rerunfailures==10.3", "psutil>=5.0.0", "pytest-timeout>=2.0.0", "IPython", diff --git a/src/pykx/core.pyx b/src/pykx/core.pyx index 6068818..a35d287 100644 --- a/src/pykx/core.pyx +++ b/src/pykx/core.pyx @@ -241,7 +241,7 @@ def _link_qhome(): warn('Unable to connect user QHOME to PyKX QHOME via symlinks.\n' # nocov 'To permanently disable attempts to create symlinks you can\n' # nocov '\t1. Set the environment variable "PYKX_IGNORE_QHOME" = True.\n' # nocov - '\t2. Update the file ".pykx.config" using kx.util.add_to_config({\'PYKX_IGNORE_QHOME\': \'True\'})\n' # nocov + '\t2. Update the file ".pykx-config" using kx.util.add_to_config({\'PYKX_IGNORE_QHOME\': \'True\'})\n' # nocov f'Error: {ex}\n', # nocov PyKXWarning) # nocov return # nocov diff --git a/src/pykx/embedded_q.py b/src/pykx/embedded_q.py index 3bfa259..0379adf 100644 --- a/src/pykx/embedded_q.py +++ b/src/pykx/embedded_q.py @@ -214,7 +214,7 @@ def __call__(self, query: The code to run in the q instance. *args: Arguments to the q query. Each argument is converted into a `#!python pykx.K` object. This parameter supports up to 8 args (the maximum amount - supported by q functions), providing more causesw an error. + supported by q functions), providing more causes an error. wait: A keyword to allow users to call any `#!python pykx.EmbeddedQ` or `#!python pykx.QConnection` instance the same way. All queries executed by this function are synchronous on the embedded q instance. Using a `#!python False` diff --git a/src/pykx/nbextension.py b/src/pykx/nbextension.py index 250a7e0..0955a43 100644 --- a/src/pykx/nbextension.py +++ b/src/pykx/nbextension.py @@ -188,7 +188,7 @@ def write_to_q_file(_q, locked, path, code): if locked: output_file = Path(path[:-1]) _q('0:', output_file, [kx.CharVector(code)]) - _q('\_ ' + path[:-1]) + _q('\\_ ' + path[:-1]) _q('hdel', output_file) else: output_file = Path(path) diff --git a/src/pykx/pykx.c b/src/pykx/pykx.c index adafe65..0a9b75e 100644 --- a/src/pykx/pykx.c +++ b/src/pykx/pykx.c @@ -217,7 +217,7 @@ static PyObject* k_to_py_list(K x) { EXPORT K k_to_py_foreign(K x, K typenum, K israw) { K k; if (pykx_threading) - return raise_k_error("pykx.q is not supported when using PYKX_THREADING"); + return raise_k_error("pyForeign is not supported when using PYKX_THREADING"); PyGILState_STATE gstate; gstate = PyGILState_Ensure(); PyObject* p = k_to_py_cast(x, typenum, israw); @@ -291,7 +291,7 @@ void construct_args_kwargs(PyObject* params, PyObject** args, PyObject** kwargs, EXPORT K k_pyrun(K k_ret, K k_eval_or_exec, K as_foreign, K k_code_string) { if (pykx_threading) - return raise_k_error("pykx.q is not supported when using PYKX_THREADING"); + return raise_k_error("pyrun is not supported when using PYKX_THREADING"); PyGILState_STATE gstate; gstate = PyGILState_Ensure(); K k; @@ -435,7 +435,7 @@ EXPORT K k_modpow(K k_base, K k_exp, K k_mod_arg) { EXPORT K foreign_to_q(K f, K b) { if (pykx_threading) - return raise_k_error("pykx.q is not supported when using PYKX_THREADING"); + return raise_k_error("foreignToq is not supported when using PYKX_THREADING"); if (f->t != 112) return raise_k_error("Expected foreign object for call to .pykx.toq"); if (!check_py_foreign(f)) @@ -483,7 +483,7 @@ EXPORT K foreign_to_q(K f, K b) { EXPORT K repr(K as_repr, K f) { if (pykx_threading) - return raise_k_error("pykx.q is not supported when using PYKX_THREADING"); + return raise_k_error("repr is not supported when using PYKX_THREADING"); K k; if (f->t != 112) { if (as_repr->g){ @@ -526,7 +526,7 @@ EXPORT K repr(K as_repr, K f) { EXPORT K get_attr(K f, K attr) { if (pykx_threading) - return raise_k_error("pykx.q is not supported when using PYKX_THREADING"); + return raise_k_error("getattr is not supported when using PYKX_THREADING"); K k; if (f->t != 112) { if (f->t == 105) { @@ -555,7 +555,7 @@ EXPORT K get_attr(K f, K attr) { EXPORT K get_global(K attr) { if (pykx_threading) - return raise_k_error("pykx.q is not supported when using PYKX_THREADING"); + return raise_k_error("getGlobal is not supported when using PYKX_THREADING"); K k; if (attr->t != -11) { return raise_k_error("Expected a SymbolAtom for the attribute to get in .pykx.get"); @@ -582,7 +582,7 @@ EXPORT K get_global(K attr) { EXPORT K set_global(K attr, K val) { if (pykx_threading) - return raise_k_error("pykx.q is not supported when using PYKX_THREADING"); + return raise_k_error("setGlobal is not supported when using PYKX_THREADING"); K k; int gstate = PyGILState_Ensure(); @@ -608,7 +608,7 @@ EXPORT K set_global(K attr, K val) { EXPORT K set_attr(K f, K attr, K val) { if (pykx_threading) - return raise_k_error("pykx.q is not supported when using PYKX_THREADING"); + return raise_k_error("setattr is not supported when using PYKX_THREADING"); if (f->t != 112) { if (f->t == 105) { return raise_k_error("Expected foreign object for call to .pykx.setattr, try unwrapping the foreign object with `."); @@ -638,7 +638,7 @@ EXPORT K set_attr(K f, K attr, K val) { EXPORT K import(K module) { if (pykx_threading) - return raise_k_error("pykx.q is not supported when using PYKX_THREADING"); + return raise_k_error("import is not supported when using PYKX_THREADING"); K k; K res; if (module->t != -11) @@ -660,7 +660,7 @@ EXPORT K import(K module) { EXPORT K call_func(K f, K has_no_args, K args, K kwargs) { if (pykx_threading) - return raise_k_error("pykx.q is not supported when using PYKX_THREADING"); + return raise_k_error("import is not supported when using PYKX_THREADING"); K k; PyObject* pyf = NULL; diff --git a/src/pykx/pykx_init.q_ b/src/pykx/pykx_init.q_ deleted file mode 100644 index e81c0a590d438d9aba511ca52552f460636dc7a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4994 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 literal 4994 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.xT(core.r1(_k(index_dict))), False) elif isinstance(x, _supported_pandas_index_types_via_numpy): - return from_numpy_ndarray(x.to_numpy(), cast=cast, handle_nulls=handle_nulls) + return from_numpy_ndarray(x.to_numpy().copy(), cast=cast, handle_nulls=handle_nulls) else: raise _conversion_TypeError(x, 'Pandas index', ktype) diff --git a/src/pykx/wrappers.py b/src/pykx/wrappers.py index 1160942..9766a92 100644 --- a/src/pykx/wrappers.py +++ b/src/pykx/wrappers.py @@ -594,7 +594,7 @@ def __array_ufunc__(self, ufunc, method, *inputs, **kwargs): **kwargs ) - if res.t >= 0: + if isinstance(res, K) and res.t >= 0: res = res._unlicensed_getitem(0) return res diff --git a/tests/__init__.py b/tests/__init__.py index 6d31cca..b9b542e 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -12,16 +12,6 @@ os.environ['PYTHONWARNINGS'] = 'ignore:No data was collected,ignore:Module pykx was never imported' - -# Addition of configuration toml used in testing -# The configuration values set here are the default values for the PyKX so should not -# 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) -config_file.close() - - if system() != 'Windows': if threading.current_thread() == threading.main_thread(): signal.signal(signal.SIGUSR1, lambda *_: None) diff --git a/tests/qcumber_tests/import.quke b/tests/qcumber_tests/import.quke index 8101657..be97a89 100644 --- a/tests/qcumber_tests/import.quke +++ b/tests/qcumber_tests/import.quke @@ -17,3 +17,10 @@ feature .pykx.import @[{.pykx.import x; 0b}; "a"; {x like "Module to be imported must be a symbol"}] + + should allow generation of random objects + expect generation without errors + def:.pykx.setdefault (),"k"; + imp:.pykx.import[`numpy.random][`:choice][01b; 10]`; + 10 = count imp + \ No newline at end of file diff --git a/tests/test_cloud_edition.py b/tests/test_cloud_edition.py index 3d819c6..bbdc363 100644 --- a/tests/test_cloud_edition.py +++ b/tests/test_cloud_edition.py @@ -262,6 +262,10 @@ def test_objstor_aws_read1(q, kx): assert isinstance(res, kx.ByteVector) +@pytest.mark.skipif( + os.getenv('PYKX_THREADING') is not None, + reason='ToDo investigate in KXI-63220' +) def test_qlog_fd_stdout_endpoint(q): """Test STDOUT endpoint creation.""" q('.com_kx_log.fd.i.write:{.fd.cache,:enlist(x;y)}') @@ -274,6 +278,10 @@ def test_qlog_fd_stdout_endpoint(q): q('.com_kx_log.lcloseAll[]') +@pytest.mark.skipif( + os.getenv('PYKX_THREADING') is not None, + reason='ToDo investigate in KXI-63220' +) def test_qlog_fd_stderr_setup(q): """Tests creation of stderr endpoint.""" q('id:.com_kx_log.lopen[`:fd://stderr]') @@ -282,6 +290,10 @@ def test_qlog_fd_stderr_setup(q): q('.com_kx_log.lcloseAll[]') +@pytest.mark.skipif( + os.getenv('PYKX_THREADING') is not None, + reason='ToDo investigate in KXI-63220' +) def test_qlog_fd_stdout_log_string(q): """Test default string logging.""" q('.com_kx_log.fd.i.write:{.fd.cache,:enlist(x;y)}') @@ -300,6 +312,10 @@ def test_qlog_fd_stdout_log_string(q): q('.com_kx_log.lcloseAll[]') +@pytest.mark.skipif( + os.getenv('PYKX_THREADING') is not None, + reason='ToDo investigate in KXI-63220' +) def test_qlog_fd_stdout_custom_log(q): """Tests custom string logging.""" q('.com_kx_log.fd.i.write:{.fd.cache,:enlist(x;y)}') @@ -316,6 +332,10 @@ def test_qlog_fd_stdout_custom_log(q): q('.com_kx_log.lcloseAll[]') +@pytest.mark.skipif( + os.getenv('PYKX_THREADING') is not None, + reason='ToDo investigate in KXI-63220' +) def test_qlog_fd_stdout_dict_log(q): """Tests dictionary message logging.""" q('.com_kx_log.fd.i.write:{.fd.cache,:enlist(x;y)}') @@ -330,6 +350,10 @@ def test_qlog_fd_stdout_dict_log(q): q('.com_kx_log.lcloseAll[]') +@pytest.mark.skipif( + os.getenv('PYKX_THREADING') is not None, + reason='ToDo investigate in KXI-63220' +) def test_qlog_fd_file_publish(q): """Tests logging message to file.""" q('.com_kx_log.fd.i.write:{.fd.cache,:enlist(x;y)}') diff --git a/tests/test_sql.py b/tests/test_sql.py index 01da07e..336c9aa 100644 --- a/tests/test_sql.py +++ b/tests/test_sql.py @@ -1,4 +1,5 @@ # Do not import pykx here - use the `kx` fixture instead! +import os from abc import ABCMeta import pytest @@ -163,6 +164,10 @@ def test_sql_get_input_values(q, kx): assert q.sql.get_input_types(p2) == ['SymbolAtom/SymbolVector', 'FloatAtom/FloatVector'] +@pytest.mark.skipif( + os.getenv('PYKX_THREADING') is not None, + reason='ToDo investigate in KXI-63220' +) @pytest.mark.embedded def test_sql_string_col(q): q('t:([] optid:1 2 3;Market:`a`b`CBOE;date:3#2023.11.14;Symbol:("a";"b";"odMP=20"))') diff --git a/tests/win_tests.bat b/tests/win_tests.bat index 0cbfff6..5435a21 100644 --- a/tests/win_tests.bat +++ b/tests/win_tests.bat @@ -2,21 +2,21 @@ python .\parse_tests.py cd .. -python -m pytest -vvv -n 0 --no-cov --junitxml=licensed_report.xml .\tests\win_tests\lic\licensed_tests.py +python -m pytest -vvv -n 0 --no-cov --color=yes --reruns=5 --junitxml=licensed_report.xml .\tests\win_tests\lic\licensed_tests.py SET /A licensed = %ERRORLEVEL% -python -m pytest -vvv -n 0 --no-cov --junitxml=unlicensed_report.xml .\tests\win_tests\unlic\unlicensed_tests.py +python -m pytest -vvv -n 0 --no-cov --color=yes --reruns=5 --junitxml=unlicensed_report.xml .\tests\win_tests\unlic\unlicensed_tests.py SET /A unlicensed = %ERRORLEVEL% -python -m pytest -vvv -n 0 --no-cov --junitxml=ipc_licensed_report.xml .\tests\win_tests\ipc_lic\ipc_licensed_tests.py +python -m pytest -vvv -n 0 --no-cov --color=yes --reruns=5 --junitxml=ipc_licensed_report.xml .\tests\win_tests\ipc_lic\ipc_licensed_tests.py SET /A ipc_licensed = %ERRORLEVEL% -python -m pytest -vvv -n 0 --no-cov --junitxml=ipc_unlicensed_report.xml .\tests\win_tests\ipc_unlic\ipc_unlicensed_tests.py +python -m pytest -vvv -n 0 --no-cov --color=yes --reruns=5 --junitxml=ipc_unlicensed_report.xml .\tests\win_tests\ipc_unlic\ipc_unlicensed_tests.py SET /A ipc_unlicensed = %ERRORLEVEL% -python -m pytest -vvv -n 0 --no-cov --junitxml=embedded_report.xml .\tests\win_tests\embedded\embedded_tests.py +python -m pytest -vvv -n 0 --no-cov --color=yes --reruns=5 --junitxml=embedded_report.xml .\tests\win_tests\embedded\embedded_tests.py SET /A embedded = %ERRORLEVEL% -python -m pytest -vvv -n 0 --no-cov --junitxml=nep_licensed_report.xml .\tests\win_tests\nep_lic\nep_licensed_tests.py +python -m pytest -vvv -n 0 --no-cov --color=yes --reruns=5 --junitxml=nep_licensed_report.xml .\tests\win_tests\nep_lic\nep_licensed_tests.py SET /A nep_licensed = %ERRORLEVEL% -python -m pytest -vvv -n 0 --no-cov --junitxml=nep_unlicensed_report.xml .\tests\win_tests\nep_unlic\nep_unlicensed_tests.py +python -m pytest -vvv -n 0 --no-cov --color=yes --reruns=5 --junitxml=nep_unlicensed_report.xml .\tests\win_tests\nep_unlic\nep_unlicensed_tests.py SET /A nep_unlicensed = %ERRORLEVEL% -python -m pytest -vvv -n 0 --no-cov --junitxml=pandas_licensed_report.xml .\tests\win_tests\pandas_lic\pandas_licensed_tests.py +python -m pytest -vvv -n 0 --no-cov --color=yes --reruns=5 --junitxml=pandas_licensed_report.xml .\tests\win_tests\pandas_lic\pandas_licensed_tests.py SET /A pandas_licensed = %ERRORLEVEL% IF %licensed% NEQ 0 ( exit %licensed%