Changelog
PyKX 1.0.2
Deprecations & Removals
- PyKX has been removed from PyPI. It is now only available from the KX Nexus server. The installation instructions have been updated to reflect this.
PyKX 1.0.1
Deprecations & Removals
- The
syncparameter forpykx.QConnectionandpykx.QConnection.__call__has been renamed to the less confusing namewait. Thesyncparameter remains, but its usage will result in aDeprecationWarningbeing emitted. Thesyncparameter will be removed in a future version.
Features & Fixes
- Updated to stable classifier (
Development Status :: 5 - Production/Stable) in project metadata. Despite this update being done in version 1.0.1, version 1.0.0 is still the first stable release of PyKX. - PyKX now provides source distributions (
sdist). It can be downloaded from PyPI usingpip download --no-binary=:all: --no-deps pykx. As noted in the installation docs, installations built from the source will only receive support on a best-effort basis. - Fixed Pandas NaT conversion to q types. Now
pykx.toq(pandas.NaT, ktype=ktype)produces a null temporal atom for any givenktype(e.g.pykx.TimeAtom). - Added a doc page for limitations of embedded q.
- Added a test to ensure large vectors are correctly handled (5 GiB).
- Always use synchronous queries internally, i.e. fix
QConnection(sync=False). - Disabled the context interface over IPC. This is a temporary measure that will be reversed once q function objects are updated to run in the environment they were defined in by default.
- Reduced the time it takes to import PyKX. There are plans to reduce it further, as
import pykxremains fairly slow. - Updated to KXI Core 2.1 & rename
qce->kxic. - Misc test updates.
- Misc doc updates.
PyKX 1.0.0
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.
Pay close attention to the renames listed below, as well as the removals. Many things have been moved to the top-level, or otherwise reorganized. A common idiom with Pykdb was the following:
from pykdb import q, k
It is recommended that the following be used instead:
import pykx as kx
This way the many attributes at the top-level can be easily accessed without any loss of context, for example:
kx.q # Can be called to execute q code
kx.K # Base type for objects in q; can be used to convert a Python object into a q type
kx.SymbolAtom # Type for symbol atoms; can be used to convert a `str` or `bytes` into a symbol atom
kx.QContext # Represents a q context via the PyKX context interface
kx.QConnection # Can be called to connect to a q process via q IPC
kx.PyKXException # Base exception type for exceptions specific to PyKX and q
kx.QError # Exception type for errors that occur in q
kx.LicenseException # Exception type raised when features that require a license are used without
kx.QHOME # Path from which to load q files, set by $QHOME environment variable
kx.QARGS # List of arguments provided to the embedded q instance at startup, set by $QARGS environment variable
# etc.
You can no longer rely on the context being reset to the global context after each call into embedded q, however IPC calls are unaffected.
Renames
- Pykdb has been renamed to PyKX.
Pykdb->PyKX;PYKDB->PYKX;pykdb->pykx. - The
adaptmodule has been renamed totoq, and it can be called directly. Instead ofpykdb.adapt.adapt(x)one should writepykx.toq(x). - The
kmodule has been renamed towrappers. All wrapper classes can be accessed from the top-level, i.e.pykx.K,pykx.SymbolAtom, etc. - The "module interface" (
pykdb.module_interface) has been renamed to the "context interface" (pykx.ctx). Allpykx.Qinstances (i.e.pykx.qand allpykx.QConnectioninstances) have actxattribute, which is the globalQContextfor thatpykx.Qinstance. Usually, one need not directly access the global context. Instead, one can access its subcontexts directly e.g.q.dbmaintinstead ofq.ctx.dbmaint. KdbError(and its subclasses) have been renamed toQErrorpykdb.ctx.KdbContexthas been renamed topykx.ctx.QContext, and is available from the top-level, i.e.pykx.QContext.- The
Connectionclass in the IPC module has been renamed toQConnection, and is now available at the top-level, i.e.pykx.QConnection. - The q type wrapper
DynamicLoadhas been renamed toForeign(pykdb.k.DynamicLoad->pykx.Foreign).
Deprecations & Removals
- The
pykdb.q.ipcattribute has been removed. The IPC module can be accessed directly instead atpykx.ipc, but generally one will only need to access theQConnectionclass, which can be accessed at the top-level:pykx.QConnection. - The
pykdb.q.Kattribute has been removed. Instead,Ktypes can be used as constructors for that type by leveraging thetoqmodule. For example, instead ofpykdb.q.K(x)one should writepykx.K(x). Instead ofpykx.q.K(x, k_type=pykx.k.SymbolAtom)one should writepykx.SymbolAtom(x)orpykx.toq(x, ktype=pykx.SymbolAtom). - Most
KdbError/QErrorsubclasses have been removed, as identifying them is error prone, and we are unable to provide helpful error messages for most of them. - The
pykx.kdbsingleton class has been removed.
Dependencies
- More Numpy, Pandas, and PyArrow versions are supported. Current
pandas~=1.0,numpy~=1.20,<1.22, andpyarrow>=3.0.0are supported. PyArrow remains an optional dependency. - A dependency on
find-libpython~=0.2was added. This is only used when running PyKX under a q process (see details in the section below about new alpha features). - A dependency on the system library
libcurlwas added for Linux. This dependency will be made optional in a future release.
Features & Fixes
- The
pykx.Qclass has been added as the base class forpykx.EmbeddedQ(the class forpykx.q) andpykx.QConnection. - The
pykx.EmbeddedQprocess now perisists its context between calls. - The console now works over IPC.
- The query module now works over IPC. Because
Kobjects hold no reference to theqinstance that created them (be it local or over IPC),Ktables no longer haveselect/exec/update/deletemethods with themselves projected in as the first argument. That is to say, instead of writingt.select(...), writeq.qsql.select(t, ...), whereqis eitherpykx.qor an instance ofpykx.QConnection, andtwas obtained fromq. - The context interface now works over IPC.
- Nulls and infinities are now handled as nulls and infinities, rather than as their underlying values.
pykx.Atom.is_null,pykx.Atom.is_inf,pykx.Collection.has_nulls, andpykx.Collection.has_infshave been added. Numpy, Pandas, and PyArrow handles integral nulls with masked arrays, and they handle temporal nulls withNaT.NaNcontinues to be used for real/float nulls. The general Python representation (from.py()) usesKobjects for nulls and infinities. - Calling
boolonpykx.Kobjects now either raises aTypeError, or return the unambiguously correct result. For ambiguous cases such aspykx.Collectioninstances, use.any(),.all(), or a length check instead. - Assignment to q reserved words or the q context now raises a
pykx.PyKXException. pykx.toq.from_list(previouslypykdb.adapt.adapt_list) now works in unlicensed mode.q.queryandq.sqlare now placeholders (set toNone). The query interface can be accessed fromq.qsql.- Ternary
pownow raisesTypeErrorforRealNumericVectorandRealNumericAtom. QContextobjects are now context handlers, e.g.with pykx.q.dbmaint: # operate in .dbmaint within this block. This context handler supports arbitrary nesting.__getitem__now raises apykx.LicenseExceptionwhen used in unlicensed mode. Previously it worked for a few select types only. If running in unlicensed mode, one should perform all q indexing in the connected q process, and all Python indexing after converting theKobject to a Python/Numpy/Pandas/PyArrow object.pykx.QConnection(previouslypykdb.ipc.Connection) objects now have an informative/idiomatic repr.- Calls to
pykx.qnow support up to 8 arguments beyond the required query at position 0, similar to callingpykx.QConnectioninstances. These arguments are applied to the result of the query. - Embedded q is now used to count the number of rows a table has.
- All dynamic linking to
libqandlibehas been replaced by dynamic loading. As a result, the modules previously known asadaptandadapt_unlicensedhave been unified underpykx.toq. - PyKX now attempts to initialize embedded q when
pykxis imported, rather than whenpykx.qis first accessed. As a result, the error-prone practice of supplying thepykx.kdbsingleton class with arguments for embedded q is now impossible. - Arguments for embedded q can now be supplied via the environment variable
$QARGSin the form of command-line arguments. For example,QARGS='--unlicensed'causes PyKX to enter unlicensed mode when it is started, andQARGS='-o 8'causes embedded q to use an offset from UTC of 8 hours. These could be combined asQARGS='--unlicensed -o 8'. - Added the
--licensedstartup flag (to be provided via the$QARGSenvironment variable), which can be used to raise apykx.PyKXException(rather than emitting a warning) if PyKX fails to start in licensed mode (likely because of a missing/invalid q license). - PyKX Linux wheels are now PEP 600 compliant, built to the
manylinux_2_17standard. - Misc other bug fixes.
- Misc doc improvements.
Performance Improvements
- Converting nested lists from q to Python is much faster.
- Internally, PyKX now calls q functions with arguments directly instead of creating a
pykx.Functioninstance then calling it. This results in modest performance benefits in some cases. - The context interface no longer loads every element of a context when the context is first accessed, thereby removing the computation spike, which could be particularly intense for large q contexts.
New Alpha Features
Alpha features are subject to change
Alpha features are not stable will be subject to changes without notice. Use at your own risk.
- q can now load PyKX by loading the q file
pykx.q.pykx.qcan be copied into$QHOMEby runningpykx.install_into_QHOME(). When loaded into q, it will define the.pykxnamespace, which notably has.pykx.execand.pykx.pyeval. This allows for Python code to be run within q libraries and applications without some of the limitations of embedded q such as the lack of the q main loop, or the lack of timers. When q loadspykx.q, it attempts to source the currently active Python environment by runningpython, then fetching the environment details from it.