Skip to main content

Some Python nicieties

Project description

I use the excellent Funcy library for Python a lot. This is my collection of extras that I have designed to work closely together with funcy. Funcy Kingston (Reference, see here).

Kingston is auto-formatted using yapf.

Nice things

dig()

CSS selector like deep value grabbing from almost any object.

>>> from kingston import dig
>>> dig.xget((1, 2, 3), 1)
2
>>> dig.xget({'foo': 'bar'}, 'foo')
'bar'
>>> dig.dig({'foo': 1, 'bar': [1,2,3]}, 'bar.1')
2
>>> dig.dig({'foo': 1, 'bar': [1,{'baz':'jox'},3]}, 'bar.1.baz')
'jox'
>>>

The difference between dig.dig() and funcy.get_in() is that you can use shell-like blob patterns to get several values keyed by similar names:

>>> from kingston import dig
>>> res = dig.dig({'foo': 1, 'foop': 2}, 'f*')
>>> res
[foo=1:int, foop=2:int]
>>> # (textual representation of an indexable object)
>>> res[0]
foo=1:int
>>> res[1]
foop=2:int
>>>

Pattern matching using extended dict’s

>>> from kingston import lang
>>> foo = lang.Match({int: lambda x: x*100, str: lambda x: f'Hello {x}'})
>>> foo(10)
1000
>>> foo('bar')
'Hello bar'
>>>

Narrowable collections

Uses indexes to narrow collections to fewer values. You can narrow by type, a predicate function or value equality. The return value is always a new Narrowable derived type from the initial value. Therefore, you can chain several narrowing operations in the same expression.

Errors raised by the narrowing predicates are considered misses.

Some examples:

Narrow by type

>>> from kingston.primitives import narrowable
>>> narrowable((1,2,3,'foo', 'bar'))[int]
(1, 2, 3)
>>>

Narrow by callable

>>> from kingston.primitives import narrowable
>>> narrowable((1, 2, 3))[lambda x: x > 1]
(2, 3)
>>>
>>> narrowable((1,2,3,'foo', 'bar'))[int]
(1, 2, 3)
>>> narrowable((1,2,3,'foo', 'bar'))[lambda x: x > 1]
(2, 3)
>>> # Note, swallows ValueError raised by 'foo' > 1 etc
>>>

Supress empty iterable objects

>>> from kingston.primitives import narrowable
>>> narrowable([[1], [2], [], []])[lambda x: x[0]]
[[1], [2]]
>>>

Narrow using exact match

>>> from kingston.primitives import narrowable
>>> narrowable((1, 2, 3, 'foo'))['foo']
('foo',)
>>>

Narrow using a regexp

>>> from kingston.primitives import narrowable
>>> import re
>>> narrowable(('foo', 'fom', 'jox', 8, 'fim'))[re.compile('fo.*').match]
('foo', 'fom')
>>>

Combine

>>> from kingston.primitives import narrowable
>>> narrowable((1,2,3,'foo', 'bar'))[str]['foo']
('foo',)
>>>

Go deeper

>>> from kingston.primitives import narrowable
>>> narrowable((1, 2, 3, (41, 42, 43)))[tuple][0][lambda x: x > 41]
(42, 43)
>>>

No matches found

If no element matches, an empty version of the collection parameter will be returned:

>>> from kingston.primitives import narrowable
>>> narrowable((1,2,3))[lambda x: x > 3]
()
>>>

Programmatic class creation

Programmatic creation of arbitrary named classes in module definition, add methods using a decorator notation:

>>> from kingston import lang
>>> mystuff = (('Foo', 1), ('Bar', 2))
>>> for name, num in mystuff: locals()[name] = lang.mkclass(name, **{'num': num})
>>> Foo
<class 'kingston.lang.Foo'>
>>> Foo.num
1
>>> \
... @Foo.classmethod
... def myclassmethod(cls, x):
...     return x + 1
>>> Foo.myclassmethod(1)
2
>>>
>>> \
... @Foo.staticmethod
... def mystaticmethod(x, y):
...     return x + y
>>> Foo.mystaticmethod(1, 2)
3
>>> \
... @Foo.method
... def mymethod(self, x):
...     self.y = self.num + x
...     return self.y
>>> foo = Foo()
>>> foo.mymethod(1)
2
>>> foo.y
2
>>>

kingston module with developer convenience tools

The kingston.microscope module contains utilities that aid development. It has to ways to inspect live objects:

  1. Via ‘AbneuYAML’

    AbneuYAML is “Almost, but not entirely unlike YAML”. Objects dumped to ‘AbneuYAML’ should be easy to get a visual overview of for humans.

    To dump any object:

    >>> from kingston import microscope
    >>> class Cls: pass
    ...
    >>> c = Cls()
    >>> c.foo, c.bar = 1, 2
    >>> c.sub = Cls()
    >>> c.sub.foo, c.sub.bar, c.sub.baz = 3, 4, [1, 2]
    >>> encoded = microscope.abneuyaml(c)
    >>> print(encoded) #doctest: +ELLIPSIS
    <__main__.Cls object at 0x...>:Cls
      foo=1:int
      bar=2:int
      sub=<__main__.Cls object at 0x...>:Cls
        foo=3:int
        bar=4:int
        baz=[1, 2]:list
    >>>

A simple way of creating small DSL’s using Python operator overloading.

>>> from kingston import lang
>>> \
... class PipingExample(lang.Piping):
...     def __add__(self, value) -> lang.Piping:
...         self.queue(lambda a, b: a + b, value)
...         return self
...
>>> simplest_pipe = PipingExample(10)
>>> res = simplest_pipe + 10 + 20
>>> res()
40
>>>

Mostly, you’ll want to use the pipe operator to define simple composition:

>>> from kingston import lang
>>> incr = lambda x: x + 1
>>> showr = "It is {}!".format
>>> (lang.ComposePiping(5) >> incr >> incr >> showr)()
'It is 7!'
>>>

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kingston-0.6.3.tar.gz (15.8 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page