[FLINK-40529][python] Warn on use of deprecated APIs, not at import time - #29061
Draft
deepyaman wants to merge 1 commit into
Draft
[FLINK-40529][python] Warn on use of deprecated APIs, not at import time#29061deepyaman wants to merge 1 commit into
deepyaman wants to merge 1 commit into
Conversation
Deprecated emitted its DeprecationWarning from __call__, which the decorator syntax invokes in order to apply the decorator. The warning therefore fired at decoration time -- that is, at import -- for every deprecated API a module defines, whether or not the user touches it, while actually calling one emitted nothing, and stacklevel=2 pointed at the decoration site inside PyFlink's own source rather than at user code. Functions now get a functools.wraps wrapper that warns when called. Classes are returned unchanged, with __init__ wrapped in place so that isinstance checks and subclassing keep working; as in PEP 702, only instantiating the deprecated class itself warns, which also avoids warning twice when a deprecated class inherits the __init__ of a deprecated base class. staticmethod and classmethod objects are unwrapped and re-packaged, and properties, ABCs and Enum subclasses degrade to the docstring directive rather than raising -- decorating any of these used to fail. A missing detail argument no longer raises either. The message format, the DeprecationWarning category, the docstring directives and the __stability_decorators attribute read by PythonAPICompletenessTestCase are unchanged, and Experimental, Internal, Public and PublicEvolving are unaffected. pyflink/util was not in the list of modules that dev/integration_test.sh runs, so it is added there for the new tests to run in CI. Generated-by: Claude Code 2.1.252 (Claude Opus 5)
Collaborator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What is the purpose of the change
Deprecatedinflink-python/pyflink/util/api_stability_decorators.pyemitted itsDeprecationWarningfrom__call__, which the decorator syntax invokes in order to apply the decorator. The warning therefore fired at decoration time — that is, at import — and the decorated function/class was returned unwrapped, so:pyflink.tableemitted aDeprecationWarningfor every deprecated API it defines, whether or not the user touches them;stacklevel=2pointed at the decoration site inside PyFlink's own source, not at user code.FLINK-37365, which introduced these decorators, describes the intended behaviour as warning "at runtime on their invocation", so this was an oversight. PyFlink supports Python >= 3.9, so
warnings.deprecated(PEP 702) is not available; the fix is by hand, mirroring PEP 702's semantics where reasonable.Brief change log
Deprecatedapplied to a function returns afunctools.wrapswrapper that warns when the function is called, withstacklevel=2so the warning is attributed to the caller.Deprecatedapplied to a class returns the class itself and wraps__init__on it, soisinstancechecks and subclassing are unaffected. As in PEP 702 only instantiating the deprecated class itself warns, which also avoids warning twice when a deprecated class inherits the__init__of a deprecated base class.staticmethod/classmethodobjects are unwrapped, decorated and re-packaged; properties, ABCs andEnumsubclasses fall back to applying the docstring directive alone rather than raising. Decorating any of these previously failed, as did omitting thedetailargument.DeprecationWarningcategory, the docstring/Sphinx directives and the__stability_decoratorsattribute read byPythonAPICompletenessTestCaseare unchanged;Experimental,Internal,PublicandPublicEvolvingare untouched.pyflink/utilwas not among the modulesdev/integration_test.shruns, so it is added there.Verifying this change
This change added tests and can be verified as follows:
pyflink/util/tests/test_api_stability_decorators.py: no warning at decoration; a regression test that importspyflink.tablein a fresh interpreter and asserts no deprecation warning is emitted; warning on function call and on class instantiation; the warning is attributed to the caller's file and line; docstring directives still applied;__stability_decoratorsstill populated;staticmethod/classmethod/property/ABC/Enumcases; subclassing and double-warning guards; the other four decorators still silent and still returning their argument unchanged.python -W error::DeprecationWarning -c "import pyflink.table"no longer raises, and that callingTable.get_schemawarns exactly once, pointing at the calling script.flake8andmypyas configured inflink-python/tox.iniare clean, and the Sphinx docs build (SPHINXOPTS="-a -W" make html) still succeeds, withDeprecated since version 2.1.0still rendered on the affected APIs.Does this pull request potentially affect one of the following parts:
@Public(Evolving): noDocumentation
Was generative AI tooling used to co-author this PR?
Generated-by: Claude Code 2.1.252 (Claude Opus 5)