All notable changes to this project are documented in this file. The format is based on Keep a Changelog. This project adheres to Semantic Versioning.
Also, at the bottom of this file there is a TODO list with planned future changes.
*: Switched to python-v3.13, black-v25.1.0, mypy-v1.20.1, pylint-v4.0.6, edited all the code to pass all the checks.
python-v3.13 or later is required now.
Renamed kisstdlib/sorted.py -> kisstdlib/collections_ext.py.
kisstdlib/base.py:
SupportsCmp, SupportsCounting, and is_closer, the latter of which replaced nearer_to_than.Number and AndNumber.TypeVars and ParamSpecs, since they are no longer needed with the new python-v3.13 features.AVG_MONTH and AVG_YEAR.kisstdlib/itertools_ext.py:
count_from_to -> range_.count_, since normal count can do the same thing with the same types now.kisstdlib/collections_ext.py:
*SortedIndex classes and their internals. The new versions are more general and better-typed.AbstractSortedIndex -> ABCIndex, SortedIndex -> SortedDictIndex, their methods, and almost everything else related.DictIndex, which SortedDictIndex is now a sub-class of.kisstdlib/sqlite3_ext.py:
AppDB.upgrade.AppDB configurable.kisstdlib/fs.py:
DeferredSync -> Deferred.kisstdlib/parsing:
unread, thus making the Parser’s buffer immutable.leftovers from property -> function.kisstdlib/time.py:
TimeStamp -> TimeStamp, TimeRange -> TimeRange.TimeValue.TimeStamp and TimeRange, renamed now -> from_now.kisstdlib/time.py: *.format*:
TimeFormatter, which is a strftime-like string.Formatter.precisions to work properly in custom fmts.fmt = "@" support, since it can be expressed normally now.format_org_delta -> format_delta.format3.format_org using format3, making it use the time format identical to that of Emacs org-mode.formatting, all these function use the inherent precision of the underlying Decimal by default now..format print the time zone by default (see below).inf_fmt arguments to all these functions to allow control over how the infinite timestamps should be formatted.kisstdlib/time.py: *parse*:
parse_* functions into static methods of their corresponding classes.parsing machinery properly.TimeStamps can be bracketed too now.TimeStamp.parse_iso_like now admits more time formats, including the one produced by Emacs org-mode.TimeStamp.parse_absolute now admits negative values and infinities.run_parser(TimeRange.parse, "<date1>--<date2>") no longer includes all of date2. The old semantics can be recovered by adding “.$” at the end of that expression (see below).devscript/test-cli-lib.sh:
start -> begin.start as a predicate.end bits optional.kisstdlib/base.py:
noop and noop_.kisstdlib/collections_ext.py:
collections.LRUCache.kisstdlib/io/base.py:
BytesIOReader by importing it from hoardy_web/tool/hoardy_web/source.py.kisstdlib/{io/base.py, fs.py}:
chunk_size arguments to fileobj_data_equals, same_file_data, and file_data_equals.kisstdlib/sqlite3_ext.py:
SortedSqliteIndex as a sub-class of ABCIndex.kisstdlib/failure.py:
CatastrophicFailure and its sub-classes, introduced subsume method and its __init__ equivalent.kisstdlib/time.py:
TimeRange is a total_ordering now.
Introduced TimeStamp.gmtoff and proper support for time zones:
TimeStamp to be a Decimal with an additional gmtoff attribute.TimeStamp methods to propagate that value around properly..parse* and .format* take gmtoff as an argument:
.parse* use their gmtoff arguments if the input does not specify a time zone and make them set gmtoff from the input when it does..format to override self.gmtoff, which it now does by default to force user’s local time zone by default.TimeFormatter..parse* functions to be run with time zone parsing disabled.Introduced TimeFun and its dependencies.
TimeFun represents a declaratively defined function over TimeStamps.
E.g., parsing “+1y2m3h” and then applying the result to a TimeStamp will move it one year, two months, and three hours forward.
The list of supported operations is pretty simple, but their compositions can be used to produce rather advanced results.
For the use cases where TimeFun gets applied to TimeStamp.from_now() or similar, there’s also TimeFun.parse_human static method that admits human-readable strings and turns them into the appropriate TimeFuns, e.g.:
TimeStamps;Generalized TimeRange.parse to admit TimeFuns and mixes of TimeStamps and TimeFuns, which is why now it also takes an additional argument of now: TimeStamp.
As a result, it can now parse and compute TimeRanges for expressions like “today”, “today-1y–last_week+1d”, etc.
Also, notably, this parser now also admits .^ and .$ operations, which shrink the previous time interval into a single point, corresponding to its start or end, respectively.
Thus, the old behaviour for, e.g., 2024--2025, previously parsed as 2024-01-01--2026-01-01 and now parsed as 2024-01-01--2025-01-01 (see “Incompatible changes” above), can be recovered with 2024--2025.$.
TimeRange.parse now also admits more delimiters, not just “–” between its two parts, when both are specified.
kisstdlib/time.py:
TimeRange.delta to return an actual Decimal and not a sub-class.TimeRange.middle and .delta produce results for all possible ranges now, instead of failing with decimal.InvalidOperation for some of them.*:
kisstdlib/fs.py: realdir: Fixed realdir(".") to work as expected.
kisstdlib/itertools_ext.py: nth: Fixed a bug.
kisstdlib/parsing.py, kisstdlib/io/adapter.py: Implemented BytesTransformer and its IO-adapter friends.
test/test_basics.py: Added better tests for nth.
test/test_parsing.py, test/test_io.py: Added tests for BytesTransformer adapters.
kisstdlib/io/adapter.py: UpdateFinalizeReader: Reordered arguments a bit.
kisstdlib/sqlite3_ext.py: Improved debug messages.
kisstdlib.fs: introduced realdir.
kisstdlib.io.adapter: imported from hoardy-adb/hoardy_adb/__main__.py, improved a bit.
kisstdlib.argparse_ext: Removed store_map and append_map.
These can be implemented with mainstream argparse by simply setting type=func.
Updated for mypy v1.14.1.
kisstdlib.fs: setup_fs: put pid in front of prog.
kisstdlib.signal_ext: Introduced GentleSignalInterrupt simplifying the API usage a bit.
kisstdlib.base: Now re-exports partial and partialmethod.
kisstdlib.string_ext: Introduced path_escaper and related singletons.
kisstdlib.logging_ext:ANSILogHandler: Simplified the API by merging rollback functionality into flush.
kisstdlib.fs:
Introduced atomic_unlink.
Introduced setup_fs, making temp file suffixes configurable.
Also, kisstdlib:setup_kisstdlib now runs this function too.
kisstdlib.signal_ext: From now on, delay_signal_handler will flush delayed signals when raising SignalInterrupt.
This prevents raise_first_delayed_signal and raise_delayed_signals from raising them again, which was a bug.
kisstdlib.io.stdio: Fixed printf to count implicit eols properly.
kisstdlib.fs:
iter_subtree: Fixed error format.
atomic_make_file: Added fsync before rename, which should have been there.
kisstdlib:run_kisstdlib_main: Now handles BrokenPipeErrors when finishing up.
devscript/test-cli-lib.sh: Improved a bit.
kisstdlib.argparse_ext.py:
Renamed and registered OptionallyMarkdownHelpAction as help_omd, similarly to how argparse does it.
Introduced store_map and append_map actions.
Which do the same thing as store and append, but map values with a given function.
kisstdlib.fs:
Replace fsdecode_maybe and fsencode_maybe with imports from os.
Those functions have this functionality too.
DeferredSync:
Renamed commit -> sync, finish -> flush.
Action deference can now be optional, i.e. DeferredSync can now be used to only defer the fsync alone.
atomic_*:
Renamed dsync arguments -> sync, now allowing them to be bools.
I.e., added no-fsync/async mode to all of those functions.
Added prog program name and its pid to temp file suffixes.
Though, it’s configurable via setup_fs.
kisstdlib:setup_kisstdlib: Simplified the API a bit.
Users should now call setup_delay_signals themselves if they need non-default signals.
Renamed kisstdlib.argparse.better module -> kisstdlib.argparse_ext.
Renamed kisstdlib.util module -> kisstdlib.base.
Renamed kisstdlib.logging module -> kisstdlib.logging_ext.
kisstdlib.base:
(In|Out|Extra)Type -> (A|B|E)Type.Decimal here.NumericType here.NumericType -> AnyNumber.BytesLike and byte sizes here.str_Exception -> get_traceback, generalized it a bit.map_optionals -> map_optional2list.compose_*calls into a single compose_pipe.kisstdlib.fs:
walk_orderly -> iter_subtree, improved its type.describe_walk -> describe_forest.describe_forest.fsync_path -> fsync_file.fsync_many_paths -> fsync_many_files.unlink_many_paths -> unlink_manyunlink_many and fsync_many_files.makedirs arguments to all relevant functions.kisstdlib.sorted:SortedIndex:
Generalized it into an AbstractSortedIndex with the original SortedIndex as its implementation.
Renamed all internal API methods to internal_*.
kisstdlib.io.wrapper:TIOWrappedWriter:
eol to be str.kisstdlib.io.stdio:
sys.std(in|out|err).kisstdlib.logging_ext:
CountHandler -> LogCounter.LogCounter:
Handler instead, for thread safety.INFO as debugs.kisstdlib.base:
Number type with a bunch of operations for it.Missing and MISSING.identity_, const, const_.Maybe, maybe, map_maybe, map_maybe2list.Either, either, map_left, map_right.optional, optional2list.fst, snd.singleton, optlist, optslist.first_def and first_ok.flat_exceptions.kisstdlib.string_ext:
abbrev.StringLexer, which is a simple parser generator for simple string lexing syntaxes.escaper, escape, unescape, which do lex-style string processing.quoter, url_quote, url_unquote, which do what similar urllib.parse functions do, but faster, and with more options.kisstdlib.fs:
same_file_data and same_symlink_data.sep and sepb.hash_file and sha256_file.kisstdlib.itertools_ext:
diff_sorted.kisstdlib.time:Timestamp
__add__ and __sub__.kisstdlib.sorted:AbstractSortedIndex, kisstdlib.sorted:SortedIndex:
In internal_from_to:
Introduced internal_from_to_step which adds stepping support to any internal_from_to.
Introduced iter_range which adds predicate support to internal_from_to_step.
Introduced a bunch of other convenience functions.
kisstdlib.sqlite3_ext:
sqlite3-related stuff.kisstdlib.signal_ext:
kisstdlib.getpass_ext:
getpass-related stuff.kisstdlib.io.wrapper:TIOWrappedWriter:
terminal_size API.Also, note that TIOWrappedWriter, by default, will automatically fallback to non-ANSI plain-text mode when the output is not a TTY of when NO_COLOR=1 environment variable is set.
Also, those newly introduced ansi_* API functions fallback to plain-text output when ANSI mode is disabled in a way that is designed to work pretty well with very little care taken in the code that uses them.
I.e. you can just color things, draw boxes, scroll text around, and etc without care, and it will make the output readable in plain-text mode for you for free.
kisstdlib.io.stdio:
setup_stdio.printf and printf_err with ANSI TTY color support.kisstdlib.logging_ext:
ANSILogHandler, which use printf to render the log very prettily on an ANSI TTY.die.setup_logging.logging.kisstdlib.fs:
describe_path, describe_forest is simple enough now.kisstdlib.base:
first with a more general version in itertools_ext.kisstdlib.fs:iter_subtree:
From now on it will sort directories as if they have os.path.sep after their name.
Otherwise, list(map(first, iter_subtree(..., include_directories=False))) won’t be sorted.
This was broken since 730b1422ea6714349693163f6ae9965a80c00c5d.
Also, added those separators to the outputs of describe_forest.
kisstdlib.failure:CatastrophicFailure:
__repr__.kisstdlib.sorted:
internal_from_nearest found by tests.kisstdlib.argparse_ext:
BetterArgumentParser, fixed it to properly format subparser headers to arbitrary depth.kisstdlib.argparse_ext:
kisstdlib.io.stdio and kisstdlib.logging_ext.BetterArgumentParser.format_help, make it play better with default argparse things.MarkdownBetterHelpFormatter produce proper Markdown headers independent of width.BetterArgumentParser defaults.kisstdlib.argparse_ext:
OptionallyMarkdownHelpAction.--help and --markdown directly in BetterArgumentParser.make_argparser_and_run.kisstdlib:
setup_kisstdlib and run_kisstdlib_main.Examples:
Tests:
./test/* unit tests../test-example.sh with fixed-output tests testing that examples produce the same results between versions.Renamed describe-dir script -> describe-forest.
describe-forest:
describe-forest--help.describe-forest --version.test-cli-lib.sh:
*:
test/* directory to remove them from resulting installations.DeferredSync and its atomic_* friends.atomic_move now has follow_symlinks = False by default, like mv(1) does.hoardy-web.DeferredSync and its atomic_* friends.walk_orderly: fixed include_files filtering.fsyncing of directories on Linux. The previous Windows support fix broke it.hoardy-* projects.black.pylint.walk_orderly:
walk_orderly:
order_by argument.Support me via: