range-key-dict-2


Namerange-key-dict-2 JSON
Version 2.0.0 PyPI version JSON
download
home_pageNone
SummaryA modern dict implementation supporting range-based keys with O(log M) lookups
upload_time2025-10-21 22:34:09
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseMIT
keywords range dict interval mapping data-structure
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # range-key-dict-2

[![PyPI version](https://img.shields.io/pypi/v/range-key-dict-2.svg)](https://pypi.org/project/range-key-dict-2/)
[![Python versions](https://img.shields.io/pypi/pyversions/range-key-dict-2.svg)](https://pypi.org/project/range-key-dict-2/)
[![CI Status](https://github.com/odosmatthews/range-key-dict-2/workflows/CI/badge.svg)](https://github.com/odosmatthews/range-key-dict-2/actions)
[![codecov](https://codecov.io/gh/odosmatthews/range-key-dict-2/branch/main/graph/badge.svg)](https://codecov.io/gh/odosmatthews/range-key-dict-2)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

A modern, feature-rich Python dictionary that uses numeric ranges as keys. Perfect for mapping continuous ranges of numbers to values, with O(M) lookup performance and full dict-like interface.

## ๐ŸŽฏ Credit & Inspiration

This project is directly inspired by and builds upon the excellent work of **Albert Li (menglong.li)** in the original [range-key-dict](https://github.com/albertmenglongli/range-key-dict) project. `range-key-dict-2` modernizes the concept with:

- Python 3.8+ features (type hints, modern syntax)
- Full dictionary-like interface
- Overlapping range strategies
- Open-ended ranges (infinite bounds)
- Comprehensive test coverage (93 tests, 98% coverage)
- Modern tooling and CI/CD

## โœจ Features

### Core Capabilities

- **Range-based Keys**: Use numeric ranges `(start, end)` as dictionary keys
- **Efficient Lookups**: Query which range contains a given number
- **Full Dict Interface**: Supports `keys()`, `values()`, `items()`, `len()`, `in`, iteration, and more
- **Mutable Operations**: Add, update, and delete ranges dynamically with `__setitem__` and `__delitem__`
- **Type Safety**: Fully typed with mypy strict mode support

### Advanced Features

- **Open-ended Ranges**: Use `None` for infinite bounds (e.g., `(None, 0)` for all negative numbers)
- **Overlap Strategies**: Control behavior when ranges overlap:
  - `'error'`: Raise exception (default, backwards compatible)
  - `'first'`: Return first matching range (by insertion order)
  - `'last'`: Return last matching range (by insertion order)
  - `'shortest'`: Return shortest matching range
  - `'longest'`: Return longest matching range
- **Flexible Types**: Works with integers, floats, and mixed types
- **Backwards Compatible**: 100% compatible with original `range-key-dict` v1 API

## ๐Ÿ“ฆ Installation

```bash
pip install range-key-dict-2
```

## ๐Ÿš€ Quick Start

### Basic Usage

```python
from range_key_dict import RangeKeyDict

# Create a range dictionary
grades = RangeKeyDict({
    (0, 60): 'F',
    (60, 70): 'D',
    (70, 80): 'C',
    (80, 90): 'B',
    (90, 100): 'A',
})

# Look up values
print(grades[85])  # 'B'
print(grades[92])  # 'A'
print(grades[58])  # 'F'

# Safe lookup with default
print(grades.get(105, 'Out of range'))  # 'Out of range'

# Check membership
print(75 in grades)  # True
print(105 in grades)  # False
```

### Dict-like Interface

```python
from range_key_dict import RangeKeyDict

rkd = RangeKeyDict()

# Add ranges
rkd[(0, 10)] = 'first'
rkd[(10, 20)] = 'second'
rkd[(20, 30)] = 'third'

# Update a range
rkd[(10, 20)] = 'updated second'

# Delete a range
del rkd[(20, 30)]

# Iterate
for range_key in rkd:
    print(f"Range {range_key} -> {rkd[range_key]}")

# Get all keys, values, items
print(rkd.keys())    # [(0, 10), (10, 20)]
print(rkd.values())  # ['first', 'updated second']
print(rkd.items())   # [((0, 10), 'first'), ((10, 20), 'updated second')]

# Length
print(len(rkd))  # 2
```

### Open-ended Ranges

Use `None` for infinite boundaries:

```python
from range_key_dict import RangeKeyDict

temperature = RangeKeyDict({
    (None, 0): 'freezing',      # (-โˆž, 0)
    (0, 20): 'cold',            # [0, 20)
    (20, 30): 'comfortable',    # [20, 30)
    (30, None): 'hot',          # [30, +โˆž)
})

print(temperature[-100])  # 'freezing'
print(temperature[25])    # 'comfortable'
print(temperature[50])    # 'hot'
```

### Overlapping Ranges

Control how overlapping ranges are handled:

```python
from range_key_dict import RangeKeyDict

# Allow overlaps, return first matching range
rkd = RangeKeyDict({
    (0, 100): 'wide',
    (25, 75): 'narrow',
}, overlap_strategy='first')

print(rkd[50])  # 'wide' (first defined range wins)

# Return shortest matching range
rkd = RangeKeyDict({
    (0, 100): 'wide',
    (25, 75): 'narrow',
}, overlap_strategy='shortest')

print(rkd[50])  # 'narrow' (shortest matching range)
```

Available strategies: `'error'`, `'first'`, `'last'`, `'shortest'`, `'longest'`

## ๐Ÿ“– Examples

Comprehensive examples available in **two formats**:

### ๐Ÿ““ Jupyter Notebooks (Recommended)
**[examples/](examples/)** - Interactive notebooks with pre-executed outputs

- `01_basic_usage.ipynb` - Get started with the basics (8 examples)
- `02_dict_interface.ipynb` - Master the dict-like API (10 examples)
- `03_open_ended_ranges.ipynb` - Work with infinity bounds (10 examples)
- `04_overlap_strategies.ipynb` - Handle overlapping ranges (10 examples)
- `05_real_world_use_cases.ipynb` - Production-ready examples (10 examples)

```bash
cd examples
jupyter notebook
```

### ๐Ÿ Python Scripts
**[examples_code/](examples_code/)** - Runnable Python scripts

```bash
cd examples_code
python 01_basic_usage.py
# or
bash run_all.sh
```

## ๐Ÿ“– Real-World Examples

### Age Categories

```python
age_groups = RangeKeyDict({
    (None, 13): 'child',
    (13, 20): 'teenager',
    (20, 65): 'adult',
    (65, None): 'senior',
})

print(age_groups[8])   # 'child'
print(age_groups[16])  # 'teenager'
print(age_groups[45])  # 'adult'
print(age_groups[70])  # 'senior'
```

### Tax Brackets

```python
tax_brackets_2024 = RangeKeyDict({
    (0, 11000): 0.10,
    (11000, 44725): 0.12,
    (44725, 95375): 0.22,
    (95375, 182100): 0.24,
    (182100, 231250): 0.32,
    (231250, 578125): 0.35,
    (578125, None): 0.37,
})

income = 50000
tax_rate = tax_brackets_2024[income]
print(f"Tax rate for ${income}: {tax_rate:.0%}")  # Tax rate for $50000: 22%
```

### HTTP Status Code Categories

```python
http_categories = RangeKeyDict({
    (100, 200): 'Informational',
    (200, 300): 'Success',
    (300, 400): 'Redirection',
    (400, 500): 'Client Error',
    (500, 600): 'Server Error',
})

print(http_categories[200])  # 'Success'
print(http_categories[404])  # 'Client Error'
print(http_categories[500])  # 'Server Error'
```

## ๐Ÿ”„ Migration from v1

`range-key-dict-2` is 100% backwards compatible with `range-key-dict` v1:

```python
# This works exactly the same in v1 and v2
from range_key_dict import RangeKeyDict

rkd = RangeKeyDict({
    (0, 100): 'A',
    (100, 200): 'B',
    (200, 300): 'C',
})

assert rkd[70] == 'A'
assert rkd[170] == 'B'
assert rkd.get(1000, 'D') == 'D'
```

Simply change your dependency from `range-key-dict` to `range-key-dict-2` and enjoy the new features!

## โšก Performance

Current implementation uses O(M) linear scan for lookups, where M is the number of ranges. Performance is excellent for small to moderate numbers of ranges (< 1000).

### Performance Roadmap

Future versions will implement O(log M) binary search optimization using:
- Sorted list of range starts with `bisect` module
- Interval trees for complex overlap scenarios
- See [TODO in source](range_key_dict/range_key_dict.py) for details

For most use cases, current performance is more than sufficient. The linear scan is simple, correct, and fast enough.

## ๐Ÿงช Testing

The package includes comprehensive tests:

```bash
# Run tests
pytest

# Run with coverage
pytest --cov=range_key_dict --cov-report=html

# Run specific test file
pytest tests/test_backwards_compatibility.py
```

Current test coverage: **98%** (93 tests)

## ๐Ÿ› ๏ธ Development

### Setup Development Environment

```bash
# Clone the repository
git clone https://github.com/odosmatthews/range-key-dict-2.git
cd range-key-dict-2

# Install in development mode with dev dependencies
pip install -e ".[dev]"

# Install pre-commit hooks
pre-commit install
```

### Run Quality Checks

```bash
# Lint and auto-fix with ruff (fast!)
ruff check --fix .

# Format check with ruff
ruff format .

# Alternative: Format with black
black range_key_dict tests

# Sort imports
isort range_key_dict tests

# Type check
mypy range_key_dict

# Run all checks (pre-commit)
pre-commit run --all-files
```

## ๐Ÿ“‹ Requirements

- Python 3.8+
- No runtime dependencies!

## ๐Ÿค Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
4. Push to the branch (`git push origin feature/AmazingFeature`)
5. Open a Pull Request

## ๐Ÿ“„ License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## ๐Ÿ™ Acknowledgments

- **Albert Li (menglong.li)** - Original [range-key-dict](https://github.com/albertmenglongli/range-key-dict) creator
- All contributors who help improve this project

## ๐Ÿ“š Related Projects

- [range-key-dict](https://github.com/albertmenglongli/range-key-dict) - The original implementation
- [intervaltree](https://github.com/chaimleib/intervaltree) - For more complex interval operations
- [portion](https://github.com/AlexandreDecan/portion) - Advanced interval arithmetic

## ๐Ÿ“ฎ Contact & Support

- **Issues**: [GitHub Issues](https://github.com/odosmatthews/range-key-dict-2/issues)
- **Discussions**: [GitHub Discussions](https://github.com/odosmatthews/range-key-dict-2/discussions)

---

Made with โค๏ธ by Matthew Odos, inspired by Albert Li's original work.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "range-key-dict-2",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": "Matthew Odos <odosmatthews@example.com>",
    "keywords": "range, dict, interval, mapping, data-structure",
    "author": null,
    "author_email": "Matthew Odos <odosmatthews@example.com>",
    "download_url": "https://files.pythonhosted.org/packages/2e/29/18a511eb39142ff97deb6711843a2fa4a037f33d78af6bdd8e64977d171a/range_key_dict_2-2.0.0.tar.gz",
    "platform": null,
    "description": "# range-key-dict-2\n\n[![PyPI version](https://img.shields.io/pypi/v/range-key-dict-2.svg)](https://pypi.org/project/range-key-dict-2/)\n[![Python versions](https://img.shields.io/pypi/pyversions/range-key-dict-2.svg)](https://pypi.org/project/range-key-dict-2/)\n[![CI Status](https://github.com/odosmatthews/range-key-dict-2/workflows/CI/badge.svg)](https://github.com/odosmatthews/range-key-dict-2/actions)\n[![codecov](https://codecov.io/gh/odosmatthews/range-key-dict-2/branch/main/graph/badge.svg)](https://codecov.io/gh/odosmatthews/range-key-dict-2)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA modern, feature-rich Python dictionary that uses numeric ranges as keys. Perfect for mapping continuous ranges of numbers to values, with O(M) lookup performance and full dict-like interface.\n\n## \ud83c\udfaf Credit & Inspiration\n\nThis project is directly inspired by and builds upon the excellent work of **Albert Li (menglong.li)** in the original [range-key-dict](https://github.com/albertmenglongli/range-key-dict) project. `range-key-dict-2` modernizes the concept with:\n\n- Python 3.8+ features (type hints, modern syntax)\n- Full dictionary-like interface\n- Overlapping range strategies\n- Open-ended ranges (infinite bounds)\n- Comprehensive test coverage (93 tests, 98% coverage)\n- Modern tooling and CI/CD\n\n## \u2728 Features\n\n### Core Capabilities\n\n- **Range-based Keys**: Use numeric ranges `(start, end)` as dictionary keys\n- **Efficient Lookups**: Query which range contains a given number\n- **Full Dict Interface**: Supports `keys()`, `values()`, `items()`, `len()`, `in`, iteration, and more\n- **Mutable Operations**: Add, update, and delete ranges dynamically with `__setitem__` and `__delitem__`\n- **Type Safety**: Fully typed with mypy strict mode support\n\n### Advanced Features\n\n- **Open-ended Ranges**: Use `None` for infinite bounds (e.g., `(None, 0)` for all negative numbers)\n- **Overlap Strategies**: Control behavior when ranges overlap:\n  - `'error'`: Raise exception (default, backwards compatible)\n  - `'first'`: Return first matching range (by insertion order)\n  - `'last'`: Return last matching range (by insertion order)\n  - `'shortest'`: Return shortest matching range\n  - `'longest'`: Return longest matching range\n- **Flexible Types**: Works with integers, floats, and mixed types\n- **Backwards Compatible**: 100% compatible with original `range-key-dict` v1 API\n\n## \ud83d\udce6 Installation\n\n```bash\npip install range-key-dict-2\n```\n\n## \ud83d\ude80 Quick Start\n\n### Basic Usage\n\n```python\nfrom range_key_dict import RangeKeyDict\n\n# Create a range dictionary\ngrades = RangeKeyDict({\n    (0, 60): 'F',\n    (60, 70): 'D',\n    (70, 80): 'C',\n    (80, 90): 'B',\n    (90, 100): 'A',\n})\n\n# Look up values\nprint(grades[85])  # 'B'\nprint(grades[92])  # 'A'\nprint(grades[58])  # 'F'\n\n# Safe lookup with default\nprint(grades.get(105, 'Out of range'))  # 'Out of range'\n\n# Check membership\nprint(75 in grades)  # True\nprint(105 in grades)  # False\n```\n\n### Dict-like Interface\n\n```python\nfrom range_key_dict import RangeKeyDict\n\nrkd = RangeKeyDict()\n\n# Add ranges\nrkd[(0, 10)] = 'first'\nrkd[(10, 20)] = 'second'\nrkd[(20, 30)] = 'third'\n\n# Update a range\nrkd[(10, 20)] = 'updated second'\n\n# Delete a range\ndel rkd[(20, 30)]\n\n# Iterate\nfor range_key in rkd:\n    print(f\"Range {range_key} -> {rkd[range_key]}\")\n\n# Get all keys, values, items\nprint(rkd.keys())    # [(0, 10), (10, 20)]\nprint(rkd.values())  # ['first', 'updated second']\nprint(rkd.items())   # [((0, 10), 'first'), ((10, 20), 'updated second')]\n\n# Length\nprint(len(rkd))  # 2\n```\n\n### Open-ended Ranges\n\nUse `None` for infinite boundaries:\n\n```python\nfrom range_key_dict import RangeKeyDict\n\ntemperature = RangeKeyDict({\n    (None, 0): 'freezing',      # (-\u221e, 0)\n    (0, 20): 'cold',            # [0, 20)\n    (20, 30): 'comfortable',    # [20, 30)\n    (30, None): 'hot',          # [30, +\u221e)\n})\n\nprint(temperature[-100])  # 'freezing'\nprint(temperature[25])    # 'comfortable'\nprint(temperature[50])    # 'hot'\n```\n\n### Overlapping Ranges\n\nControl how overlapping ranges are handled:\n\n```python\nfrom range_key_dict import RangeKeyDict\n\n# Allow overlaps, return first matching range\nrkd = RangeKeyDict({\n    (0, 100): 'wide',\n    (25, 75): 'narrow',\n}, overlap_strategy='first')\n\nprint(rkd[50])  # 'wide' (first defined range wins)\n\n# Return shortest matching range\nrkd = RangeKeyDict({\n    (0, 100): 'wide',\n    (25, 75): 'narrow',\n}, overlap_strategy='shortest')\n\nprint(rkd[50])  # 'narrow' (shortest matching range)\n```\n\nAvailable strategies: `'error'`, `'first'`, `'last'`, `'shortest'`, `'longest'`\n\n## \ud83d\udcd6 Examples\n\nComprehensive examples available in **two formats**:\n\n### \ud83d\udcd3 Jupyter Notebooks (Recommended)\n**[examples/](examples/)** - Interactive notebooks with pre-executed outputs\n\n- `01_basic_usage.ipynb` - Get started with the basics (8 examples)\n- `02_dict_interface.ipynb` - Master the dict-like API (10 examples)\n- `03_open_ended_ranges.ipynb` - Work with infinity bounds (10 examples)\n- `04_overlap_strategies.ipynb` - Handle overlapping ranges (10 examples)\n- `05_real_world_use_cases.ipynb` - Production-ready examples (10 examples)\n\n```bash\ncd examples\njupyter notebook\n```\n\n### \ud83d\udc0d Python Scripts\n**[examples_code/](examples_code/)** - Runnable Python scripts\n\n```bash\ncd examples_code\npython 01_basic_usage.py\n# or\nbash run_all.sh\n```\n\n## \ud83d\udcd6 Real-World Examples\n\n### Age Categories\n\n```python\nage_groups = RangeKeyDict({\n    (None, 13): 'child',\n    (13, 20): 'teenager',\n    (20, 65): 'adult',\n    (65, None): 'senior',\n})\n\nprint(age_groups[8])   # 'child'\nprint(age_groups[16])  # 'teenager'\nprint(age_groups[45])  # 'adult'\nprint(age_groups[70])  # 'senior'\n```\n\n### Tax Brackets\n\n```python\ntax_brackets_2024 = RangeKeyDict({\n    (0, 11000): 0.10,\n    (11000, 44725): 0.12,\n    (44725, 95375): 0.22,\n    (95375, 182100): 0.24,\n    (182100, 231250): 0.32,\n    (231250, 578125): 0.35,\n    (578125, None): 0.37,\n})\n\nincome = 50000\ntax_rate = tax_brackets_2024[income]\nprint(f\"Tax rate for ${income}: {tax_rate:.0%}\")  # Tax rate for $50000: 22%\n```\n\n### HTTP Status Code Categories\n\n```python\nhttp_categories = RangeKeyDict({\n    (100, 200): 'Informational',\n    (200, 300): 'Success',\n    (300, 400): 'Redirection',\n    (400, 500): 'Client Error',\n    (500, 600): 'Server Error',\n})\n\nprint(http_categories[200])  # 'Success'\nprint(http_categories[404])  # 'Client Error'\nprint(http_categories[500])  # 'Server Error'\n```\n\n## \ud83d\udd04 Migration from v1\n\n`range-key-dict-2` is 100% backwards compatible with `range-key-dict` v1:\n\n```python\n# This works exactly the same in v1 and v2\nfrom range_key_dict import RangeKeyDict\n\nrkd = RangeKeyDict({\n    (0, 100): 'A',\n    (100, 200): 'B',\n    (200, 300): 'C',\n})\n\nassert rkd[70] == 'A'\nassert rkd[170] == 'B'\nassert rkd.get(1000, 'D') == 'D'\n```\n\nSimply change your dependency from `range-key-dict` to `range-key-dict-2` and enjoy the new features!\n\n## \u26a1 Performance\n\nCurrent implementation uses O(M) linear scan for lookups, where M is the number of ranges. Performance is excellent for small to moderate numbers of ranges (< 1000).\n\n### Performance Roadmap\n\nFuture versions will implement O(log M) binary search optimization using:\n- Sorted list of range starts with `bisect` module\n- Interval trees for complex overlap scenarios\n- See [TODO in source](range_key_dict/range_key_dict.py) for details\n\nFor most use cases, current performance is more than sufficient. The linear scan is simple, correct, and fast enough.\n\n## \ud83e\uddea Testing\n\nThe package includes comprehensive tests:\n\n```bash\n# Run tests\npytest\n\n# Run with coverage\npytest --cov=range_key_dict --cov-report=html\n\n# Run specific test file\npytest tests/test_backwards_compatibility.py\n```\n\nCurrent test coverage: **98%** (93 tests)\n\n## \ud83d\udee0\ufe0f Development\n\n### Setup Development Environment\n\n```bash\n# Clone the repository\ngit clone https://github.com/odosmatthews/range-key-dict-2.git\ncd range-key-dict-2\n\n# Install in development mode with dev dependencies\npip install -e \".[dev]\"\n\n# Install pre-commit hooks\npre-commit install\n```\n\n### Run Quality Checks\n\n```bash\n# Lint and auto-fix with ruff (fast!)\nruff check --fix .\n\n# Format check with ruff\nruff format .\n\n# Alternative: Format with black\nblack range_key_dict tests\n\n# Sort imports\nisort range_key_dict tests\n\n# Type check\nmypy range_key_dict\n\n# Run all checks (pre-commit)\npre-commit run --all-files\n```\n\n## \ud83d\udccb Requirements\n\n- Python 3.8+\n- No runtime dependencies!\n\n## \ud83e\udd1d Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.\n\n1. Fork the repository\n2. Create your feature branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)\n4. Push to the branch (`git push origin feature/AmazingFeature`)\n5. Open a Pull Request\n\n## \ud83d\udcc4 License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## \ud83d\ude4f Acknowledgments\n\n- **Albert Li (menglong.li)** - Original [range-key-dict](https://github.com/albertmenglongli/range-key-dict) creator\n- All contributors who help improve this project\n\n## \ud83d\udcda Related Projects\n\n- [range-key-dict](https://github.com/albertmenglongli/range-key-dict) - The original implementation\n- [intervaltree](https://github.com/chaimleib/intervaltree) - For more complex interval operations\n- [portion](https://github.com/AlexandreDecan/portion) - Advanced interval arithmetic\n\n## \ud83d\udcee Contact & Support\n\n- **Issues**: [GitHub Issues](https://github.com/odosmatthews/range-key-dict-2/issues)\n- **Discussions**: [GitHub Discussions](https://github.com/odosmatthews/range-key-dict-2/discussions)\n\n---\n\nMade with \u2764\ufe0f by Matthew Odos, inspired by Albert Li's original work.\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A modern dict implementation supporting range-based keys with O(log M) lookups",
    "version": "2.0.0",
    "project_urls": {
        "Bug Tracker": "https://github.com/odosmatthews/range-key-dict-2/issues",
        "Homepage": "https://github.com/odosmatthews/range-key-dict-2",
        "Original Project": "https://github.com/albertmenglongli/range-key-dict",
        "Source Code": "https://github.com/odosmatthews/range-key-dict-2"
    },
    "split_keywords": [
        "range",
        " dict",
        " interval",
        " mapping",
        " data-structure"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "0f49c10ee0826d692ea04ee28bf3f6dda8e354bb5c261b061acab81f12ff271c",
                "md5": "14ee735680990196ae3df181c9ba81ab",
                "sha256": "b460682107f6eb2810ff83bd33547971ed36924f1d506d1c981808a3cbd28cd6"
            },
            "downloads": -1,
            "filename": "range_key_dict_2-2.0.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "14ee735680990196ae3df181c9ba81ab",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 10410,
            "upload_time": "2025-10-21T22:34:08",
            "upload_time_iso_8601": "2025-10-21T22:34:08.057497Z",
            "url": "https://files.pythonhosted.org/packages/0f/49/c10ee0826d692ea04ee28bf3f6dda8e354bb5c261b061acab81f12ff271c/range_key_dict_2-2.0.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "2e2918a511eb39142ff97deb6711843a2fa4a037f33d78af6bdd8e64977d171a",
                "md5": "e14184a315252346a6ac910a7db89021",
                "sha256": "3348515fda514c0f718e94231344af6ddb1f8f16f93ffcb3683120d116b9dea9"
            },
            "downloads": -1,
            "filename": "range_key_dict_2-2.0.0.tar.gz",
            "has_sig": false,
            "md5_digest": "e14184a315252346a6ac910a7db89021",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 20501,
            "upload_time": "2025-10-21T22:34:09",
            "upload_time_iso_8601": "2025-10-21T22:34:09.236682Z",
            "url": "https://files.pythonhosted.org/packages/2e/29/18a511eb39142ff97deb6711843a2fa4a037f33d78af6bdd8e64977d171a/range_key_dict_2-2.0.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-21 22:34:09",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "odosmatthews",
    "github_project": "range-key-dict-2",
    "github_not_found": true,
    "lcname": "range-key-dict-2"
}
        
Elapsed time: 2.02246s