Skip to content

0.11.0

Latest

Choose a tag to compare

@x42005e1f x42005e1f released this 31 Dec 23:15
· 6 commits to main since this release
56e8260

Added

  • culsans.__version__ and culsans.__version_tuple__ as a way to retrieve the package version at runtime.
  • culsans.Grouper (initial implementation) as a higher-level synchronization primitive with phase-fair priority policy by default. See x42005e1f/aiologic#19 for details.
  • culsans.RWLock (initial implementation) as a readers-writer lock that is both phase-fair and reentrant. It is currently defined as a subclass of culsans.Grouper, but this may change in the future.
  • culsans.BaseQueueProxy as a common superclass for culsans.SyncQueueProxy and culsans.AsyncQueueProxy. Added to reduce code duplication, but can also be used separately for other purposes (such as checking that an object is an instance of either proxy type).
  • culsans.GreenQueue, culsans.GreenQueueProxy, and methods prefixed with green_, which make the interfaces aiologic-like. They are equivalent to their "sync" alternatives and are preferred for new uses.
  • blocking parameter wherever there is block parameter, as its alias. This change complements the previous one. Note that none of these parameters have been added to async def methods, as this would complicate the implementation, so there is still no full compatibility with aiologic queues (the parameters will be added in the future along with async timeouts).
  • sizer parameter, corresponding isize() public methods, and _isize protected attribute/method (for overriding). Allows to specify the size for each queue item, which affects the put methods. Solves #9.
  • clearable() methods and related culsans.Queue._clearable() protected method (for overriding) analogous to those for peek methods, making implementation of the clear() method optional. Along with this, the clear() method is now also used in the implementation of the shutdown() method, when available.
  • size property, which returns the cumulative size of items in the queue.
  • green_proxy/async_proxy properties as a more generic alternative to sync_q/async_q.
  • The proxies can now be weakly referenced. Previously, this was disallowed due to their limited lifetime (since the corresponding properties return new objects on each access). This is now allowed for cases where a proxy is used as a backport to older versions of Python.
  • A negative queue length is now a valid value and is handled correctly (extends subclassing capabilities).
  • A negative value of the unfinished_tasks property is now treated as infinity (extends subclassing capabilities).

Changed

  • The queues now override __len__() and __bool__(), allowing len(queue) and bool(queue) to be used in the same sense as for collections. And while this change is not conceptually incompatible, in fact it breaks the not-so-good pattern if self.queue: # self.queue is not None.
  • The maxsize property is now defined as the maximum cumulative size of queue items rather than the maximum queue length. This allows arbitrary queue item sizes to be supported, but may require existing code to be modified to work correctly when passing a custom sizer (as this affects both the put methods and the full() methods).
  • The underlying lock is now reentrant. This differs from the standard queue approach, but makes it much easier to create subclasses and also makes culsans.Queue somewhat compatible with sqlalchemy.util.queue.Queue. However, the main reason is not this, but to make the following change efficiently implemented.
  • The queues now rely on new aiologic safety guarantees when using the condition variables. Previously, as with threading.Condition, a KeyboardInterrupt raised during synchronization on the underlying lock after notification led to the lock being over-released and, as a result, to a RuntimeError. Now, aiologic.Condition is used as a context manager, thereby including additional checks on the aiologic side to ensure that the current thread owns the lock when releasing it.
  • The unfinished_tasks property's value now changes according to the queue length change (the value returned by the _qsize() method). This allows to create flattened queues without introducing related additional methods and also corrects the behavior for subclasses that may not change the queue length as a result of insertion.
  • The timeout parameter's value is now checked and converted at the beginning of the method call, regardless of the block parameter's value. This should prevent cases where an incorrect value is passed.
  • The peekability check is now ensured before each call (after each context switch), allowing the peek methods to be enabled/disabled dynamically.
  • The package now relies on aiologic.meta.export() for exports instead of using its own implementation (similar to aiologic==0.15.0), which provides safer behavior. In particular, queue methods now also update their metadata, allowing them to be safely referenced during pickling.
  • The protocols are now inherited from typing_extensions.Protocol on Python below 3.13, which backports all related fixes and improvements to older versions of Python.
  • The shutdown exceptions are now defined again via backports (on Python below 3.13), but in a type-friendly manner.

Fixed

  • The sync methods called the checkpoint function regardless of the block parameter's value. Now they do not make the call in the non-blocking case.
  • Notifications could be insufficient or excessive when the queue length changed differently than in the standard behavior. Now such situations are detected and a different notification mechanism is activated when they are detected.