Django Evolution 2.1.3: Evolution and compatibility fixes

Django Evolution 2.1.3 a small but important bug fix release that addresses issues with Python 3.10, mysqlclient, and evolving very old databases.

Compatibility Fixes

Python 3.10 removed some deprecated imports from collections, which Django 2.0 and older depend on. When using this combination of versions, Django Evolution will bring back those legacy imports, allowing Django to work again.

mysqlclient also received a similar fix. Django 1.11 and older depended on some unintentional functionality, which mysqlclient maintained until the 2.1 release. We now patch these versions of Django at runtime to continue working.

Upgrade Fixes

Two important issues affecting upgrades were addressed:

  1. Django Evolution no longer tries to apply evolutions to models that were just introduced. This was a regression from previous releases.
  2. When upgrading from very old databases, some state for a model’s unique_together index couldn’t be compared properly, causing issues applying some upgrades. The old format for this state is now taken into account during comparison.

Coming Up…

We’re preparing Django Evolution 2.2, which will support all versions of Django up through 4.0. This should be coming soon.

In the meantime, check out the release notes for the full changes, including other fixes in this release.

Read More

kgb 7.0: Pytest, Python 3.10, and more

kgb 7.0 has been released with a handful of new features:

  • Python 3.10 support
  • Support for pytest, and other non-unittest-based test frameworks
  • Snake-case and standalone assertion methods
  • Workarounds for spying on methods with poorly-implemented decorators

It also drops official support for Python 2.6 and 3.4-3.5 (though these should still work for now, if you need them).

pytest

kgb now provides a spy_agency fixture for pytest unit tests. This will set up a SpyAgency for you, letting you spy on functions and assert calls. For example:

def test_doomsday_device(spy_agency):
    device = DoomsdayDevice()
    spy_agency.spy_on(device.destroy_reality, call_original=False)

    device.trigger_the_event()

    spy_agency.assert_spy_called(device.destroy_reality)

The SpyAgency will be managed for the lifetime of the test, removing spies upon completion.

Snake-case and standalone assertion methods

We’ve provided snake_case versions of all the assertion methods, making for more natural tests. For instance, you can use assert_spy_called_with() instead of assertSpyCalledWith(). The old camelCase versions will continue to exist, though.

You can also call assertion methods without needing to mix in a SpyAgency into your test. Just import from kgb.asserts. This is useful if you have a need to spy on methods and assert them within non-unit test code, or without access to a SpyAgency. For example:

from kgb.asserts import assert_spy_called_with

def check_connection_state(api_connection):
    assert_spy_called_with(api_connection.make_request,
                           url='https://middleman.zyx',
                           method='POST')

Workarounds for bad decorators

Before, if you were trying to spy on a method (particularly unbound methods) wrapped in a decorator, and that decorator didn’t preserve the function’s original name, you’d hit an error looking up the method.

You can now work around this by passing the original function name when setting up a spy. For example:

def bad_decorator(func):
    def _wrap(*args, **kwargs):
        return func(*args, **kwargs)

    return _wrap

class BadClass:
    @bad_decorator
    def good_func(self):
        return 42

def test_good_func(spy_agency):
    spy_agency.spy_on(BadClass.good_func,
                      owner=BadClass,
                      func_name='good_func')

kgb will try to detect when you need this and emit a warning during the test.

Get started with kgb 7.0

See the release notes for the full list of changes.

You can install kgb today through pip:

$ pip install -U kgb

Visit our kgb documentation to see how to use kgb in your projects.

Read More

kgb 6.1: New spy operations, with nesting

kgb 6.1 has been released, featuring some new spy operations and enhancements to existing ones.

kgb is our Python unit test library for crafting function spies, making it easy to check on the calls made during a test or to override their behavior, in ways not possible with Python’s mock.

New spy operations

Two new spy operations, kgb.SpyOpReturnInOrder and kgb.SpyOpRaiseInOrder, have been added. These work like a combination of kgb.SpyOpReturn/kgb.SpyOpRaise and kgb.SpyOpMatchInOrder. Each takes a list of results, and each call will receive the next result in the list, making it really easy to build tests that, somewhere, involve repeated calls to some function.

For example:

spy_on(our_agent.get_identity, op=kgb.SpyOpReturnInOrder([
    'nobody...',
    'who?',
    'not telling...',
]))

spy_on(pen.emit_poison, op=kgb.SpyOpRaiseInOrder([
    PoisonEmptyError(),
    Kaboom(),
    MissingPenError(),
]))

Nesting spy operations

The kgb.SpyOpMatchInOrder and kgb.SpyOpMatchAny operations can now nest other spy operations, which simplifies returning or raising values, and can even allow for more advanced interactions with a spy.

The call definitions passed now accept an 'op' key pointing to a spy operation instance, which will be invoked if a call matches.

For example:

spy_on(lockbox.enter_code, op=kgb.SpyOpMatchInOrder([
    {
        'args': (42, 42, 42, 42, 42, 42),
        'op': kgb.SpyOpRaise(Kaboom()),
        'call_original': True,
    },
]))

Get started with 6.1

See the release notes for the full list of changes.

You can install kgb today through pip:

$ pip install -U kgb

Visit our kgb documentation to see how to use kgb in your projects.

Read More

beanbag-docutils 1.8: Sphinx 3 and Django 3

beanbag-docutils is a set of extensions to the Sphinx ReStructuredText-based documentation system used by our products to help generate better documentation. Amongst other enhancements, it provides:

  • A parser for the Beanbag docstring format, a variation on the Google docstring format, which we use for Python and JavaScript documentation
  • Enhancements for Sphinx’s intersphinx system to provide per-page intersphinx resolution options (useful for pages, such as release notes, that need to link to different versions of the same docs, such as Django or Python)
  • Enhancements to ReStructuredText references to let a reference name span lines (useful for long Python/JavaScript module/class names)
  • Linking code references to GitHub documentation
  • High-DPI image embedding
  • A role for HTTP status codes

Today’s release of beanbag-docutils 1.8 features:

  • Compatibility with Sphinx 1.7 through the latest 3.x (as of this writing, 3.5.1)
  • Compatibility with Django 3.x (when using the django_utils extension)
  • New documentation, which we’ll be expanding over time.

See the release notes for the full list of changes.

Read More