Skip to main content

btx_lib_list

CI CodeQL License: MIT Open in Codespaces PyPI PyPI - Downloads Code Style: Ruff codecov Maintainability security: bandit

  • small list helpers

Install

pip install btx_lib_list

For alternative install paths (pipx, uv, source builds, etc.), see INSTALL.md. All supported methods register both the btx_lib_list and btx-lib-list commands on your PATH.

Python 3.13+ Baseline

  • The project now targets Python 3.13 and newer only. All compatibility shims for older interpreters and legacy tool outputs have been removed; the automation helpers now lean on modern conveniences such as Path.unlink(missing_ok=True) and standard-library shutil.which() lookups.
  • Runtime dependencies stay on the current stable releases (rich-click>=1.9.3 and lib_cli_exit_tools>=2.0.0), while the development extra trims unused packages (notably pytest-asyncio) and keeps pytest, ruff, pyright, bandit, build, twine, codecov-cli, pip-audit, textual, and import-linter pinned to their newest majors.
  • CI workflows now exercise GitHub's rolling runner images (ubuntu-latest, macos-latest, windows-latest) and cover CPython 3.13 alongside the latest available 3.x release provided by Actions.

Why we recommend uv: supply-chain protection

This repository commits a uv.lock. It pins every package the project needs, transitive dependencies included, to an exact version and to the hashes of that version's files. The exclude-newer setting under [tool.uv] in pyproject.toml adds a cooldown: uv leaves any release younger than that out of the lock. CI installs from the lock, so a hijacked release that gets pulled again within the cooldown never reaches our builds, and a file whose hash does not match is refused.

That protection stays in this repository. The installable package declares only lower bounds (>=) for its dependencies, so a plain pip install takes the newest release of every transitive dependency at the moment you run it. If one of them was hijacked an hour earlier, you get the hijacked version. pipx install and uv tool install without options do the same.

To install the command line tool with a cooldown of your own (uv then skips any release younger than 7 days, transitive ones included), or to run the exact tree our CI tests:

uv tool install --exclude-newer "7 days" btx_lib_list
git clone https://github.com/bitranox/btx_lib_list.git && cd btx_lib_list && uv sync --locked && uv run btx_lib_list --help

If you depend on btx_lib_list in your own project, give that project the same cooldown (7 days here, as an example) and commit the uv.lock that uv add btx_lib_list writes:

[tool.uv]
exclude-newer = "7 days"

Usage

The CLI leverages rich-click so help output, validation errors, and prompts render with Rich styling while keeping the familiar click ergonomics. The scaffold keeps a CLI entry point so you can validate packaging flows, but it currently exposes a single informational command while logging features are developed:

btx_lib_list info
btx_lib_list hello
btx_lib_list fail
btx_lib_list --traceback fail
btx-lib-list info
python -m btx_lib_list info

For library use you can import the documented helpers directly:

import btx_lib_list

btx_lib_list.emit_greeting()
try:
    btx_lib_list.raise_intentional_failure()
except RuntimeError as exc:
    print(f"caught expected failure: {exc}")

btx_lib_list.print_info()

Development Quickstart

These steps assume Python 3.13+ (the same baseline enforced by pyproject.toml).

make dev           # install the project in editable mode with dev extras
make test          # run linting, type checks, docs/doctests, and pytest
python -m pytest   # thanks to pytest's configured pythonpath, this now works without extra env vars

The CLI fixtures exercise the lib_list helpers directly, so any changes to the legacy compatibility layer should be accompanied by matching updates in tests/test_lib_list.py.

Public API

The helpers are available directly off the package root (btx_lib_list.<function_name>). The summaries below describe the behaviour and intended use of each helper.

btx_lib_list.deduplicate(elements: list[Any]) -> list[Any]

Removes duplicate, hashable values from elements without preserving order. Used when older CLI flows accidentally emit repeat arguments.

Docs: Module Reference

Example:

>>> from btx_lib_list import deduplicate
>>> deduplicate([])
[]
>>> sorted(deduplicate(['c', 'b', 'a']))
['a', 'b', 'c']
>>> sorted(deduplicate(['b', 'a', 'c', 'b', 'a']))
['a', 'b', 'c']
>>> sorted(deduplicate(['x', 'x', 'x', 'y', 'y']))
['x', 'y']

btx_lib_list.del_elements_containing(elements: list[str], search_string: str) -> list[str]

Returns a new list that excludes any string containing search_string. Handy for pruning blacklisted patterns before issuing filesystem calls.

Docs: Module Reference

