From 973020c6b43b8bfc56a666c3541a3082df0f6a87 Mon Sep 17 00:00:00 2001 From: MrTango Date: Tue, 11 Feb 2025 13:55:29 +0100 Subject: [PATCH 01/28] add deprecation chapter --- .gitignore | 3 + docs/backend/deprecation.md | 311 ++++++++++++++++++++++++++++++++++++ docs/backend/index.md | 1 + 3 files changed, 315 insertions(+) create mode 100644 docs/backend/deprecation.md diff --git a/.gitignore b/.gitignore index a825459902..7d91e6a2d6 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,6 @@ docs/volto # editor files .vscode +/bin/ +/lib +/lib64 diff --git a/docs/backend/deprecation.md b/docs/backend/deprecation.md new file mode 100644 index 0000000000..de87412692 --- /dev/null +++ b/docs/backend/deprecation.md @@ -0,0 +1,311 @@ +--- +myst: + html_meta: + "description": "A guide how to do depracations, including Python, ZCML and templates in Plone." + "property=og:description": "A guide how to do depracations, including Python, ZCML and templates in Plone." + "property=og:title": "Deprecation" + "keywords": "depracation, zcml, template, jbot" +--- + +(backend-deprecation-label)= +# Deprecation + +## Introduction + +This document describes rationales, configuration and best practices of deprecations in Plone, Zope and Python. +It is meant as a styleguide on how to apply deprecations in Plone core packages. +It also has a value as a general overview on how to deprecate in Python. + + +### Why Deprecation + +At some point we + +- need to get rid of old code, +- want to unify api style (consistent api), +- fix typos in namings, +- move code or templates around (inside package or to another package). + +While refactoring code, moving modules, functions, classes and methods is often needed. +To not break third party code imports from the old place or usage of old functions/ methods must work for while. +Deprecated methods are usually removed with the next major release of Plone. +Following the [semantic versioning guideline](http://semver.org) is recommended. + +### Help Programmers, No annoyance + +Deprecation has to support the consumers of the code - the programmers using it. +From their point of view, Plone core code is an API to them. +Any change is annoying to them anyway, but they feel better if deprecation warnings are telling them what to do. + +Deprecations must always log at level *warning* and have to answers the question: + +**"Why is the code gone from the old place? What to do instead?"** + +A short message is enough., i.e.: + +- "Replaced by new API xyz, found at abc.cde"., +- "Moved to xyz, because of abc.", +- "Name had a typo, new name is "xyz". + +All logging has to be done once, i.e. on first usage or first import. +It must not flood the logs. + +### Use Cases + +Renaming + +: We may want to rename classes, methods, functions or global or class variables in order to get a more consistent api or because of a typo, etc. + We never just rename, we always provide a deprecated version logging a verbose deprecation warning with information where to + import from in future. + +Moving a module, class, function, etc to another place + +: For some reason, i.e. merging packages, consistent api or resolving cirular import problems, we need to move code around. + When imported from the old place it logs a verbose deprecation warning with information where to import from in future. + +Deprecation of a whole package + +: A whole package (folder with `__init__.py`) + + - all imports still working, logging deprecation warnings on first import + - ZCML still exists, but is empty (or includes the zcml from the new place if theres no auto import (i.e. for meta.zcml). + +Deprecation of a whole python egg + +: We will provide a last major release with no 'real' code, only backward compatible (bbb) imports of public API are provided. + This will be done the way described above for a whole package. + The README clearly states why it was moved and where to find the code now. + +Deprecation of a GenericSetup profile + +: They may got renamed for consistency or are superfluos after an update. + Code does not need to break to support this. + +## Enable Deprecation Warnings + +### Zope + +Zope does configure logging and warnings, so the steps below (under section Python) are not needed. + +Using `plone.recipe.zope2instance` add the option `deprecation-warnings = on` to the buildouts `[instance]` section. + +```ini +[buildout] +parts = instance + +[instance] +recipe = plone.recipe.zope2instance +... +deprecation-warnings = on +... +``` + +This just sets a configuration option in `zope.conf`. + +Without the recipe this can be set manually as well: +In `zope.conf` custom filters for warnings can be defined. + +```xml +... + + action always + category exceptions.DeprecationWarning + +... +``` + +### Python + +Enable Warnings + +: Warnings are written to `stderr` by default, but `DeprecationWarning` output is surpressed by default. + + Output can be enabled by starting the Python interpreter with the [-W \[all|module|once\]](https://docs.python.org/2/using/cmdline.html#cmdoption-W) option. + + It is possible to enable output in code too: + + ```python + import warnings + warnings.simplefilter("module") + ``` + +Configure Logging + +: Once output is enabled it is possible to [redirect warnings to the logger](https://docs.python.org/2/library/logging.html#logging.captureWarnings): + + ```python + import logging + logging.captureWarnings(True) + ``` + +### Running tests + +In Plone tests deprecation warnings are not shown by default. +The `zope.conf` setting is not taken into account. + +In order to enable deprecation warnings, +the Python way with the `-W` command option must to be used. + +Given youre using a modern buildout with virtualenv as recommended, +the call looks like so: + +```bash +./bin/python -W module ./bin/test +``` + +## Deprecation Best Practice + +### Vanilla Deprecation Messages + +Python offers a built-in `DeprecationWarning` which can be issued using standard libraries `warnings` module. + +For details read the [official documentation about warnings](https://docs.python.org/2/library/warnings.html). + +In short it works like so + +```python +import warnings +warnings.warn('deprecated', DeprecationWarning) +``` + +### Moving Whole Modules + +Given a package `old.pkg` with a module `foo.py` need to be moved to a package `new.pkg` as `bar.py`. + +[zope.deprecation Moving modules](http://docs.zope.org/zope.deprecation/api.html#moving-modules) offers a helper. + +1. Move the `foo.py` as `bar.py` to the `new.pkg`. +2. At the old place create a new `foo.py` and add to it + +```python +from zope.deprecation import moved +moved('new.pkg.bar', 'Version 2.0') +``` + +Now you can still import the namespace from `bar` at the old place, but get a deprecation warning: + +> DeprecationWarning: old.pkg.foo has moved to new.pkg.bar. +> Import of old.pkg.foo will become unsupported in Version 2.0 + +### Moving Whole Packages + +This is the same as moving a module, just create for each module a file. + +### Deprecating methods and properties + +You can use the `@deprecate` decorator from [zope.deprecation Deprecating methods and properties](http://docs.zope.org/zope.deprecation/api.html#deprecating-methods-and-properties) to deprecate methods in a module: + +```python +from zope.deprecation import deprecate + +@deprecate('Old method is no longer supported, use new_method instead.') +def old_method(): + return 'some value' +``` + +The `deprecated` wrapper method is for deprecating properties: + +```python +from zope.deprecation import deprecated + +foo = None +foo = deprecated(foo, 'foo is no more, use bar instead') +``` + +### Moving functions and classes + +Given we have a Python file at `old/foo/bar.py` and want to move some classes or functions to `new/baz/baaz.py`. + +Here `zope.deferredimport` offers a deprecation helper. +It also avoids circular imports on initialization time. + +```python +import zope.deferredimport +zope.deferredimport.initialize() + +zope.deferredimport.deprecated( + "Import from new.baz.baaz instead", + SomeOldClass='new.baz:baaz.SomeMovedClass', + some_old_function='new.baz:baaz.some_moved_function', +) + +def some_function_which_is_not_touched_at_all(): + pass +``` + +### Deprecating a GenericSetup profile + +Starting with GenericSetup 1.8.2 (part of Plone > 5.0.2) the `post_handler` attribute in ZCML can be used to call a function after the profile was applied. +We use this feature to issue a warning. + +First we register the same profile twice. Under the new name and under the old name: + +```xml + + + +``` + +And in `setuphandlers.py` add a function: + +```python +import warnings + +def deprecate_profile_some_confusing_name(tool): + warnings.warn( + 'The profile with id "some_confusing_name" was renamed to "default".', + DeprecationWarning + ) +``` + +### Deprecating a template position + +Sometimes we need to move templates to new locations. Since addons often use jbot to override templates by their position, we need to point them to the new position as well as make sure that the override still works with the old position. + + +In the old package folders `__init__.py` we add a mapping dict with the name `jbot_deprecations` of old and new template location: + +```python +jbot_deprecations = { + "plone.locking.browser.info.pt": "plone.app.layout.viewlets.info.pt" +} +``` + +add a jbot-deprecations config to the `configure.zcml` file + +create a `jbot_deprecations.zcml` file: + +```{code-block} xml +:emphasize-lines: 6,9-12 +:linenos: + + + + + + + + + +``` + +this will load the defined `jbot_deprecations` dictionary. diff --git a/docs/backend/index.md b/docs/backend/index.md index 3e7dd32784..9411e26f70 100644 --- a/docs/backend/index.md +++ b/docs/backend/index.md @@ -22,6 +22,7 @@ behaviors configuration-registry content-types/index control-panels +deprecation fields global-utils indexing From bd6eac99a7b0f9d357fb35de1660c676faf2cf26 Mon Sep 17 00:00:00 2001 From: MrTango Date: Tue, 11 Feb 2025 14:44:25 +0100 Subject: [PATCH 02/28] fix broken links in deprecation chapter --- docs/backend/deprecation.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/backend/deprecation.md b/docs/backend/deprecation.md index de87412692..3edd49b4c2 100644 --- a/docs/backend/deprecation.md +++ b/docs/backend/deprecation.md @@ -120,7 +120,7 @@ Enable Warnings : Warnings are written to `stderr` by default, but `DeprecationWarning` output is surpressed by default. - Output can be enabled by starting the Python interpreter with the [-W \[all|module|once\]](https://docs.python.org/2/using/cmdline.html#cmdoption-W) option. + Output can be enabled by starting the Python interpreter with the [-W \[all|module|once\]](https://docs.python.org/3/using/cmdline.html#cmdoption-W) option. It is possible to enable output in code too: @@ -131,7 +131,7 @@ Enable Warnings Configure Logging -: Once output is enabled it is possible to [redirect warnings to the logger](https://docs.python.org/2/library/logging.html#logging.captureWarnings): +: Once output is enabled it is possible to [redirect warnings to the logger](https://docs.python.org/3/library/logging.html#logging.captureWarnings): ```python import logging @@ -159,7 +159,7 @@ the call looks like so: Python offers a built-in `DeprecationWarning` which can be issued using standard libraries `warnings` module. -For details read the [official documentation about warnings](https://docs.python.org/2/library/warnings.html). +For details read the [official documentation about warnings](https://docs.python.org/3/library/warnings.html). In short it works like so @@ -172,7 +172,7 @@ warnings.warn('deprecated', DeprecationWarning) Given a package `old.pkg` with a module `foo.py` need to be moved to a package `new.pkg` as `bar.py`. -[zope.deprecation Moving modules](http://docs.zope.org/zope.deprecation/api.html#moving-modules) offers a helper. +[zope.deprecation Moving modules](https://zopedeprecation.readthedocs.io/en/latest/api.html#moving-modules) offers a helper. 1. Move the `foo.py` as `bar.py` to the `new.pkg`. 2. At the old place create a new `foo.py` and add to it @@ -193,7 +193,7 @@ This is the same as moving a module, just create for each module a file. ### Deprecating methods and properties -You can use the `@deprecate` decorator from [zope.deprecation Deprecating methods and properties](http://docs.zope.org/zope.deprecation/api.html#deprecating-methods-and-properties) to deprecate methods in a module: +You can use the `@deprecate` decorator from [zope.deprecation Deprecating methods and properties](https://zopedeprecation.readthedocs.io/en/latest/api.html#deprecating-methods-and-properties) to deprecate methods in a module: ```python from zope.deprecation import deprecate From ff7461bacffb8f4a699a283df90013a519011e94 Mon Sep 17 00:00:00 2001 From: Maik Derstappen Date: Tue, 11 Feb 2025 16:01:58 +0200 Subject: [PATCH 03/28] Update docs/backend/deprecation.md Co-authored-by: Alessandro Pisa --- docs/backend/deprecation.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/backend/deprecation.md b/docs/backend/deprecation.md index 3edd49b4c2..2c3f012b53 100644 --- a/docs/backend/deprecation.md +++ b/docs/backend/deprecation.md @@ -29,6 +29,7 @@ At some point we While refactoring code, moving modules, functions, classes and methods is often needed. To not break third party code imports from the old place or usage of old functions/ methods must work for while. Deprecated methods are usually removed with the next major release of Plone. + Following the [semantic versioning guideline](http://semver.org) is recommended. ### Help Programmers, No annoyance From 6027930e27a52b8c40fc0058798a378c490b3ce4 Mon Sep 17 00:00:00 2001 From: Maik Derstappen Date: Tue, 11 Feb 2025 16:02:22 +0200 Subject: [PATCH 04/28] Update docs/backend/deprecation.md Co-authored-by: Alessandro Pisa --- docs/backend/deprecation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/backend/deprecation.md b/docs/backend/deprecation.md index 2c3f012b53..fe418e7d54 100644 --- a/docs/backend/deprecation.md +++ b/docs/backend/deprecation.md @@ -274,7 +274,7 @@ def deprecate_profile_some_confusing_name(tool): ### Deprecating a template position -Sometimes we need to move templates to new locations. Since addons often use jbot to override templates by their position, we need to point them to the new position as well as make sure that the override still works with the old position. +Sometimes we need to move templates to new locations. Since addons often use [z3c.jbot](https://github.com/zopefoundation/z3c.jbot) to override templates by their position, we need to point them to the new position as well as make sure that the override still works with the old position. In the old package folders `__init__.py` we add a mapping dict with the name `jbot_deprecations` of old and new template location: From e6acc830944237e0284f763ebe0c960de999ea48 Mon Sep 17 00:00:00 2001 From: Maik Derstappen Date: Tue, 11 Feb 2025 16:02:43 +0200 Subject: [PATCH 05/28] Update docs/backend/deprecation.md Co-authored-by: Alessandro Pisa From b9090696e774066788c5900aec5179ced6a8499f Mon Sep 17 00:00:00 2001 From: Maik Derstappen Date: Tue, 11 Feb 2025 16:03:21 +0200 Subject: [PATCH 06/28] Update docs/backend/deprecation.md Co-authored-by: Alessandro Pisa --- docs/backend/deprecation.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/backend/deprecation.md b/docs/backend/deprecation.md index fe418e7d54..c086ec2f03 100644 --- a/docs/backend/deprecation.md +++ b/docs/backend/deprecation.md @@ -277,6 +277,8 @@ def deprecate_profile_some_confusing_name(tool): Sometimes we need to move templates to new locations. Since addons often use [z3c.jbot](https://github.com/zopefoundation/z3c.jbot) to override templates by their position, we need to point them to the new position as well as make sure that the override still works with the old position. +To deprecate a package: + In the old package folders `__init__.py` we add a mapping dict with the name `jbot_deprecations` of old and new template location: ```python From b0923fbd7e6268b938c8628c455b98b75719e5a8 Mon Sep 17 00:00:00 2001 From: Maik Derstappen Date: Tue, 11 Feb 2025 16:03:34 +0200 Subject: [PATCH 07/28] Update docs/backend/deprecation.md Co-authored-by: Alessandro Pisa --- docs/backend/deprecation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/backend/deprecation.md b/docs/backend/deprecation.md index c086ec2f03..45792d9a7b 100644 --- a/docs/backend/deprecation.md +++ b/docs/backend/deprecation.md @@ -279,7 +279,7 @@ Sometimes we need to move templates to new locations. Since addons often use [z3 To deprecate a package: -In the old package folders `__init__.py` we add a mapping dict with the name `jbot_deprecations` of old and new template location: +1. In the old package folders `__init__.py` add a dictionary `jbot_deprecations` that maps the old template locations to their new counterparts, e.g.: ```python jbot_deprecations = { From 7ca4ede254adcb590e2359584ad8e46a12fcaede Mon Sep 17 00:00:00 2001 From: Maik Derstappen Date: Tue, 11 Feb 2025 16:03:51 +0200 Subject: [PATCH 08/28] Update docs/backend/deprecation.md Co-authored-by: Alessandro Pisa --- docs/backend/deprecation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/backend/deprecation.md b/docs/backend/deprecation.md index 45792d9a7b..83aa62b07c 100644 --- a/docs/backend/deprecation.md +++ b/docs/backend/deprecation.md @@ -287,7 +287,7 @@ jbot_deprecations = { } ``` -add a jbot-deprecations config to the `configure.zcml` file +2. Add this deprecation snippet to the package `configure.zcml` file: create a `jbot_deprecations.zcml` file: From 66a58dcafb104b906a0eab861c3696f3ad9d9a35 Mon Sep 17 00:00:00 2001 From: Maik Derstappen Date: Tue, 11 Feb 2025 16:04:10 +0200 Subject: [PATCH 09/28] Update docs/backend/deprecation.md Co-authored-by: Alessandro Pisa --- docs/backend/deprecation.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/backend/deprecation.md b/docs/backend/deprecation.md index 83aa62b07c..fcd6d913d8 100644 --- a/docs/backend/deprecation.md +++ b/docs/backend/deprecation.md @@ -289,8 +289,6 @@ jbot_deprecations = { 2. Add this deprecation snippet to the package `configure.zcml` file: -create a `jbot_deprecations.zcml` file: - ```{code-block} xml :emphasize-lines: 6,9-12 :linenos: From c859367a1af8558fd8949ee330b1c1f92554ac13 Mon Sep 17 00:00:00 2001 From: Maik Derstappen Date: Tue, 11 Feb 2025 16:04:20 +0200 Subject: [PATCH 10/28] Update docs/backend/deprecation.md Co-authored-by: Alessandro Pisa --- docs/backend/deprecation.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/backend/deprecation.md b/docs/backend/deprecation.md index fcd6d913d8..c76564c075 100644 --- a/docs/backend/deprecation.md +++ b/docs/backend/deprecation.md @@ -294,7 +294,6 @@ jbot_deprecations = { :linenos: Date: Tue, 11 Feb 2025 16:04:33 +0200 Subject: [PATCH 11/28] Update docs/backend/deprecation.md Co-authored-by: Alessandro Pisa --- docs/backend/deprecation.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/backend/deprecation.md b/docs/backend/deprecation.md index c76564c075..4341c68db3 100644 --- a/docs/backend/deprecation.md +++ b/docs/backend/deprecation.md @@ -296,7 +296,6 @@ jbot_deprecations = { From c7cad7a8ff52c048ed4fcaf9c828119c5783e834 Mon Sep 17 00:00:00 2001 From: Maik Derstappen Date: Tue, 11 Feb 2025 16:08:05 +0200 Subject: [PATCH 12/28] Update docs/backend/deprecation.md Co-authored-by: Alessandro Pisa --- docs/backend/deprecation.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/backend/deprecation.md b/docs/backend/deprecation.md index 4341c68db3..a9e720b7c5 100644 --- a/docs/backend/deprecation.md +++ b/docs/backend/deprecation.md @@ -299,10 +299,15 @@ jbot_deprecations = { xmlns:zcml="http://namespaces.zope.org/zcml" > - - - - + + ``` From a9fc020a60779d4af40b0b473575d2d5d831b5d5 Mon Sep 17 00:00:00 2001 From: MrTango Date: Tue, 11 Feb 2025 15:09:12 +0100 Subject: [PATCH 13/28] remove meta.zcml attribute from z3c.jbot include --- docs/backend/deprecation.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/backend/deprecation.md b/docs/backend/deprecation.md index a9e720b7c5..caa5766edb 100644 --- a/docs/backend/deprecation.md +++ b/docs/backend/deprecation.md @@ -301,8 +301,7 @@ jbot_deprecations = { Date: Tue, 11 Feb 2025 16:09:59 +0200 Subject: [PATCH 14/28] Update docs/backend/deprecation.md Co-authored-by: Alessandro Pisa --- docs/backend/deprecation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/backend/deprecation.md b/docs/backend/deprecation.md index caa5766edb..c3e49a2d83 100644 --- a/docs/backend/deprecation.md +++ b/docs/backend/deprecation.md @@ -311,4 +311,4 @@ jbot_deprecations = { ``` -this will load the defined `jbot_deprecations` dictionary. +If a `z3c.jbot` version that supports deprecation is found, trying to override the template with the old location will trigger a deprecation warning that will instruct the user to rename its override file. From cff3ad670fba66da06f1759f71d5ef12ad66cd8f Mon Sep 17 00:00:00 2001 From: Alessandro Pisa Date: Tue, 11 Feb 2025 16:03:29 +0100 Subject: [PATCH 15/28] Fix ty --- docs/backend/deprecation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/backend/deprecation.md b/docs/backend/deprecation.md index c3e49a2d83..c78578525a 100644 --- a/docs/backend/deprecation.md +++ b/docs/backend/deprecation.md @@ -1,7 +1,7 @@ --- myst: html_meta: - "description": "A guide how to do depracations, including Python, ZCML and templates in Plone." + "description": "A guide how to do deprecations, including Python, ZCML and templates in Plone." "property=og:description": "A guide how to do depracations, including Python, ZCML and templates in Plone." "property=og:title": "Deprecation" "keywords": "depracation, zcml, template, jbot" From d0286e49cff9bb55dad62237a24772ed0a017eb0 Mon Sep 17 00:00:00 2001 From: Alessandro Pisa Date: Tue, 11 Feb 2025 16:03:42 +0100 Subject: [PATCH 16/28] Fix typo --- docs/backend/deprecation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/backend/deprecation.md b/docs/backend/deprecation.md index c78578525a..1f15b92ce6 100644 --- a/docs/backend/deprecation.md +++ b/docs/backend/deprecation.md @@ -2,7 +2,7 @@ myst: html_meta: "description": "A guide how to do deprecations, including Python, ZCML and templates in Plone." - "property=og:description": "A guide how to do depracations, including Python, ZCML and templates in Plone." + "property=og:description": "A guide how to do deprecations, including Python, ZCML and templates in Plone." "property=og:title": "Deprecation" "keywords": "depracation, zcml, template, jbot" --- From 1c733a301cbc7cec378c9335148910064127c0cc Mon Sep 17 00:00:00 2001 From: Alessandro Pisa Date: Tue, 11 Feb 2025 16:03:50 +0100 Subject: [PATCH 17/28] Fix typo --- docs/backend/deprecation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/backend/deprecation.md b/docs/backend/deprecation.md index 1f15b92ce6..eb33ca9af7 100644 --- a/docs/backend/deprecation.md +++ b/docs/backend/deprecation.md @@ -4,7 +4,7 @@ myst: "description": "A guide how to do deprecations, including Python, ZCML and templates in Plone." "property=og:description": "A guide how to do deprecations, including Python, ZCML and templates in Plone." "property=og:title": "Deprecation" - "keywords": "depracation, zcml, template, jbot" + "keywords": "deprecation, zcml, template, jbot" --- (backend-deprecation-label)= From 49e96f82cfb9e22804b8790b583ec8130dc320c8 Mon Sep 17 00:00:00 2001 From: Maik Derstappen Date: Wed, 12 Feb 2025 11:39:42 +0200 Subject: [PATCH 18/28] Update docs/backend/deprecation.md Co-authored-by: Alessandro Pisa --- docs/backend/deprecation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/backend/deprecation.md b/docs/backend/deprecation.md index eb33ca9af7..2f2fbb3fe0 100644 --- a/docs/backend/deprecation.md +++ b/docs/backend/deprecation.md @@ -19,7 +19,7 @@ It also has a value as a general overview on how to deprecate in Python. ### Why Deprecation -At some point we +At some point we: - need to get rid of old code, - want to unify api style (consistent api), From 8608dffba3c6eda340b3eb908b4b03faa3662352 Mon Sep 17 00:00:00 2001 From: Maik Derstappen Date: Wed, 12 Feb 2025 11:39:59 +0200 Subject: [PATCH 19/28] Update docs/backend/deprecation.md Co-authored-by: Alessandro Pisa --- docs/backend/deprecation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/backend/deprecation.md b/docs/backend/deprecation.md index 2f2fbb3fe0..7ab10a4e12 100644 --- a/docs/backend/deprecation.md +++ b/docs/backend/deprecation.md @@ -61,7 +61,7 @@ Renaming Moving a module, class, function, etc to another place -: For some reason, i.e. merging packages, consistent api or resolving cirular import problems, we need to move code around. +: For some reason, i.e. merging packages, consistent API or resolving cirular import problems, we need to move code around. When imported from the old place it logs a verbose deprecation warning with information where to import from in future. Deprecation of a whole package From 155c344a143d4e64aa696dd4e9da6d4bb3e52872 Mon Sep 17 00:00:00 2001 From: Maik Derstappen Date: Wed, 12 Feb 2025 11:40:15 +0200 Subject: [PATCH 20/28] Update docs/backend/deprecation.md Co-authored-by: Alessandro Pisa --- docs/backend/deprecation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/backend/deprecation.md b/docs/backend/deprecation.md index 7ab10a4e12..138d355332 100644 --- a/docs/backend/deprecation.md +++ b/docs/backend/deprecation.md @@ -55,7 +55,7 @@ It must not flood the logs. Renaming -: We may want to rename classes, methods, functions or global or class variables in order to get a more consistent api or because of a typo, etc. +: We may want to rename classes, methods, functions or global or class variables in order to get a more consistent API or because of a typo, etc. We never just rename, we always provide a deprecated version logging a verbose deprecation warning with information where to import from in future. From 295f3f53c3317b52e8592d769fe87987f5b1cb3f Mon Sep 17 00:00:00 2001 From: Maik Derstappen Date: Wed, 12 Feb 2025 11:40:31 +0200 Subject: [PATCH 21/28] Update docs/backend/deprecation.md Co-authored-by: Alessandro Pisa --- docs/backend/deprecation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/backend/deprecation.md b/docs/backend/deprecation.md index 138d355332..2c0c4848c3 100644 --- a/docs/backend/deprecation.md +++ b/docs/backend/deprecation.md @@ -22,7 +22,7 @@ It also has a value as a general overview on how to deprecate in Python. At some point we: - need to get rid of old code, -- want to unify api style (consistent api), +- want to unify API style (consistent API), - fix typos in namings, - move code or templates around (inside package or to another package). From 5db30276ca5dedb6103533c685122f4f972b80a7 Mon Sep 17 00:00:00 2001 From: Maik Derstappen Date: Wed, 12 Feb 2025 11:40:53 +0200 Subject: [PATCH 22/28] Update docs/backend/deprecation.md Co-authored-by: Alessandro Pisa --- docs/backend/deprecation.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/backend/deprecation.md b/docs/backend/deprecation.md index 2c0c4848c3..4285665197 100644 --- a/docs/backend/deprecation.md +++ b/docs/backend/deprecation.md @@ -101,7 +101,11 @@ deprecation-warnings = on ... ``` -This just sets a configuration option in `zope.conf`. +This adds this line to the `zope.conf` file: + +``` +debug-mode on +``` Without the recipe this can be set manually as well: In `zope.conf` custom filters for warnings can be defined. From 0bacab8045878ae64b9420cc617530d11211dee7 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 15 Feb 2025 22:23:49 -0800 Subject: [PATCH 23/28] Apply suggestions from code review Co-authored-by: Alessandro Pisa Co-authored-by: Jens W. Klein --- .gitignore | 3 --- docs/backend/deprecation.md | 8 ++++---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 7d91e6a2d6..a825459902 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,3 @@ docs/volto # editor files .vscode -/bin/ -/lib -/lib64 diff --git a/docs/backend/deprecation.md b/docs/backend/deprecation.md index 4285665197..80a0a98e64 100644 --- a/docs/backend/deprecation.md +++ b/docs/backend/deprecation.md @@ -30,11 +30,11 @@ While refactoring code, moving modules, functions, classes and methods is often To not break third party code imports from the old place or usage of old functions/ methods must work for while. Deprecated methods are usually removed with the next major release of Plone. -Following the [semantic versioning guideline](http://semver.org) is recommended. +Following the [semantic versioning guideline](https://semver.org) is recommended. ### Help Programmers, No annoyance -Deprecation has to support the consumers of the code - the programmers using it. +The developers should use code deprecations to support the consumers of the code. From their point of view, Plone core code is an API to them. Any change is annoying to them anyway, but they feel better if deprecation warnings are telling them what to do. @@ -66,12 +66,12 @@ Moving a module, class, function, etc to another place Deprecation of a whole package -: A whole package (folder with `__init__.py`) +: A whole [package](https://docs.python.org/3/tutorial/modules.html#packages) - all imports still working, logging deprecation warnings on first import - ZCML still exists, but is empty (or includes the zcml from the new place if theres no auto import (i.e. for meta.zcml). -Deprecation of a whole python egg +Deprecation of a whole released/ installable package. : We will provide a last major release with no 'real' code, only backward compatible (bbb) imports of public API are provided. This will be done the way described above for a whole package. From 46b14ebd34e3c9777c5e5c0a51a2585a961476c4 Mon Sep 17 00:00:00 2001 From: "Jens W. Klein" Date: Fri, 5 Dec 2025 00:44:16 +0100 Subject: [PATCH 24/28] split deprecation guide into two file according to diataxis principles --- docs/backend/index.md | 1 - docs/conceptual-guides/deprecation.md | 87 +++++++++++++++++ docs/conceptual-guides/index.md | 3 +- .../deprecation.md | 95 ++++--------------- docs/developer-guide/index.md | 1 + 5 files changed, 106 insertions(+), 81 deletions(-) create mode 100644 docs/conceptual-guides/deprecation.md rename docs/{backend => developer-guide}/deprecation.md (64%) diff --git a/docs/backend/index.md b/docs/backend/index.md index 9411e26f70..3e7dd32784 100644 --- a/docs/backend/index.md +++ b/docs/backend/index.md @@ -22,7 +22,6 @@ behaviors configuration-registry content-types/index control-panels -deprecation fields global-utils indexing diff --git a/docs/conceptual-guides/deprecation.md b/docs/conceptual-guides/deprecation.md new file mode 100644 index 0000000000..203d0c21d9 --- /dev/null +++ b/docs/conceptual-guides/deprecation.md @@ -0,0 +1,87 @@ +--- +myst: + html_meta: + "description": "Understanding deprecation in Plone - rationales, philosophy, and use cases." + "property=og:description": "Understanding deprecation in Plone - rationales, philosophy, and use cases." + "property=og:title": "Deprecation" + "keywords": "deprecation, Plone, Python, philosophy" +--- + +(conceptual-deprecation-label)= + +# Deprecation + +This chapter describes rationales and philosophy of deprecations in Plone, Zope, and Python. +It is meant as a guide on how to think about deprecations in Plone core packages. + +```{seealso} +For implementation details and code examples, see {doc}`/developer-guide/deprecation`. +``` + + +## Why deprecation + +At some point we: + +- need to get rid of old code, +- want to unify API style (consistent API), +- fix typos in namings, +- move code or templates around (inside package or to another package). + +While refactoring code, moving modules, functions, classes and methods is often needed. +To not break third party code imports from the old place or usage of old functions/ methods must work for while. +Deprecated methods are usually removed with the next major release of Plone. + +Following the [semantic versioning guideline](https://semver.org) is recommended. + + +## Help programmers, no annoyance + +The developers should use code deprecations to support the consumers of the code. +From their point of view, Plone core code is an API to them. +Any change is annoying to them anyway, but they feel better if deprecation warnings are telling them what to do. + +Deprecations must always log at level *warning* and have to answers the question: + +**"Why is the code gone from the old place? What to do instead?"** + +A short message is enough., i.e.: + +- "Replaced by new API xyz, found at abc.cde"., +- "Moved to xyz, because of abc.", +- "Name had a typo, new name is "xyz". + +All logging has to be done once, i.e. on first usage or first import. +It must not flood the logs. + + +## Use cases + +Renaming + +: We may want to rename classes, methods, functions or global or class variables in order to get a more consistent API or because of a typo, etc. + We never just rename, we always provide a deprecated version logging a verbose deprecation warning with information where to + import from in future. + +Moving a module, class, function, etc to another place + +: For some reason, i.e. merging packages, consistent API or resolving cirular import problems, we need to move code around. + When imported from the old place it logs a verbose deprecation warning with information where to import from in future. + +Deprecation of a whole package + +: A whole [package](https://docs.python.org/3/tutorial/modules.html#packages) + + - all imports still working, logging deprecation warnings on first import + - ZCML still exists, but is empty (or includes the zcml from the new place if theres no auto import (i.e. for meta.zcml). + +Deprecation of a whole released/ installable package. + +: We will provide a last major release with no 'real' code, only backward compatible (bbb) imports of public API are provided. + This will be done the way described above for a whole package. + The README clearly states why it was moved and where to find the code now. + +Deprecation of a GenericSetup profile + +: They may got renamed for consistency or are superfluos after an update. + Code does not need to break to support this. diff --git a/docs/conceptual-guides/index.md b/docs/conceptual-guides/index.md index fb98fce31f..dcd44b630f 100644 --- a/docs/conceptual-guides/index.md +++ b/docs/conceptual-guides/index.md @@ -16,8 +16,9 @@ This part of the documentation provides explanation of concepts to deepen and br :maxdepth: 2 choose-user-interface -compare-buildout-pip distributions +compare-buildout-pip +deprecation package-management package-dependencies make-backend-build diff --git a/docs/backend/deprecation.md b/docs/developer-guide/deprecation.md similarity index 64% rename from docs/backend/deprecation.md rename to docs/developer-guide/deprecation.md index 80a0a98e64..2089ef81f9 100644 --- a/docs/backend/deprecation.md +++ b/docs/developer-guide/deprecation.md @@ -1,88 +1,24 @@ --- myst: html_meta: - "description": "A guide how to do deprecations, including Python, ZCML and templates in Plone." - "property=og:description": "A guide how to do deprecations, including Python, ZCML and templates in Plone." - "property=og:title": "Deprecation" - "keywords": "deprecation, zcml, template, jbot" + "description": "How to implement deprecations in Plone, including Python, ZCML and templates." + "property=og:description": "How to implement deprecations in Plone, including Python, ZCML and templates." + "property=og:title": "Implement deprecations" + "keywords": "deprecation, zcml, template, jbot, Plone, Python" --- -(backend-deprecation-label)= -# Deprecation +(developer-deprecation-label)= -## Introduction +# Implement deprecations -This document describes rationales, configuration and best practices of deprecations in Plone, Zope and Python. -It is meant as a styleguide on how to apply deprecations in Plone core packages. -It also has a value as a general overview on how to deprecate in Python. +This chapter describes how to enable deprecation warnings and best practices for implementing deprecations in Plone, Zope, and Python. +```{seealso} +For background on deprecation philosophy and use cases, see {doc}`/conceptual-guides/deprecation`. +``` -### Why Deprecation - -At some point we: - -- need to get rid of old code, -- want to unify API style (consistent API), -- fix typos in namings, -- move code or templates around (inside package or to another package). - -While refactoring code, moving modules, functions, classes and methods is often needed. -To not break third party code imports from the old place or usage of old functions/ methods must work for while. -Deprecated methods are usually removed with the next major release of Plone. - -Following the [semantic versioning guideline](https://semver.org) is recommended. - -### Help Programmers, No annoyance - -The developers should use code deprecations to support the consumers of the code. -From their point of view, Plone core code is an API to them. -Any change is annoying to them anyway, but they feel better if deprecation warnings are telling them what to do. - -Deprecations must always log at level *warning* and have to answers the question: - -**"Why is the code gone from the old place? What to do instead?"** - -A short message is enough., i.e.: - -- "Replaced by new API xyz, found at abc.cde"., -- "Moved to xyz, because of abc.", -- "Name had a typo, new name is "xyz". - -All logging has to be done once, i.e. on first usage or first import. -It must not flood the logs. - -### Use Cases - -Renaming - -: We may want to rename classes, methods, functions or global or class variables in order to get a more consistent API or because of a typo, etc. - We never just rename, we always provide a deprecated version logging a verbose deprecation warning with information where to - import from in future. - -Moving a module, class, function, etc to another place - -: For some reason, i.e. merging packages, consistent API or resolving cirular import problems, we need to move code around. - When imported from the old place it logs a verbose deprecation warning with information where to import from in future. - -Deprecation of a whole package - -: A whole [package](https://docs.python.org/3/tutorial/modules.html#packages) - - - all imports still working, logging deprecation warnings on first import - - ZCML still exists, but is empty (or includes the zcml from the new place if theres no auto import (i.e. for meta.zcml). - -Deprecation of a whole released/ installable package. - -: We will provide a last major release with no 'real' code, only backward compatible (bbb) imports of public API are provided. - This will be done the way described above for a whole package. - The README clearly states why it was moved and where to find the code now. - -Deprecation of a GenericSetup profile - -: They may got renamed for consistency or are superfluos after an update. - Code does not need to break to support this. -## Enable Deprecation Warnings +## Enable deprecation warnings ### Zope @@ -158,9 +94,10 @@ the call looks like so: ./bin/python -W module ./bin/test ``` -## Deprecation Best Practice -### Vanilla Deprecation Messages +## Deprecation best practice + +### Vanilla deprecation messages Python offers a built-in `DeprecationWarning` which can be issued using standard libraries `warnings` module. @@ -173,7 +110,7 @@ import warnings warnings.warn('deprecated', DeprecationWarning) ``` -### Moving Whole Modules +### Moving whole modules Given a package `old.pkg` with a module `foo.py` need to be moved to a package `new.pkg` as `bar.py`. @@ -192,7 +129,7 @@ Now you can still import the namespace from `bar` at the old place, but get a de > DeprecationWarning: old.pkg.foo has moved to new.pkg.bar. > Import of old.pkg.foo will become unsupported in Version 2.0 -### Moving Whole Packages +### Moving whole packages This is the same as moving a module, just create for each module a file. diff --git a/docs/developer-guide/index.md b/docs/developer-guide/index.md index 940f950079..22eb2c572f 100644 --- a/docs/developer-guide/index.md +++ b/docs/developer-guide/index.md @@ -25,4 +25,5 @@ develop-volto-add-ons-index create-a-distribution standardize-python-project-configuration native-namespace +deprecation ``` From ef525302e4c36e302b969fb9dbf0971a7b748a16 Mon Sep 17 00:00:00 2001 From: "Jens W. Klein" Date: Fri, 5 Dec 2025 12:57:19 +0100 Subject: [PATCH 25/28] Update docs/developer-guide/deprecation.md Co-authored-by: Alessandro Pisa --- docs/developer-guide/deprecation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-guide/deprecation.md b/docs/developer-guide/deprecation.md index 2089ef81f9..acbe27ae47 100644 --- a/docs/developer-guide/deprecation.md +++ b/docs/developer-guide/deprecation.md @@ -231,7 +231,7 @@ jbot_deprecations = { 2. Add this deprecation snippet to the package `configure.zcml` file: ```{code-block} xml -:emphasize-lines: 6,9-12 +:emphasize-lines: 7-14 :linenos: Date: Tue, 9 Dec 2025 04:17:36 -0800 Subject: [PATCH 26/28] - Fix English grammar and syntax - Generalize for npm and Volto - Clean up MyST style and formatting --- docs/conceptual-guides/deprecation.md | 89 +++++++++++++-------------- 1 file changed, 44 insertions(+), 45 deletions(-) diff --git a/docs/conceptual-guides/deprecation.md b/docs/conceptual-guides/deprecation.md index 203d0c21d9..5569758fd9 100644 --- a/docs/conceptual-guides/deprecation.md +++ b/docs/conceptual-guides/deprecation.md @@ -1,87 +1,86 @@ --- myst: html_meta: - "description": "Understanding deprecation in Plone - rationales, philosophy, and use cases." - "property=og:description": "Understanding deprecation in Plone - rationales, philosophy, and use cases." + "description": "Understanding deprecation in Plone - rationale, philosophy, and use cases" + "property=og:description": "Understanding deprecation in Plone - rationale, philosophy, and use cases" "property=og:title": "Deprecation" - "keywords": "deprecation, Plone, Python, philosophy" + "keywords": "deprecation, Plone, Python, Node.js, React, philosophy, rationale, use cases" --- (conceptual-deprecation-label)= # Deprecation -This chapter describes rationales and philosophy of deprecations in Plone, Zope, and Python. -It is meant as a guide on how to think about deprecations in Plone core packages. +This chapter describes the rationale and philosophy of deprecations in Plone. +It is meant as a guide for how to think about deprecations in Plone core packages. ```{seealso} For implementation details and code examples, see {doc}`/developer-guide/deprecation`. ``` +(why-deprecation-label)= + ## Why deprecation -At some point we: +Developers may need to get rid of old code, unify to a consistent API style, fix typos in names, move code or templates around, resolve technical debt, address security issues, or adapt to changes in external dependencies. -- need to get rid of old code, -- want to unify API style (consistent API), -- fix typos in namings, -- move code or templates around (inside package or to another package). +When refactoring code, it's often necessary to move modules, functions, classes, and methods. +It's critical not to break third party code imports from the old place. +It's also important that usage of old functions or methods must work for a while to allow developers to migrate or update their code. -While refactoring code, moving modules, functions, classes and methods is often needed. -To not break third party code imports from the old place or usage of old functions/ methods must work for while. Deprecated methods are usually removed with the next major release of Plone. +Plone follows the [semantic versioning guideline](https://semver.org). -Following the [semantic versioning guideline](https://semver.org) is recommended. +## Help programmers without annoyance -## Help programmers, no annoyance +Developers should use code deprecations to support the consumers of the code, that is, their fellow Plone developers. +From the consumer's point of view, Plone core code is an API. +Any change may annoy them, but they feel better when deprecation warnings tell them how to adapt their code to the changes. -The developers should use code deprecations to support the consumers of the code. -From their point of view, Plone core code is an API to them. -Any change is annoying to them anyway, but they feel better if deprecation warnings are telling them what to do. +Deprecations must always log at the level of warning. -Deprecations must always log at level *warning* and have to answers the question: +Deprecations should always answer the following questions. -**"Why is the code gone from the old place? What to do instead?"** +- Why is the code gone from the old place? +- What to do instead? -A short message is enough., i.e.: +A short message is enough, such as the following examples. -- "Replaced by new API xyz, found at abc.cde"., -- "Moved to xyz, because of abc.", -- "Name had a typo, new name is "xyz". +- "Replaced by new API `xyz`, found at `abc.cde`". +- "Moved to `xyz`, because of `abc`". +- "Name had a typo, new name is `xyz`". -All logging has to be done once, i.e. on first usage or first import. +All logging must be done only once, in other words, on the first usage or import. It must not flood the logs. ## Use cases -Renaming - -: We may want to rename classes, methods, functions or global or class variables in order to get a more consistent API or because of a typo, etc. - We never just rename, we always provide a deprecated version logging a verbose deprecation warning with information where to - import from in future. - -Moving a module, class, function, etc to another place +The following use cases describe when to deprecate. -: For some reason, i.e. merging packages, consistent API or resolving cirular import problems, we need to move code around. - When imported from the old place it logs a verbose deprecation warning with information where to import from in future. +Rename +: Developers may want to rename classes, methods, functions, or global or class variables to get a more consistent API or because of a typo. + Never just rename. + Always provide a deprecated version that logs a verbose deprecation warning with information for where to import from in the future. -Deprecation of a whole package +Move objects +: For reasons described in {ref}`why-deprecation-label`, developers may need to move code around. + When imported from the old place, it logs a verbose deprecation warning with information of where to import from in the future. -: A whole [package](https://docs.python.org/3/tutorial/modules.html#packages) +Deprecation of a whole Python or npm package +: A whole {ref}`Python package ` or [npm package](https://www.npmjs.com/) may be moved to a new location. - - all imports still working, logging deprecation warnings on first import - - ZCML still exists, but is empty (or includes the zcml from the new place if theres no auto import (i.e. for meta.zcml). + - All imports still work. + - Log deprecation warnings on first import. + - The ZCML still exists, but is empty or includes the ZCML from the new place, if there's no auto import for `meta.zcml`. -Deprecation of a whole released/ installable package. - -: We will provide a last major release with no 'real' code, only backward compatible (bbb) imports of public API are provided. - This will be done the way described above for a whole package. - The README clearly states why it was moved and where to find the code now. +Deprecation of a whole released or installable package +: Plone developers provide a major release with no "real" code, but only backward compatible imports of the public API. + This will be done the way described above for a whole package. + The README clearly states why it was moved and where to find the code now. Deprecation of a GenericSetup profile - -: They may got renamed for consistency or are superfluos after an update. - Code does not need to break to support this. +: These may have been renamed for consistency or are superfluous after an update. + Code does not need to break to support this. From 78165e0509f5c025ee5dd98dc2a60e82d586dc0c Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Fri, 12 Dec 2025 23:23:14 -0800 Subject: [PATCH 27/28] Refine some grammar --- docs/conceptual-guides/deprecation.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/conceptual-guides/deprecation.md b/docs/conceptual-guides/deprecation.md index 5569758fd9..7c181b2554 100644 --- a/docs/conceptual-guides/deprecation.md +++ b/docs/conceptual-guides/deprecation.md @@ -18,8 +18,8 @@ It is meant as a guide for how to think about deprecations in Plone core package For implementation details and code examples, see {doc}`/developer-guide/deprecation`. ``` -(why-deprecation-label)= +(why-deprecation-label)= ## Why deprecation @@ -44,7 +44,7 @@ Deprecations must always log at the level of warning. Deprecations should always answer the following questions. - Why is the code gone from the old place? -- What to do instead? +- What should the developer do instead? A short message is enough, such as the following examples. @@ -62,7 +62,7 @@ The following use cases describe when to deprecate. Rename : Developers may want to rename classes, methods, functions, or global or class variables to get a more consistent API or because of a typo. - Never just rename. + Renaming alone is not enough to deprecate code. Always provide a deprecated version that logs a verbose deprecation warning with information for where to import from in the future. Move objects @@ -78,8 +78,8 @@ Deprecation of a whole Python or npm package Deprecation of a whole released or installable package : Plone developers provide a major release with no "real" code, but only backward compatible imports of the public API. - This will be done the way described above for a whole package. - The README clearly states why it was moved and where to find the code now. + This should be done the way described above for a whole package. + The README should clearly state why it was moved and where to find the code now. Deprecation of a GenericSetup profile : These may have been renamed for consistency or are superfluous after an update. From a1e40f45ea8733845bdcdb48a2ac32c213a1f59d Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sun, 14 Dec 2025 04:06:08 -0800 Subject: [PATCH 28/28] - Add MyST syntax to link to Python objects, improve rendering - Clean up grammar, MyST syntax - Indent code within list items. - Use ruff style code example formatting. --- docs/developer-guide/deprecation.md | 236 ++++++++++++++-------------- 1 file changed, 122 insertions(+), 114 deletions(-) diff --git a/docs/developer-guide/deprecation.md b/docs/developer-guide/deprecation.md index acbe27ae47..0296ded169 100644 --- a/docs/developer-guide/deprecation.md +++ b/docs/developer-guide/deprecation.md @@ -9,9 +9,9 @@ myst: (developer-deprecation-label)= -# Implement deprecations +# Deprecate code -This chapter describes how to enable deprecation warnings and best practices for implementing deprecations in Plone, Zope, and Python. +This chapter describes how to enable deprecation warnings and best practices for deprecating code in Plone, Zope, and Python. ```{seealso} For background on deprecation philosophy and use cases, see {doc}`/conceptual-guides/deprecation`. @@ -20,146 +20,154 @@ For background on deprecation philosophy and use cases, see {doc}`/conceptual-gu ## Enable deprecation warnings +This section describes how to enable deprecation warnings in Zope, Python, and tests. + + ### Zope -Zope does configure logging and warnings, so the steps below (under section Python) are not needed. +Zope configures logging and warnings, so the steps as described below in {ref}`deprecation-warning-python-label` aren't needed. -Using `plone.recipe.zope2instance` add the option `deprecation-warnings = on` to the buildouts `[instance]` section. +Using `plone.recipe.zope2instance`, add the option `deprecation-warnings = on` to the buildout's `[instance]` section. -```ini +```cfg [buildout] parts = instance [instance] recipe = plone.recipe.zope2instance -... +# … deprecation-warnings = on -... +# … ``` -This adds this line to the `zope.conf` file: +This adds the following line to the {file}`zope.conf` file. -``` +```cfg debug-mode on ``` -Without the recipe this can be set manually as well: -In `zope.conf` custom filters for warnings can be defined. +Without the recipe, this can be set manually as well. +In {file}`zope.conf`, define custom filters for warnings, such as the following example. ```xml -... action always category exceptions.DeprecationWarning -... ``` -### Python -Enable Warnings +(deprecation-warning-python-label)= -: Warnings are written to `stderr` by default, but `DeprecationWarning` output is surpressed by default. - - Output can be enabled by starting the Python interpreter with the [-W \[all|module|once\]](https://docs.python.org/3/using/cmdline.html#cmdoption-W) option. +### Python - It is possible to enable output in code too: +Enable warnings - ```python - import warnings - warnings.simplefilter("module") - ``` +: Warnings are written to `stderr` by default, but `DeprecationWarning` output is surpressed by default. + + Output can be enabled by starting the Python interpreter with the {ref}`-W[all|module|once] ` argument. + + It's possible to enable output in code, too. + + ```python + import warnings + warnings.simplefilter("module") + ``` -Configure Logging +Configure logging -: Once output is enabled it is possible to [redirect warnings to the logger](https://docs.python.org/3/library/logging.html#logging.captureWarnings): +: Once output is enabled, it's possible to use {func}`python:logging.captureWarnings` to redirect warnings to the logger. - ```python - import logging - logging.captureWarnings(True) - ``` + ```python + import logging + logging.captureWarnings(True) + ``` ### Running tests -In Plone tests deprecation warnings are not shown by default. -The `zope.conf` setting is not taken into account. +In Plone, test deprecation warnings are not shown by default. +The {file}`zope.conf` setting is not taken into account. -In order to enable deprecation warnings, -the Python way with the `-W` command option must to be used. +To enable deprecation warnings, use the `-W` command. -Given youre using a modern buildout with virtualenv as recommended, -the call looks like so: +Given you're using a modern buildout with a virtual environment as recommended, the command would be the following -```bash +```shell ./bin/python -W module ./bin/test ``` -## Deprecation best practice +## Deprecation best practices -### Vanilla deprecation messages +It's recommended to follow these best practices when deprecating code. -Python offers a built-in `DeprecationWarning` which can be issued using standard libraries `warnings` module. -For details read the [official documentation about warnings](https://docs.python.org/3/library/warnings.html). +### Vanilla deprecation messages + +Python offers a built-in exception {exc}`DeprecationWarning` which can be issued using the standard library's {mod}`warnings` module. -In short it works like so +Its basic usage is the following example. ```python import warnings -warnings.warn('deprecated', DeprecationWarning) +warnings.warn("deprecated", DeprecationWarning) ``` -### Moving whole modules -Given a package `old.pkg` with a module `foo.py` need to be moved to a package `new.pkg` as `bar.py`. +### Move an entire module -[zope.deprecation Moving modules](https://zopedeprecation.readthedocs.io/en/latest/api.html#moving-modules) offers a helper. +Given a package {file}`old.pkg` with a module {file}`foo.py`, to move it to a package {file}`new.pkg` as {file}`bar.py`, go through the following steps. -1. Move the `foo.py` as `bar.py` to the `new.pkg`. -2. At the old place create a new `foo.py` and add to it +[`zope.deprecation` Moving modules](https://zopedeprecation.readthedocs.io/en/latest/api.html#moving-modules) offers a helper. -```python -from zope.deprecation import moved -moved('new.pkg.bar', 'Version 2.0') -``` +1. Move the {file}`foo.py` as {file}`bar.py` to the {file}`new.pkg`. +1. At the old place, create a new {file}`foo.py`, and add to it the following lines of code. + + ```python + from zope.deprecation import moved + moved("new.pkg.bar", "Version 2.0") + ``` + +1. Now you can still import the namespace from `bar` at the old place, but get a deprecation warning. + + ```console + DeprecationWarning: old.pkg.foo has moved to new.pkg.bar. + Import of old.pkg.foo will become unsupported in Version 2.0 + ``` -Now you can still import the namespace from `bar` at the old place, but get a deprecation warning: -> DeprecationWarning: old.pkg.foo has moved to new.pkg.bar. -> Import of old.pkg.foo will become unsupported in Version 2.0 +### Move an entire package -### Moving whole packages +To move an entire package, the process is exactly the same as moving a module, but instead, create a file for each module in the package. -This is the same as moving a module, just create for each module a file. -### Deprecating methods and properties +### Deprecate methods and properties -You can use the `@deprecate` decorator from [zope.deprecation Deprecating methods and properties](https://zopedeprecation.readthedocs.io/en/latest/api.html#deprecating-methods-and-properties) to deprecate methods in a module: +Use the `@deprecate` decorator from [`zope.deprecation` Deprecating methods and properties](https://zopedeprecation.readthedocs.io/en/latest/api.html#deprecating-methods-and-properties) to deprecate methods in a module. ```python from zope.deprecation import deprecate -@deprecate('Old method is no longer supported, use new_method instead.') +@deprecate("Old method is no longer supported, use new_method instead.") def old_method(): - return 'some value' + return "some value" ``` -The `deprecated` wrapper method is for deprecating properties: +The `@deprecated` wrapper method deprecates properties. ```python from zope.deprecation import deprecated foo = None -foo = deprecated(foo, 'foo is no more, use bar instead') +foo = deprecated(foo, "foo is no more, use bar instead") ``` -### Moving functions and classes -Given we have a Python file at `old/foo/bar.py` and want to move some classes or functions to `new/baz/baaz.py`. +### Move functions and classes -Here `zope.deferredimport` offers a deprecation helper. -It also avoids circular imports on initialization time. +This example describes how to move some classes or functions from a Python file at {file}`old/foo/bar.py` to {file}`new/baz/baaz.py`. +Here, `zope.deferredimport` offers a deprecation helper. +It also avoids circular imports at initialization time. ```python import zope.deferredimport @@ -167,25 +175,25 @@ zope.deferredimport.initialize() zope.deferredimport.deprecated( "Import from new.baz.baaz instead", - SomeOldClass='new.baz:baaz.SomeMovedClass', - some_old_function='new.baz:baaz.some_moved_function', + SomeOldClass="new.baz:baaz.SomeMovedClass", + some_old_function="new.baz:baaz.some_moved_function", ) def some_function_which_is_not_touched_at_all(): pass ``` -### Deprecating a GenericSetup profile +### Deprecate a GenericSetup profile -Starting with GenericSetup 1.8.2 (part of Plone > 5.0.2) the `post_handler` attribute in ZCML can be used to call a function after the profile was applied. -We use this feature to issue a warning. +In GenericSetup, the `post_handler` attribute in ZCML can be used to call a function after the profile was applied. +Use this feature to issue a warning. -First we register the same profile twice. Under the new name and under the old name: +First, register the same profile twice, under both the new name and old. ```xml ``` -And in `setuphandlers.py` add a function: +Then in {file}`setuphandlers.py`, add a function. ```python import warnings @@ -213,43 +221,43 @@ def deprecate_profile_some_confusing_name(tool): ) ``` -### Deprecating a template position - -Sometimes we need to move templates to new locations. Since addons often use [z3c.jbot](https://github.com/zopefoundation/z3c.jbot) to override templates by their position, we need to point them to the new position as well as make sure that the override still works with the old position. - - -To deprecate a package: - -1. In the old package folders `__init__.py` add a dictionary `jbot_deprecations` that maps the old template locations to their new counterparts, e.g.: - -```python -jbot_deprecations = { - "plone.locking.browser.info.pt": "plone.app.layout.viewlets.info.pt" -} -``` - -2. Add this deprecation snippet to the package `configure.zcml` file: - -```{code-block} xml -:emphasize-lines: 7-14 -:linenos: - - - - - - - -``` +### Deprecate a template position + +Sometimes you need to move templates to new locations. +Since add-ons often use [`z3c.jbot`](https://github.com/zopefoundation/z3c.jbot) to override templates by their position, you'll need to point them to the new position as well as make sure that the override still works with the old position. + +To deprecate a package, follow these steps. + +1. In the old package folder's {file}`__init__.py`, add a dictionary `jbot_deprecations` that maps the old template locations to their new counterparts. + + ```python + jbot_deprecations = { + "plone.locking.browser.info.pt": "plone.app.layout.viewlets.info.pt" + } + ``` + +1. Add this deprecation snippet to the package {file}`configure.zcml` file. + + ```{code-block} xml + :emphasize-lines: 7-14 + :linenos: + + + + + + + + ``` If a `z3c.jbot` version that supports deprecation is found, trying to override the template with the old location will trigger a deprecation warning that will instruct the user to rename its override file.