MappingTools. Do stuff with Mappings
Project description
MappingTools
This library provides utility functions for manipulating and transforming data structures which have or include Mapping-like characteristics. Including inverting dictionaries, converting class like objects to dictionaries, creating nested defaultdicts, and unwrapping complex objects.
Package |
|
Tools | |
CI/CD | |
Scans |
|
Usage
Transformers
distinct
Yields distinct values for a specified key across multiple mappings.
from mappingtools import distinct
mappings = [
{'a': 1, 'b': 2},
{'a': 2, 'b': 3},
{'a': 1, 'b': 4}
]
distinct_values = list(distinct('a', *mappings))
print(distinct_values)
# Output: [1, 2]
keep
Yields subsets of mappings by retaining only the specified keys.
from mappingtools import keep
mappings = [
{'a': 1, 'b': 2, 'c': 3},
{'a': 4, 'b': 5, 'd': 6}
]
keys_to_keep = ['a', 'b']
result = list(keep(keys_to_keep, *mappings))
# result: [{'a': 1, 'b': 2}, {'a': 4, 'b': 5}]
remove
Yields mappings with specified keys removed. It takes an iterable of keys and multiple mappings, and returns a generator of mappings with those keys excluded.
from mappingtools import remove
mappings = [
{'a': 1, 'b': 2, 'c': 3},
{'a': 4, 'b': 5, 'd': 6}
]
keys_to_remove = ['a', 'b']
result = list(remove(keys_to_remove, *mappings))
# result: [{'c': 3}, {'d': 6}]
inverse
Swaps keys and values in a dictionary.
from mappingtools import inverse
original_mapping = {'a': {1, 2}, 'b': {3}}
inverted_mapping = inverse(original_mapping)
print(inverted_mapping)
# Output: defaultdict(<class 'set'>, {1: {'a'}, 2: {'a'}, 3: {'b'}})
flattened
The flattened function takes a nested mapping structure and converts it into a single-level dictionary by flattening the keys into tuples.
from mappingtools import flattened
nested_dict = {
'a': {'b': 1, 'c': {'d': 2}},
'e': 3
}
flat_dict = flattened(nested_dict)
# Expected output: {('a', 'b'): 1, ('a', 'c', 'd'): 2, ('e',): 3}
strictify
Strictify function applies a strict structural conversion to an object using optional converters for keys and values.
from mappingtools import strictify
def uppercase_key(key):
return key.upper()
def double_value(value):
return value * 2
data = {'a': 1, 'b': 2}
result = strictify(data, key_converter=uppercase_key, value_converter=double_value)
print(result)
# Output: {'A': 2, 'B': 4}
simplify
Converts objects to strictly structured dictionaries.
from collections import Counter
from dataclasses import dataclass
from datetime import datetime
from typing import Mapping
from mappingtools import simplify
data = {'key1': 'value1', 'key2': ['item1', 'item2']}
simplified_data = simplify(data)
print(simplified_data)
# Output: {'key1': 'value1', 'key2': ['item1', 'item2']}
counter = Counter({'a': 1, 'b': 2})
print(counter)
# Output: Counter({'b': 2, 'a': 1})
simplified_counter = simplify(counter)
print(simplified_counter)
# Output: {'a': 1, 'b': 2}
@dataclass
class SampleDataClass:
a: int
b: int
aa: str
bb: str
c: list[int]
d: Mapping
e: datetime
sample_datetime = datetime(2024, 7, 22, 21, 42, 17, 314159)
sample_dataclass = SampleDataClass(1, 2, '11', '22', [1, 2], {'aaa': 111, 'bbb': '222'}, sample_datetime)
print(sample_dataclass)
# Output: SampleDataClass(a=1, b=2, aa='11', bb='22', c=[1, 2], d={'aaa': 111, 'bbb': '222'}, e=datetime.datetime(2024, 7, 22, 21, 42, 17, 314159))
simplified_sample_dataclass = simplify(sample_dataclass)
print(simplified_sample_dataclass)
# Output: {'a': 1, 'aa': '11', 'b': 2, 'bb': '22', 'c': [1, 2], 'd': {'aaa': 111, 'bbb': '222'}, 'e': datetime.datetime(2024, 7, 22, 21, 42, 17, 314159)}
listify
Transforms complex objects into a list of dictionaries with key and value pairs.
from mappingtools import listify
wrapped_data = {'key1': {'subkey': 'value'}, 'key2': ['item1', 'item2']}
unwrapped_data = listify(wrapped_data)
print(unwrapped_data)
# Output: [{'key': 'key1', 'value': [{'key': 'subkey', 'value': 'value'}]}, {'key': 'key2', 'value': ['item1', 'item2']}]
stream
Takes a mapping and an optional item factory function, and generates items from the mapping. If the item factory is provided, it applies the factory to each key-value pair before yielding.
from collections import namedtuple
from mappingtools import stream
def custom_factory(key, value):
return f"{key}: {value}"
my_mapping = {'a': 1, 'b': 2, 'c': 3}
for item in stream(my_mapping, custom_factory):
print(item)
# Output:
# a: 1
# b: 2
# c: 3
MyTuple = namedtuple('MyTuple', ['key', 'value'])
data = {'a': 1, 'b': 2}
for item in stream(data, MyTuple):
print(item)
# Output:
# MyTuple(key='a', value=1)
# MyTuple(key='b', value=2)
def record(k, v):
return {'key': k, 'value': v}
for item in stream(data, record):
print(item)
# output:
# {'key': 'a', 'value': 1}
# {'key': 'b', 'value': 2}
stream_dict_records
generates dictionary records from a given mapping, where each record contains a key-value pair from the mapping with customizable key and value names.
from mappingtools import stream_dict_records
mapping = {'a': 1, 'b': 2}
records = stream_dict_records(mapping, key_name='letter', value_name='number')
for record in records:
print(record)
# Output:
# {'letter': 'a', 'number': 1}
# {'letter': 'b', 'number': 2}
Collectors
nested_defaultdict
Creates a nested defaultdict with specified depth and factory.
from mappingtools import nested_defaultdict
nested_dd = nested_defaultdict(1, list)
nested_dd[0][1].append('value')
print(nested_dd)
# Output: defaultdict(<function nested_defaultdict.<locals>.factory at ...>, {0: defaultdict(<function nested_defaultdict.<locals>.factory at ...>, {1: ['value']})})
CategoryCounter
The CategoryCounter class extends a dictionary to count occurrences of data items categorized by multiple categories. It maintains a total count of all data items and allows categorization using direct values or functions.
from mappingtools import CategoryCounter
counter = CategoryCounter()
for fruit in ['apple', 'banana', 'apple']:
counter.update({fruit: 1}, type='fruit', char_count=len(fruit), unique_char_count=len(set(fruit)))
print(counter.total)
# Output: Counter({'apple': 2, 'banana': 1})
print(counter)
# Output: CategoryCounter({'type': defaultdict(<class 'collections.Counter'>, {'fruit': Counter({'apple': 2, 'banana': 1})}), 'char_count': defaultdict(<class 'collections.Counter'>, {5: Counter({'apple': 2}), 6: Counter({'banana': 1})}), 'unique_char_count': defaultdict(<class 'collections.Counter'>, {4: Counter({'apple': 2}), 3: Counter({'banana': 1})})})
MappingCollector
A class designed to collect key-value pairs into an internal mapping based on different modes. It supports modes like ALL, COUNT, DISTINCT, FIRST, and LAST, each dictating how key-value pairs are collected.
from mappingtools import MappingCollector, MappingCollectorMode
collector = MappingCollector(MappingCollectorMode.ALL)
collector.add('a', 1)
collector.add('a', 2)
collector.collect([('b', 3), ('b', 4)])
print(collector.mapping)
# Output: {'a': [1, 2], 'b': [3, 4]}
Development
Ruff
ruff check src
Test
Standard (cobertura) XML Coverage Report
python -m pytest tests -n auto --cov=src --cov-branch --doctest-modules --cov-report=xml
HTML Coverage Report
python -m pytest tests -n auto --cov=src --cov-branch --doctest-modules --cov-report=html
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file mappingtools-0.2.2.tar.gz
.
File metadata
- Download URL: mappingtools-0.2.2.tar.gz
- Upload date:
- Size: 26.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.9.20
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | ecb62596207a5b167ef774fecfeb77c797262527ba888d08878e4e67666cfceb |
|
MD5 | 45206c74b52eb4f43d2ad31a7bd3e016 |
|
BLAKE2b-256 | 9fb1fd8e319fad786b3d32609673f9733924bb9ca113b66f7d36217443488060 |
File details
Details for the file mappingtools-0.2.2-py3-none-any.whl
.
File metadata
- Download URL: mappingtools-0.2.2-py3-none-any.whl
- Upload date:
- Size: 9.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.9.20
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | eed4eae5ec41bc8a1cbd63ea56bcc8eb7820c8b778c22eb4c99e01102a880f8b |
|
MD5 | 65433f400ac9eb194e59a5552d4dd588 |
|
BLAKE2b-256 | b359139e483562bd8260818566e0b89be5773c095cf5d234f677d4c3f78adc47 |