Example:

>>> from btx_lib_list import del_elements_containing
>>> del_elements_containing(['a', 'abba', 'c'], 'b')
['a', 'c']
>>> del_elements_containing(['a', 'abba', 'c'], 'z')
['a', 'abba', 'c']
>>> del_elements_containing(['a', 'abba', 'c'], '')
['a', 'abba', 'c']
>>> del_elements_containing([], 'b')
[]

btx_lib_list.filter_contains(elements: list[Any], search_string: str) -> list[str]

Collects only the string entries that contain search_string. When the search text is blank every string element is returned.

Docs: Module Reference

Example:

>>> from btx_lib_list import filter_contains
>>> filter_contains([], 'bc')
[]
>>> filter_contains(['abcd', 'def', 1, None], 'bc')
['abcd']
>>> filter_contains(['abc'], '')
['abc']
>>> filter_contains(['abc', 123], '')
['abc']

btx_lib_list.filter_fnmatch(elements: list[Any], search_pattern: str) -> list[str]

Applies fnmatch to each string element and returns the ones that match the shell-style pattern (non-strings are ignored).

Docs: Module Reference

Example:

>>> from btx_lib_list import filter_fnmatch
>>> filter_fnmatch([], 'a*')
[]
>>> filter_fnmatch(['abc', 'def', 1, None], 'a*')
['abc']

btx_lib_list.is_element_containing(elements: list[str], search_string: str) -> bool

Returns True if any string in elements contains search_string, enabling cheap guards before more expensive checks.

Docs: Module Reference

Example:

>>> from btx_lib_list import is_element_containing
>>> is_element_containing([], '')
False
>>> is_element_containing(['abcd', 'def', 1, None], '')
True
>>> is_element_containing(['abcd', 'def', 1, None], 'bc')
True
>>> is_element_containing(['abcd', 'def', 1, None], 'fg')
False

btx_lib_list.is_fnmatching(elements: list[Any], search_pattern: str) -> bool

Boolean probe that reports whether at least one string matches the given fnmatch pattern.

Docs: Module Reference

Example:

>>> from btx_lib_list import is_fnmatching
>>> is_fnmatching([], 'bc')
False
>>> is_fnmatching(['abcd', 'def', 1, None], '*bc*')
True
>>> is_fnmatching(['abcd', 'def', 1, None], '*1*')
False

btx_lib_list.is_fnmatching_one_pattern(elements: list[Any], search_patterns: list[str]) -> bool

Iterates over multiple patterns and returns True if any of them match one of the string elements.

Docs: Module Reference

Example:

>>> from btx_lib_list import is_fnmatching_one_pattern
>>> is_fnmatching_one_pattern([], [])
False
>>> is_fnmatching_one_pattern(['abcd', 'def', 1, None], [])
False
>>> is_fnmatching_one_pattern(['abcd', 'def', 1, None], ['*bc*', '*fg*'])
True
>>> is_fnmatching_one_pattern(['abcd', 'def', 1, None], ['*fg*', '*gh*'])
False

btx_lib_list.substract_all_keep_sorting(minuend: list[Any], subtrahend: list[Any]) -> list[Any]

Mutates minuend by removing every occurrence of values found in subtrahend while preserving the original order.

Docs: Module Reference

Example:

>>> from btx_lib_list import substract_all_keep_sorting
>>> substract_all_keep_sorting([], ['a'])
[]
>>> substract_all_keep_sorting(['a', 'a'], [])
['a', 'a']
>>> minuend = ['a', 'a', 'b']
>>> substract_all_keep_sorting(minuend, ['a', 'c'])
['b']

btx_lib_list.substract_all_unsorted_fast(minuend: list[Any], subtrahend: list[Any]) -> list[Any]

Creates a new list representing the set difference between the two lists (order is not guaranteed).

Docs: Module Reference

Example:

>>> from btx_lib_list import substract_all_unsorted_fast
>>> substract_all_unsorted_fast(['a', 'a', 'b'], ['a', 'c'])
['b']
>>> substract_all_unsorted_fast(['a', 'a', 'b'], ['b'])
['a']

btx_lib_list.ls_del_empty_elements(ls_elements: list[Any]) -> list[Any]

Drops any falsey values ("", None, 0, etc.) from the provided list.

Docs: Module Reference

Example:

