The caselessly library provides several case-less container data type implementations:
- a
dictsubclass that allows for case-insensitive comparison of its string keys - a
listsubclass that allows for case-insensitive comparison of its string items - a
setsubclass that allows for case-insensitive comparison of its string items - a
tuplesubclass that allows for case-insensitive comparison of its string items
The Caselessly library has been tested with Python 3.10, 3.11, 3.12 and 3.13. The library is not compatible with Python 3.9 or earlier.
The Caselessly library is available from PyPI, so may be added to a project's dependencies
via its requirements.txt file or similar by referencing the Caselessly library's name,
caselessly, or the library may be installed directly into your local runtime environment
using pip via the pip install command by entering the following into your shell:
$ pip install caselessly
To use the Caselessly library, import the library and the data type or data types you need and use them just like their regular counterparts, with the knowledge that they support setting and getting values without regard to the casing of any string keys:
from caselessly import caselessdict
data = caselessdict({"a": 1, "B": 2}, c=3)
assert isinstance(data, caselessdict)
assert isinstance(data, dict)
assert len(data) == 3
assert data == {"A": 1, "B": 2, "c": 3}
assert data == {"a": 1, "b": 2, "c": 3}
assert data == {"a": 1, "B": 2, "c": 3}
assert data == {"A": 1, "b": 2, "C": 3}from caselessly import caselesslist
data: list[str] = ["A", "B", "c", "D", "e", "f"]
assert isinstance(data, list)
assert len(data) == 6
assert "A" in data
assert "B" in data
assert not "C" in data
data = caselesslist(data)
assert isinstance(data, list)
assert isinstance(data, caselesslist)
assert len(data) == 6
assert "A" in data
assert "B" in data
assert "C" in data # note that "C" does not exist in the list but "c" does
assert "D" in data
assert "E" in data # note that "E" does not exist in the list but "e" does
assert "f" in data # note that "f" does not exist in the list but "f" doesfrom caselessly import caselessdict
data = caselessdict({"a": 1, "B": 2}, c=3)
assert isinstance(data, caselessdict)
assert isinstance(data, dict)
assert len(data) == 3
assert data == {"A": 1, "B": 2, "c": 3}
assert data == {"a": 1, "b": 2, "c": 3}
assert data == {"a": 1, "B": 2, "c": 3}
assert data == {"A": 1, "b": 2, "C": 3}from caselessly import caselesstuple
data = tuple(["A", "B", "c", "D", "E", "f"])
assert "A" in data
assert "B" in data
assert not "C" in data
data = caselesstuple(data)
assert "A" in data
assert "B" in data
assert "C" in data # note that "C" does not exist in the list but "c" does
assert "D" in data
assert "E" in data
assert "F" in data # note that "F" does not exist in the list but "f" doesThe Caselessly library provides the following data type subclasses and each class offers
a shorthand alias that prefixes the superclass' name with ci to denote that the class
is its case-insensitive variant. The aliases can be used interchangeably with the fully
qualified class names as they are direct aliases rather than further subclasses.
| Subclass | Superclass | Subclass Alias |
|---|---|---|
caselessdict |
dict |
cidict |
caselesslist |
list |
cilist |
caselessset |
set |
ciset |
caselesstuple |
tuple |
cituple |
The Caselessly library classes can be used interchangeably with their superclasses where one needs the ability to place items into and retrieve items from the containers without regard to case sensitivity. The classes offer all the usual functionality that their superclasses offer, and all the usual methods and interactions are available.
The Caselessly library includes a suite of comprehensive unit tests which ensure that the
library functionality operates as expected. The unit tests were developed with and are
run via pytest.
To ensure that the unit tests are run within a predictable runtime environment where all of the necessary dependencies are available, a Docker image is created within which the tests are run. To run the unit tests, ensure Docker and Docker Compose is installed, and perform the following commands, which will build the Docker image via docker compose build and then run the tests via docker compose run – the output of running the tests will be displayed:
$ docker compose build
$ docker compose run testsTo run the unit tests with optional command line arguments being passed to pytest, append the relevant arguments to the docker compose run tests command, as follows, for example passing -vv to enable verbose output:
$ docker compose run tests -vvSee the documentation for PyTest regarding available optional command line arguments.
Copyright © 2025 Daniel Sissman; licensed under the MIT License.