Kgb

Latest version: v7.1.1

Safety actively analyzes 613568 Python packages for vulnerabilities to keep your Python projects secure.

Scan your dependencies

Page 1 of 3

7.1.1

=========================

* Small packaging update to include the ``LICENSE`` file.

No code changes.

7.1

=======================

* Added support for Python 3.11.


kgb 7 (20-January-2022)
=======================

* Added explicit support for Python 3.10.

* Dropped support for Python 2.6, 3.4, and 3.5.

* kgb now works as a plugin for pytest_.

Unit tests can use the ``spy_agency`` fixture to have a spy agency created
and ready for use. Spies will be automatically unregistered when the test
completes.

* Added snake_case versions of all assertion methods in ``SpyAgency``.

This includes:

* ``assert_has_spy``
* ``assert_spy_call_count``
* ``assert_spy_called_with``
* ``assert_spy_called``
* ``assert_spy_last_called_with``
* ``assert_spy_last_raised_message``
* ``assert_spy_last_raised``
* ``assert_spy_last_returned``
* ``assert_spy_not_called_with``
* ``assert_spy_not_called``
* ``assert_spy_raised_message``
* ``assert_spy_raised``
* ``assert_spy_returned``

* Added standalone assertion methods in ``kgb.asserts``.

This provides all the assertion methods shown above, but as standalone
methods that can work in any test suite.

* Added a ``func_name=`` argument when setting up spies, to avoid problems
with bad decorators.

When spying on an unbound method wrapped in a decorator that doesn't
preserve the function name, errors could occur.

In this case, you can pass ``func_name=`` when setting up the spy, telling
kgb about the original function name it should use.

This is a special situation. Most spies will not need to set this.

* Updated ``SpyCall.__repr__`` to list keyword arguments in sorted order.

* The package now lists the Python versions that are supported.

This will help down the road when we begin deprecating older versions of
Python, ensuring that ``pip`` will install the appropriate version of kgb
for the version of Python.


.. _pytest: https://pytest.org

6.1

========================

* Added new ``SpyOpReturnInOrder`` and ``SpyOpRaiseInOrder`` spy operations.

``SpyOpReturnInOrder`` takes a list of values to return. Each call made
will return the next value from that list. An exception will be raised
if any further calls are made once the list is exhausted.

``SpyOpRaiseInOrder`` is similar, but takes a list of exceptions to raise.

Examples:

.. code-block:: python

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

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

* ``SpyOpMatchInOrder`` and ``SpyOpMatchAny`` now accept operations in the
expected calls.

These can be set through an ``op`` key, instead of setting ``call_fake``
or ``call_original``.

For example:

.. code-block:: python

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

Any operation can be provided. This also allows for advanced, reusable
rule sets by nesting, for example, ``SpyOpMatchInOrder`` inside
``SpyOpMatchAny``.

* ``UnexpectedCallError`` now lists the call that was made in the error
message.

6.0

==========================

* Added a new ``spy_for`` decorator.

This is an alternative to defining a function and then calling
``spy_on(func, call_fake=...)``. It takes a function or method to spy on
and an optional owner, much like ``spy_on()``.

For example:

.. code-block:: python

def test_doomsday_device(self):
dd = DoomsdayDevice()

self.spy_for(dd.kaboom)
def _save_world(*args, **kwargs)
print('Sprinkles and ponies!')

* Added new support for Spy Operations.

Spy Operations can be thought of as pre-packaged "fake functions" for a spy,
which can perform some useful operations. There are a few built-in types:

* ``SpyOpMatchAny`` allows a caller to provide a list of all possible sets
of arguments that may be in one or more calls, triggering spy behavior
for the particular match (allowing ``call_original``/``call_fake`` to be
conditional on the arguments). Any call not provided in the list will
raise an ``UnexpectedCallError`` assertion.

* ``SpyOpMatchInOrder`` is similar to ``SpyOpMatchAny``, but the calls
must be in the order specified (which is useful for ensuring an order
of operations).

* ``SpyOpRaise`` takes an exception instance and raises it when the
function is called (preventing a caller from having to define a
wrapping function).

* ``SpyOpReturn`` takes a return value and returns it when the function is
called (similar to defining a simple lambda, but better specifying the
intent).

These are set with an ``op=`` argument, instead of a ``call_fake=``. For
example:

.. code-block:: python

spy_on(pen.emit_poison, op=kgb.SpyOpRaise(PoisonEmptyError()))

Or, for one of the more complex examples:

.. code-block:: python

spy_on(traps.trigger, op=kgb.SpyOpMatchAny([
{
'args': ('hallway_lasers',),
'call_fake': _send_wolves,
},
{
'args': ('trap_tile',),
'call_fake': _spill_hot_oil,
},
{
'args': ('infrared_camera',),
'kwargs': {
'sector': 'underground_passage',
},
'call_original': False,
},
]))

* Added an ``assertSpyNotCalledWith()`` assertion method.

Like the name suggests, it asserts that a spy has not been called with
the provided arguments. It's the inverse of ``assertSpyCalledWith()``.

* ``SpyAgency``'s assertion methods can now be used even without mixing it
into a ``TestCase``.

* Fixed a crash in ``SpyAgency.unspy_all()``.

* Fixed the grammar in an error message about slippery functions.

5.0

=======================

* Added support for Python 3.8.

Functions with positional-only arguments on Python 3.8 will now work
correctly, and the positional-only arguments will factor into any spy
matching.

* Added several new unit test assertion methods:

* ``assertHasSpy``
* ``assertSpyCalled``
* ``assertSpyNotCalled``
* ``assertSpyCallCount``
* ``assertSpyCalledWith``
* ``assertSpyLastCalledWith``
* ``assertSpyReturned``
* ``assertSpyLastReturned``
* ``assertSpyRaised``
* ``assertSpyLastRaised``
* ``assertSpyRaisedMessage``
* ``assertSpyLastRaisedMessage``

We recommend using these for unit tests instead of checking individual
properties of calls, as they'll provide better output and help you find out
why spies have gone rogue.

* Added support for spying on "slippery" functions.

A slippery function is defined (by us) as a function on an object that is
actually a different function every time you access it. In other words, if
you were to just reference a slippery function as an attribute two times,
you'd end up with two separate copies of that function, each with their own
ID.

This can happen if the "function" is actually some decorator that returns a
new function every time it's accessed. A real-world example would be the
Python Stripe module's API functions, like ``stripe.Customer.delete``.

In previous versions of kgb, you wouldn't be able to spy on these
functions. With 5.0, you can spy on them just fine by passing
``owner=<instance>`` when setting up the spy:

.. code-block:: python

spy_on(myobj.slippery_func,
owner=myobj)

* Lots of internal changes to help keep the codebase organized and
manageable, as Python support increases.

4.0

======================

* Added ``call_original()``, which calls the original spied-on function.

The call will not be logged, and will invoke the original behavior of
the function. This is useful when a spy simply needs to wrap another
function.

* Updated the Python 3 support to use the modern, non-deprecated support
for inspecting and formatting function/method signatures.

Page 1 of 3

© 2024 Safety CLI Cybersecurity Inc. All Rights Reserved.