Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
24df416
Specify constants for native error policies.
picnixz Sep 27, 2024
a65c1b7
Add `PyCodec_UnregisterError` C API function
picnixz Sep 27, 2024
c1ff9e6
Expose `PyCodec_UnregisterError` as `codecs.unregister_error`
picnixz Sep 27, 2024
5837019
Update stable ABI files.
picnixz Sep 27, 2024
80d1ceb
update ignored.tsv
picnixz Sep 27, 2024
a134f23
add tests
picnixz Sep 27, 2024
47971e9
add docs
picnixz Sep 27, 2024
c00ad8d
add What's New entry
picnixz Sep 27, 2024
cf3bc2f
blurb
picnixz Sep 27, 2024
2108308
docs fix
picnixz Sep 27, 2024
1036516
simplify logic
picnixz Sep 27, 2024
ae601fe
nit: error message standardization
picnixz Sep 27, 2024
864c1ab
Make it a private utility for now.
picnixz Sep 28, 2024
3d9ff15
Revert "docs fix"
picnixz Sep 28, 2024
dbf0d5b
Revert "blurb"
picnixz Sep 28, 2024
5ba676c
Revert "add What's New entry"
picnixz Sep 28, 2024
8a0a0a9
Revert "add docs"
picnixz Sep 28, 2024
7915fa1
Revert "Update stable ABI files."
picnixz Sep 28, 2024
8eaa147
simplify array logic
picnixz Sep 28, 2024
7f41aec
update tests
picnixz Sep 28, 2024
988b34d
fix tests
picnixz Sep 28, 2024
c6e1d98
Duplicate standard error policies to avoid indirection.
picnixz Sep 28, 2024
dd6d210
standardize names
picnixz Sep 28, 2024
b68e54e
PEP 7
picnixz Sep 28, 2024
2c528fe
standardize names
picnixz Sep 28, 2024
c95cd65
revert renaming as well
picnixz Sep 28, 2024
101eb76
use 'built-in' instead of 'standard' terminology
picnixz Sep 28, 2024
903238a
use 'random.getrandbits' instead of 'os.urandom' to generate random IDs
picnixz Sep 28, 2024
a6c692d
address Victor's review
picnixz Sep 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions Doc/c-api/codec.rst
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,22 @@ Registry API for Unicode encoding error handlers

Return ``0`` on success, ``-1`` on error.

.. c:function:: int PyCodec_UnregisterError(const char *name)

Un-register the error handling callback function error under the given error
policy *name*. :ref:`Standard error policies <error-handlers>` cannot be
un-registered.

* Return ``-1`` and set a :exc:`ValueError` exception if *name* is a
standard error policy or if an error occurred (in which case the
existing exception is propagated).

* Return ``0`` if no error handler is associated with the given error policy.

* Return ``1`` if the error handler was successfully removed.

.. versionadded:: 3.14

.. c:function:: PyObject* PyCodec_LookupError(const char *name)

Lookup the error handling callback function registered under *name*. As a
Expand Down
3 changes: 3 additions & 0 deletions Doc/data/refcounts.dat
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,9 @@ PyCodec_RegisterError:int:::
PyCodec_RegisterError:const char*:name::
PyCodec_RegisterError:PyObject*:error:+1:

PyCodec_UnregisterError:int:::
PyCodec_UnregisterError:const char*:name::

PyCodec_LookupError:PyObject*::+1:
PyCodec_LookupError:const char*:name::

Expand Down
1 change: 1 addition & 0 deletions Doc/data/stable_abi.dat

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions Doc/library/codecs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,17 @@ handler:
replacement from the error handler will be put into the output directly.


.. function:: unregister_error(name)

Attempt to un-register the error handling function under the name *name*.

This raises a :exc:`ValueError` if *name* denotes a standard error policy
as specified above. Otherwise, this returns ``True`` if an error handler
existed for the given *name* and ``False`` otherwise.

.. versionadded:: 3.14


Previously registered error handlers (including the standard error handlers)
can be looked up by name:

Expand Down
11 changes: 11 additions & 0 deletions Doc/whatsnew/3.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,13 @@ ast
(Contributed by Irit Katriel in :gh:`123958`.)


codecs
------

* Added :func:`codecs.unregister_error` to un-register custom error handlers.
(Contributed by Bénédikt Tran in :gh:`124665`.)


ctypes
------

Expand Down Expand Up @@ -672,6 +679,10 @@ New Features
<https://peps.python.org/pep-0630/#type-checking>`__ mentioned in :pep:`630`
(:gh:`124153`).

