#86 Make your NoSQL async and await-able with uMongo

Python Bytes - A podcast by Michael Kennedy and Brian Okken - Luni

Categories:

Sponsored by DigitalOcean: pythonbytes.fm/digitalocean

Special guest Bob Belderbos: @bbelderbos

Brian #1: responses

  • “A utility for mocking out the Python Requests library.”
  • From Sentry

Example:

import responses
import requests

@responses.activate
def test_simple():
    responses.add(responses.GET, 'http://twitter.com/api/1/foobar',
                  json={'error': 'not found'}, status=404)
    resp = requests.get('http://twitter.com/api/1/foobar')
    assert resp.json() == {"error": "not found"}
    assert len(responses.calls) == 1
    assert responses.calls[0].request.url == 'http://twitter.com/api/1/foobar'
    assert responses.calls[0].response.text == '{"error": "not found"}'

Bob #2: 29 common beginner Python errors on one page

  • Decision trees / graphics are nice to digest and concise, it wraps a lot of experience on one slide
  • Knowing about common errors can safe you a lot of time (the guide I wish I had when I started coding in Python)
  • Reminded me of struggles I had when I started in Python, for example TypeErrors when converting suspected ints to strings, regexes before discovering raw strings
  • It made me think of related issues newer Pythonistas face, for example “I am reading a file but getting no input” can be translated to “I am looping over a generator for the second time and don’t get any output”
  • Made me realize that some things are subtle, like comparing 3 == “3” or require good knowledge of stdlib (sorted returning new sequence vs inplace sort() for example)
  • Made me reflect on how much hand holding you would give your students when teaching. Part of the learning is in the struggle.
  • About the source, I like seeing Python being taught in all different kind of domains, in this case biology.

Michael #3: μMongo

  • μMongo is a Python MongoDB ODM.
  • It inception comes from two needs:
    • the lack of async ODM
    • the difficulty to do document (un)serialization with existing ODMs.
  • a few design choices:
    • Stay close to the standards MongoDB driver to keep the same API when possible: use find({"field": "value"}) like usual but retrieve your data nicely OO wrapped !
    • Work with multiple drivers (PyMongo, TxMongo, motor_asyncio and mongomock for the moment)
    • Tight integration with Marshmallow serialization library to easily dump and load your data with the outside world
    • i18n integration to localize validation error messages
    • Free software: MIT license
    • Test with 90%+ coverage ;-)
  • async / await support through Motor

Brian #4: Basic Statistics in Python: Descriptive Statistics

  • Cool use of Python to teach basic statistics topics.
  • Includes code snippets to explain different concepts like min, max, mean, median, mode, …
  • However, after you understand the math, DON’T write your own functions.

Example from article:

sum_score = sum(scores)
num_score = len(scores)
avg_score = sum_score/num_score
avg_score
>>> 87.8884184721394

Using built in:

>>> x = (2, 2, 3, 100)
>>> min(x), max(x)
(2, 100)
>>> import statistics as s
>>> s.mean(x), s.median(x), s.mode(x)
(26.75, 2.5, 2)
>>> s.pstdev(x), s.pvariance(x)
(42.29287765097097, 1788.6875)
>>> s.stdev(x), s.variance(x)
(48.835608593184, 2384.9166666666665)

Bob #5: Strings and Character Data in Python

  • Everything you need to know to work with strings and more …
  • Similar to that great itertools article you shared some weeks ago: exhaustive overview
  • Nice re-usable code snippets and explanation of basic concepts, ideal for beginners but you likely will get something out of it, few useful bites:
    • Instead of try int(…) except, you can use isdigit() on a string
    • You can use isspace() to see if all characters of a nonempty string are whitespace characters ( ' ', tab '\t', and newline '\n')
    • It’s easy to make a header in your Python scripts:
>>>> 'bar'.center(10, '-')
        '---bar----'
- Replace up till n occurrences:
>>>> 'foo bar foo baz foo qux'.replace('foo', 'grault', 2)
        'grault bar grault baz foo qux'
- Strip multiple characters from both ends of a string:
>>>> 'www.realpython.com'.strip('w.moc')
        'realpython'
- Add leading padding to a string with `zfill`:
>>>> '42'.zfill(5)
        '00042'
  • This also reminded me of Python’s polymorphism, for example str.find and str.index work on both strings as well as lists
    >>> 'foo bar foo baz foo qux'.index('baz')
      12
    >>> 'foo bar foo baz foo qux'.split().index('baz')
      3
    >>> 'foo bar foo baz foo qux'.count('foo')
      3
    >>> 'foo bar foo baz foo qux'.split().count('foo')
      3

Michael #6: PEP 572: Assignment expressions accepted

  • Whoa, check out that twitter conversation
  • Splits 2 statements into an expressions (so they can be part of list comprehensions, etc).
  • Not sure I like it but here you go:

Example:

# Handle a matched regex
if (match := pattern.search(data)) is not None:
    ...

Contrast old and new:

# old
if self._is_special:
    ans = self._check_nans(context=context)
    if ans:
        return ans


# new
if self._is_special and (ans := self._check_nans(context=context)):
    return ans

Our news:

Visit the podcast's native language site