Package: lully
LullyA small library providing some helpers for python devs.See thetestsfor usage examples and ideas.CollectionsOtomThe One-To-One-Mapping is a special kind of dict, where all values are also keys, associated to their key.from lully import Otom

O = Otom({
    'one': 1,
    'two': 2,
    'tee': 3,
})
assert O[1] == 'one'
assert O['one'] == 1An Otom acts like a dict. Seetestsfor more.ConfiseurA Confiseur is here to help with configurations.The principle is to subclass, for each configuration kind you need, the Confiseur base class and populate it with Bonbon instances, describing options.from lully import Confiseur, Bonbon

class MyConfig(Confiseur):

    def bonbons(self) -> [Bonbon]:
        return (
            Bonbon('server options', 'max instances', default=3),
        )

    def validate(self, cfg):
        if cfg['server options']['max instances'] > 10:
            self.add_error(f"Can't handle more than ten instances. Provided: {cfg['server options']['max instances']}.")

myconfig = MyConfig('{"server options": { "max instances": 11 }}')
assert myconfig['server options']['max instances'] == 11
assert myconfig.has_error
assert len(myconfig.errors)Seetestsfor more.ItermoreMore itertools functions !from lully.itermore import window, grouper, flatten, dotproduct, ncyclesSee thesource filefor the full set of functions.Kotlin-inspired functionsWhen coding in other languages, you get ideas. Here are the ones i got after a 1h course of Kotlin.from lully import first, last, zip_with_next

assert first([1, 2]) == 1
assert last([1, 2]) == 2
assert first([2, 3], lambda x: x % 2) == 3
assert tuple(zip_with_next('abc')) == (('a', 'b'), ('c', None))See thesource filefor the full set of functions.FiefThis name should recall both its goal, which isFIltering of EFfective paramaters, and the fact it keeps functions to work within theirfief.You have this function:def func(a, b):
    ...  # some implementationand you have its parameter stored in a dict, with other keys that are not for that specific function:config = {'a': 1, 'b': 'doe', 'loglevel': 'WARNING'}Thus, you can't just do that:func(**config)Because of the expected:TypeError: func() got an unexpected keyword argument 'loglevel'One solution can be to filter that dict, but that's cumbersome and needs maintainance. And that's worse if you have a lot of functions to call that way.Fief is a decorator that will make that for you, usinginspectmodule.from lully import fief

@fief
def func(a, b):
    return a + b

config = {'a': 2, 'b': 3, 'loglevel': 'WARNING'}

# and suddenly, you can provide anything in keywords argument:
assert func(**config) == 5   # no TypeError, that's magic !randomlsampleThis is a function answering to then choose kproblem using the Vitter's algorithm.The problem is to choose randomly n element in a set of k. That's usually done with therandom.sample(n, [1, 2, ...])function. Hence thesamplingpart oflsamplename.
However, that stdlib function will load everything in memory, forcing you to provide a list, not a generator.Vitter's solution is to collect thenelements during a single pass over the list, making possible to work on generators,
as long as you have a idea of their size, hence not loading all data in memory.from lully import lsample
print(lsample(3, [x for x in range(10)], it_size=10))This enables you to pick 100 random tweets among the entire tweeter database without having to load it in memory.
Provided you have enough time for the full browsing to be performed.Seethat repofor more information, sources and benchmarks.weighed_choicesThis function is basically arandom.choice()equivalent, but where each choice can be weighted.from lully import weighed_choices
print(weighed_choices(a=2, b=4, c=1))Will print you mostlyb, sometimesaand only once on seven callsc.Note that you can also provide the input choices as a dict:print(weighed_choices({'a': 2, 'b': 4, 'c': 1))