>>> from btx_lib_list import ls_del_empty_elements
>>> ls_del_empty_elements([])
[]
>>> ls_del_empty_elements(['', ''])
[]
>>> ls_del_empty_elements(['', '', 'a', None, 'b'])
['a', 'b']
>>> ls_del_empty_elements(['   ', '', 'a', None, 'b'])
['   ', 'a', 'b']
>>> ls_del_empty_elements(['   ', '', 'a', None, 'b', 0])
['   ', 'a', 'b']

btx_lib_list.ls_double_quote_if_contains_blank(ls_elements: list[str]) -> list[str]

Wraps any string containing spaces in double quotes, keeping shell invocations safe.

Docs: Module Reference

Example:

>>> from btx_lib_list import ls_double_quote_if_contains_blank
>>> ls_double_quote_if_contains_blank([])
[]
>>> ls_double_quote_if_contains_blank([''])
['']
>>> ls_double_quote_if_contains_blank(['', 'double quote'])
['', '"double quote"']

btx_lib_list.ls_elements_replace_strings(ls_elements: list[Any], s_old: str, s_new: str) -> list[str]

Runs str.replace on each string element while leaving non-string entries untouched (return type stays list[str] to align with consumer expectations).

Docs: Module Reference

Example:

>>> from btx_lib_list import ls_elements_replace_strings
>>> ls_elements_replace_strings(['a', 'b', 'c', 1], 'a', 'z')
['z', 'b', 'c', 1]
>>> ls_elements_replace_strings([], 'a', 'z')
[]

btx_lib_list.ls_lstrip_list(list_of_strings: list[str], chars: str = "") -> list[str]

Returns a slice that omits leading entries equal to chars (defaults to empty strings).

Docs: Module Reference

Example:

>>> from btx_lib_list import ls_lstrip_list
>>> ls_lstrip_list(['', '', 'a', 'b', 'c', '', ''])
['a', 'b', 'c', '', '']
>>> ls_lstrip_list([])
[]

btx_lib_list.ls_rstrip_elements(ls_elements: list[str], chars: str | None = None) -> list[str]

Strips the specified characters from the right side of every string element.

Docs: Module Reference

Example:

>>> from btx_lib_list import ls_rstrip_elements
>>> ls_rstrip_elements(['  a', 'bbb', 'c   '])
['  a', 'bbb', 'c']
>>> ls_rstrip_elements([])
[]

btx_lib_list.ls_rstrip_list(list_of_strings: list[str], chars: str = "") -> list[str]

Removes trailing entries that match chars, returning the shortened list.

Docs: Module Reference

Example:

>>> from btx_lib_list import ls_rstrip_list
>>> ls_rstrip_list(['', '', 'a', 'b', 'c', '', ''])
['', '', 'a', 'b', 'c']
>>> ls_rstrip_list([])
[]

btx_lib_list.ls_strip_afz(ls_elements: list[str] | None) -> list[str]

Strips surrounding single or double quotes (and leading/trailing whitespace) from each string; returns [] when the input is None.

Docs: Module Reference

Example:

>>> from btx_lib_list import ls_strip_afz
>>> ls_strip_afz(['"  a"', "'bbb'", 'ccc', "   'ddd'"])
['  a', 'bbb', 'ccc', 'ddd']
>>> ls_strip_afz([])
[]
>>> ls_strip_afz(None)
[]

btx_lib_list.ls_strip_elements(ls_elements: list[str], chars: str | None = None) -> list[str]

Calls str.strip on every string element, returning the cleaned list.

Docs: Module Reference

Example:

>>> from btx_lib_list import ls_strip_elements
>>> ls_strip_elements(['  a', 'bbb', '   '])
['a', 'bbb', '']
>>> ls_strip_elements([])
[]

btx_lib_list.ls_strip_list(list_of_strings: list[str], chars: str = "") -> list[str]

Combines ls_lstrip_list and ls_rstrip_list to remove the sentinel from both ends.

Docs: Module Reference

Example:

>>> from btx_lib_list import ls_strip_list
>>> ls_strip_list(['', '', 'a', 'b', 'c', '', ''])
['a', 'b', 'c']

btx_lib_list.ls_substract(ls_minuend: list[Any], ls_subtrahend: list[Any]) -> list[Any]

Mutates ls_minuend by removing a single occurrence of each value found in ls_subtrahend.

Docs: Module Reference

Example:

>>> from btx_lib_list import ls_substract
>>> minuend = ['a', 'a', 'b']
>>> ls_substract(minuend, ['a', 'c'])
['a', 'b']

btx_lib_list.split_list_into_junks(source_list: list[Any], junk_size: int = sys.maxsize) -> list[list[Any]]