* Add :c:func:`PyCodec_UnregisterError` to the limited C API to un-register
custom error handlers.
(Contributed by Bénédikt Tran in :gh:`124665`.)


Porting to Python 3.14
----------------------
Expand Down
12 changes: 12 additions & 0 deletions Include/codecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,18 @@ PyAPI_FUNC(PyObject *) PyCodec_StreamWriter(
Return 0 on success, -1 on error */
PyAPI_FUNC(int) PyCodec_RegisterError(const char *name, PyObject *error);

#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030e0000
/* Un-register the error handling callback function error under the given
name. Only non-native error handlers can be un-registered.

- Return -1 and set an exception if 'name' is a native error policy, or
if an error occurred.
- Return 0 if no error handler is associated with the given error policy.
- Return 1 if the error handler was successfully removed.
*/
PyAPI_FUNC(int) PyCodec_UnregisterError(const char *name);
#endif

/* Lookup the error handling callback function registered under the given
name. As a special case NULL can be passed, in which case
the error handling callback for "strict" will be returned. */
Expand Down
25 changes: 25 additions & 0 deletions Lib/test/test_codeccallbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -1235,6 +1235,31 @@ class FakeUnicodeError(Exception):
with self.assertRaises((TypeError, FakeUnicodeError)):
handler(FakeUnicodeError())

def test_reject_unregister_native_error_policy(self):
for policy in [
'strict', 'ignore', 'replace', 'backslashreplace', 'namereplace',
'xmlcharrefreplace', 'surrogateescape', 'surrogatepass',
]:
with self.subTest(f'reject native {policy!r} un-registration'):
self.assertRaises(ValueError, codecs.unregister_error, policy)

def test_unregister_custom_error_policy(self):
def custom_handler(exc):
raise exc

custom_name = f'test.test_unregister_error.custom.{id(self)}'
self.assertRaises(LookupError, codecs.lookup_error, custom_name)
codecs.register_error(custom_name, custom_handler)
self.assertIs(codecs.lookup_error(custom_name), custom_handler)
self.assertTrue(codecs.unregister_error(custom_name))
self.assertRaises(LookupError, codecs.lookup_error, custom_name)

def test_unregister_custom_unknown_error_policy(self):
unknown_name = f'test.test_unregister_error.custom.{id(self)}.unknown'
self.assertRaises(LookupError, codecs.lookup_error, unknown_name)
self.assertFalse(codecs.unregister_error(unknown_name))
self.assertRaises(LookupError, codecs.lookup_error, unknown_name)


if __name__ == "__main__":
unittest.main()
1 change: 1 addition & 0 deletions Lib/test/test_stable_abi_ctypes.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Add :c:func:`PyCodec_UnregisterError` to the limited C API to un-register
custom error handlers. Patch by Bénédikt Tran.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Added :func:`codecs.unregister_error` to un-register custom error handlers.
Patch by Bénédikt Tran.
2 changes: 2 additions & 0 deletions Misc/stable_abi.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2510,6 +2510,8 @@
added = '3.14'
[function.Py_REFCNT]
added = '3.14'
[function.PyCodec_UnregisterError]
added = '3.14'
[function.PyIter_NextItem]
added = '3.14'
[function.PyLong_FromInt32]
Expand Down
21 changes: 21 additions & 0 deletions Modules/_codecsmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -979,6 +979,26 @@ _codecs_register_error_impl(PyObject *module, const char *errors,
Py_RETURN_NONE;
}

/*[clinic input]
_codecs.unregister_error -> bool
errors: str
/

Un-register the specified error handler under the name errors.

Only custom handlers can be un-registered. Returns True if the
handler has been successfully un-registered, and False if the
errors policy is not recognized. An exception is raised when
the errors policy is not allowed.
[clinic start generated code]*/

static int
_codecs_unregister_error_impl(PyObject *module, const char *errors)
/*[clinic end generated code: output=d8c1418e402aecdf input=103c9dae16f32e08]*/
{
return PyCodec_UnregisterError(errors);
}

/*[clinic input]
_codecs.lookup_error
name: str
Expand Down Expand Up @@ -1044,6 +1064,7 @@ static PyMethodDef _codecs_functions[] = {
_CODECS_CODE_PAGE_ENCODE_METHODDEF
_CODECS_CODE_PAGE_DECODE_METHODDEF
_CODECS_REGISTER_ERROR_METHODDEF
_CODECS_UNREGISTER_ERROR_METHODDEF
_CODECS_LOOKUP_ERROR_METHODDEF
{NULL, NULL} /* sentinel */
};
Expand Down
49 changes: 48 additions & 1 deletion Modules/clinic/_codecsmodule.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions PC/python3dll.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading