|
1 | 1 | Release Notes |
2 | 2 | ============= |
3 | 3 |
|
| 4 | +Version 2.3.0 |
| 5 | +------------- |
| 6 | + |
| 7 | +**New Features** |
| 8 | + |
| 9 | +* The ``__trunc__()``, ``__floor__()`` and ``__ceil__()`` special methods |
| 10 | + are now implemented by object proxies, delegating to ``math.trunc()``, |
| 11 | + ``math.floor()`` and ``math.ceil()`` applied to the wrapped object. As |
| 12 | + with other special methods, these are only looked up on the class type |
| 13 | + and not the instance, so they cannot rely on the ``__getattr__()`` |
| 14 | + fallback of the proxy and must be implemented explicitly. Previously |
| 15 | + calling ``math.trunc()`` on an object proxy raised ``TypeError``. These |
| 16 | + special methods sit somewhat outside the core Python object model in that |
| 17 | + they are not used by any builtin operators, with the ``math`` module |
| 18 | + being their only consumer. They are however documented as part of the |
| 19 | + Python data model and the ``math`` module is a key module in the standard |
| 20 | + library, so supporting them is warranted, in the same way as the existing |
| 21 | + support for ``__round__()``, which is consumed by the ``round()`` |
| 22 | + builtin. Note that although ``math.floor()`` and ``math.ceil()`` |
| 23 | + previously appeared to work when used on an object proxy, they were |
| 24 | + silently falling back to converting the proxy using ``__float__()``. If |
| 25 | + the wrapped object provided its own ``__floor__()`` or ``__ceil__()`` |
| 26 | + special methods these were ignored and the result could differ from that |
| 27 | + when the wrapped object was used directly. These now yield the same |
| 28 | + result as using the wrapped object directly. With thanks to Vincent Gao |
| 29 | + for `pull request #344 |
| 30 | + <https://github.com/GrahamDumpleton/wrapt/pull/344>`_. |
| 31 | + |
| 32 | +* The ``__fspath__()`` special method of the ``os.PathLike`` protocol has |
| 33 | + been added to the set of dunder methods which ``AutoObjectProxy`` |
| 34 | + detects on the wrapped object and adds to the class it generates, so a |
| 35 | + proxy it creates around a path-like object can now be used with |
| 36 | + ``os.fspath()``, the builtin ``open()`` and other standard library |
| 37 | + functions accepting paths. Note that ``__fspath__()`` is deliberately |
| 38 | + not implemented by the base object proxy, since its presence on the |
| 39 | + proxy type would cause every proxy to be classified as path-like by |
| 40 | + code branching on ``isinstance(obj, os.PathLike)``. Also be aware that |
| 41 | + ``AutoObjectProxy`` creates a new class for every proxy instance, so it |
| 42 | + should not be used to wrap path-like objects in large numbers due to |
| 43 | + the memory overhead. For high-frequency use define a custom proxy class |
| 44 | + which adds an explicit ``__fspath__()`` method instead. See the section |
| 45 | + on wrapping path-like objects in the known issues documentation for |
| 46 | + more details. |
| 47 | + |
| 48 | +**Features Changed** |
| 49 | + |
| 50 | +* The type stubs have been aligned with the runtime behaviour of the code |
| 51 | + and are now verified by ``stubtest`` against both the C extension and |
| 52 | + pure Python implementations. If using a type checker there are a couple |
| 53 | + of changes in what will be accepted which may be noticed. The |
| 54 | + ``__self_dict__`` attribute of proxy objects is now declared as a read |
| 55 | + only property, matching the runtime where assignment to it deliberately |
| 56 | + raises ``AttributeError``, so assignment to it will now be rejected by |
| 57 | + type checkers. The ``PartialCallableObjectProxy``, ``WeakFunctionProxy`` |
| 58 | + and ``bind_state_to_wrapper`` classes, which always derived from the base |
| 59 | + object proxy at runtime, are now also declared that way in the stubs. |
| 60 | + This means use of the object proxy interface on instances of these |
| 61 | + classes, such as accessing ``__wrapped__``, is no longer falsely |
| 62 | + rejected, although as a consequence of inheriting the permissive |
| 63 | + ``__getattr__()`` of the proxy, attribute typos on these classes will no |
| 64 | + longer be caught. The ``__class_getitem__()`` special method and the |
| 65 | + ``__bound_function_wrapper__`` attribute of ``FunctionWrapper`` are now |
| 66 | + also declared in the stubs. Finally, the pure Python implementation was |
| 67 | + brought into line with the C implementation and the descriptor protocol |
| 68 | + in two small ways. The ``owner`` argument of ``__get__()`` on function |
| 69 | + wrappers now defaults to ``None``, so manual binding using the one |
| 70 | + argument form works, and the argument to ``__class_getitem__()`` is now |
| 71 | + positional only. |
| 72 | + |
| 73 | +**Bugs Fixed** |
| 74 | + |
| 75 | +* Calling ``bytes()`` on an object proxy did not match calling ``bytes()`` |
| 76 | + on the wrapped object directly when the wrapped object did not implement |
| 77 | + ``__bytes__()``. The C extension implementation of ``__bytes__()`` used |
| 78 | + ``PyObject_Bytes()``, which only honours the ``__bytes__()`` protocol, so |
| 79 | + ``bytes(wrapt.ObjectProxy(3))`` raised ``TypeError`` even though |
| 80 | + ``bytes(3)`` returns a zero filled buffer. The pure Python implementation |
| 81 | + already used the ``bytes()`` constructor and was unaffected. The C |
| 82 | + extension now uses the ``bytes()`` constructor as well, so both |
| 83 | + implementations yield the same result as using the wrapped object |
| 84 | + directly. With thanks to Sanjay Santhanam for `pull request #345 |
| 85 | + <https://github.com/GrahamDumpleton/wrapt/pull/345>`_. |
| 86 | + |
4 | 87 | Version 2.2.2 |
5 | 88 | ------------- |
6 | 89 |
|
|
0 commit comments