Splits source_list into slices of length junk_size (must be >= 1). The final chunk shares references with the original list to avoid copying.

Docs: Module Reference

Example:

>>> from btx_lib_list import split_list_into_junks
>>> split_list_into_junks([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], junk_size=11)
[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]
>>> split_list_into_junks([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], junk_size=3)
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
>>> split_list_into_junks([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]

btx_lib_list.str_in_list_lower_and_de_double(list_of_strings: list[str]) -> list[str]

Returns a lowered, deduplicated set of strings (order is not preserved) for case-insensitive comparisons.

Docs: Module Reference

Example:

>>> from btx_lib_list import str_in_list_lower_and_de_double
>>> sorted(str_in_list_lower_and_de_double(['a', 'b', 'c', 'b', 'A']))
['a', 'b', 'c']
>>> str_in_list_lower_and_de_double([])
[]

btx_lib_list.str_in_list_non_case_sensitive(string: str, list_of_strings: list[str]) -> bool

Checks for membership regardless of case by comparing the lowercase variants.

Docs: Module Reference

Example:

>>> from btx_lib_list import str_in_list_non_case_sensitive
>>> str_in_list_non_case_sensitive('aba', ['abc', 'cde'])
False
>>> str_in_list_non_case_sensitive('aBa', ['abc', 'Aba'])
True

btx_lib_list.str_in_list_to_lower(list_of_strings: list[str]) -> list[str]

Lowercases every string element and returns the new list.

Docs: Module Reference

Example:

>>> from btx_lib_list import str_in_list_to_lower
>>> str_in_list_to_lower(['A', 'b', 'C'])
['a', 'b', 'c']
>>> str_in_list_to_lower([])
[]

btx_lib_list.strip_and_add_non_empty_args_to_list(*args: str | None) -> list[str]

Trims each argument, discards blanks/None, and returns the remaining non-empty strings in order.

Docs: Module Reference

Example:

>>> from btx_lib_list import strip_and_add_non_empty_args_to_list
>>> strip_and_add_non_empty_args_to_list('a  ', '  b', 'c', '', '  ')
['a', 'b', 'c']
>>> strip_and_add_non_empty_args_to_list()
[]

Performance Reference

Helper group Representative functions Complexity Notes
Deduplication deduplicate, str_in_list_lower_and_de_double O(n) Uses set; ordering and duplicate survivors are not preserved.
Filtering filter_contains, filter_fnmatch, del_elements_containing O(n) Single pass over inputs; non-strings skipped where appropriate.
Ordered subtraction substract_all_keep_sorting, ls_substract O(n·m)† Relies on repeated list.remove; best for small collections.
Unordered subtraction substract_all_unsorted_fast O(n) Builds a set; removes duplicates of survivors.
Chunking split_list_into_junks O(n) Iterates once and reuses references for the final chunk.
String trimming ls_strip_elements, ls_rstrip_elements, ls_strip_list O(n) Applies string trimming per element.

† n = length of the minuend and m = distinct subtrahend entries. For large lists prefer the unordered subtraction helper or precompute a lookup set.

Further Documentation

Metadata

Release files for btx-lib-list 1.0.8

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for btx-lib-list 1.0.8
File Size Uploaded Provenance Actions
btx_lib_list-1.0.8.tar.gz 45.0 kB Without provenance Details for btx_lib_list-1.0.8.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for btx-lib-list 1.0.8
File Interpreter ABI Platform Actions
btx_lib_list-1.0.8-py3-none-any.whl Python 3 none any Details for btx_lib_list-1.0.8-py3-none-any.whl

Total release size: 70.2 kB

Release files / btx_lib_list-1.0.8.tar.gz

Download URL btx_lib_list-1.0.8.tar.gz
Size 45.0 kB
Tags Source
SHA-256 checksum
How to use checksums
e0a341e3eef9b1eab8020645c1100b898704963b699a2b24e565d307b55254ba
BLAKE2b-256 checksum
How to use checksums
2cd2c808f687d48c7e57166f47567bd3ed5a7f679d4f0bb1d6cb9fe2b9025cab
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / btx_lib_list-1.0.8-py3-none-any.whl

Download URL btx_lib_list-1.0.8-py3-none-any.whl
Size 25.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
185b5e56f613825f5aeed5a6d0ddabecbe52926ff7622734403cf4f6c9000497
BLAKE2b-256 checksum
How to use checksums
a96a8b65152cab75ed8949a352c0235696ef836c9d572b2a57488ad514c370d2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Security for btx-lib-list 1.0.8

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page