o bl @sdZgdZddlZddlZddlmZddlmZddlm Z ddl m Z m Z m Z mZmZmZddlmamZdd lmZmZd Zd d Zd e_de_de_ddZdaa Deprecation framework for Twisted. To mark a method, function, or class as being deprecated do this:: from incremental import Version from twisted.python.deprecate import deprecated @deprecated(Version("Twisted", 8, 0, 0)) def badAPI(self, first, second): ''' Docstring for badAPI. ''' ... @deprecated(Version("Twisted", 16, 0, 0)) class BadClass: ''' Docstring for BadClass. ''' The newly-decorated badAPI will issue a warning when called, and BadClass will issue a warning when instantiated. Both will also have a deprecation notice appended to their docstring. To deprecate properties you can use:: from incremental import Version from twisted.python.deprecate import deprecatedProperty class OtherwiseUndeprecatedClass: @deprecatedProperty(Version('Twisted', 16, 0, 0)) def badProperty(self): ''' Docstring for badProperty. ''' @badProperty.setter def badProperty(self, value): ''' Setter sill also raise the deprecation warning. ''' To mark module-level attributes as being deprecated you can use:: badAttribute = "someValue" ... deprecatedModuleAttribute( Version("Twisted", 8, 0, 0), "Use goodAttribute instead.", "your.full.module.name", "badAttribute") The deprecated attributes will issue a warning whenever they are accessed. If the attributes being deprecated are in the same module as the L{deprecatedModuleAttribute} call is being made from, the C{__name__} global can be used as the C{moduleName} parameter. To mark an optional, keyword parameter of a function or method as deprecated without deprecating the function itself, you can use:: @deprecatedKeywordParameter(Version("Twisted", 19, 2, 0), 'baz') def someFunction(foo, bar=0, baz=None): ... See also L{incremental.Version}. @type DEPRECATION_WARNING_FORMAT: C{str} @var DEPRECATION_WARNING_FORMAT: The default deprecation warning string format to use when one is not provided by the user. ) deprecateddeprecatedPropertygetDeprecationWarningStringgetWarningMethodsetWarningMethoddeprecatedModuleAttributedeprecatedKeywordParameterN)findlinestartswraps) ModuleType)AnyCallableDictOptionalTypeVarcast)warn warn_explicit)VersiongetVersionStringz&%(fqpn)s was deprecated in %(version)scCslz|j}Wn ty|j}Ynwt|st|r&|j}|d|St|r4|jd|jS|S)z Return the fully qualified name of a module, class, method or function. Classes and functions need to be module level ones to be correctly qualified. @rtype: C{str}. .) __qualname__AttributeError__name__inspectisclass isfunction __module__ismethod)objname moduleNamer#:/usr/lib/python3/dist-packages/twisted/python/deprecate.py_fullyQualifiedNameos    r%ztwisted.python.reflectfullyQualifiedNamecCst|rt|}d|dS)a  Surround a replacement for a deprecated API with some polite text exhorting the user to consider it as an alternative. @type replacement: C{str} or callable @return: a string like "please use twisted.python.modules.getModule instead". z please use z instead)callabler% replacementr#r#r$_getReplacementStrings  r*cCs,dt|}|r|dt|}|dS)a Generate an addition to a deprecated object's docstring that explains its deprecation. @param version: the version it was deprecated. @type version: L{incremental.Version} @param replacement: The replacement, if specified. @type replacement: C{str} or callable @return: a string like "Deprecated in Twisted 27.2.0; please use twisted.timestream.tachyon.flux instead." zDeprecated in ; r)rr*)versionr)docr#r#r$_getDeprecationDocstringsr.cCs6|durt}||t|d}|rd|t|}|S)ag Return a string indicating that the Python name was deprecated in the given version. @param fqpn: Fully qualified Python name of the thing being deprecated @type fqpn: C{str} @param version: Version that C{fqpn} was deprecated in. @type version: L{incremental.Version} @param format: A user-provided format to interpolate warning values into, or L{DEPRECATION_WARNING_FORMAT } if L{None} is given. @type format: C{str} @param replacement: what should be used in place of C{fqpn}. Either pass in a string, which will be inserted into the warning message, or a callable, which will be expanded to its full import path. @type replacement: C{str} or callable @return: A textual description of the deprecation @rtype: C{str} N)fqpnr,z{}; {})DEPRECATION_WARNING_FORMATrformatr*)r/r,r1r) warningStringr#r#r$_getDeprecationWarningStringsr3cCstt||||S)ak Return a string indicating that the callable was deprecated in the given version. @type callableThing: C{callable} @param callableThing: Callable object to be deprecated @type version: L{incremental.Version} @param version: Version that C{callableThing} was deprecated in. @type format: C{str} @param format: A user-provided format to interpolate warning values into, or L{DEPRECATION_WARNING_FORMAT } if L{None} is given @param replacement: what should be used in place of the callable. Either pass in a string, which will be inserted into the warning message, or a callable, which will be expanded to its full import path. @type replacement: C{str} or callable @return: A string describing the deprecation. @rtype: C{str} )r3r%) callableThingr,r1r)r#r#r$rs rcCsx|jr |j}ng}t|dkr||nt|dkr&|d|dgn|}|d|||gd||_dS)av Append the given text to the docstring of C{thingWithDoc}. If C{thingWithDoc} has no docstring, then the text just replaces the docstring. If it has a single-line docstring then it appends a blank line and the message text. If it has a multi-line docstring, then in appends a blank line a the message text, and also does the indentation correctly. r N)__doc__ splitlineslenappendextendpopjoin) thingWithDoc textToAppenddocstringLinesspacesr#r#r$_appendToDocstrings    rCcsfdd}|S)a Return a decorator that marks callables as deprecated. To deprecate a property, see L{deprecatedProperty}. @type version: L{incremental.Version} @param version: The version in which the callable will be marked as having been deprecated. The decorated function will be annotated with this version, having it set as its C{deprecatedVersion} attribute. @param replacement: what should be used in place of the callable. Either pass in a string, which will be inserted into the warning message, or a callable, which will be expanded to its full import path. @type replacement: C{str} or callable cs>tdtfdd}t|t|_|S)zA Decorator that marks C{function} as deprecated. Ncttdd|i|SN stacklevelrDeprecationWarningargskwargsfunctionr2r#r$deprecatedFunctionzDdeprecated..deprecationDecorator..deprecatedFunction)rr rCr.deprecatedVersion)rOrPr)r,rNr$deprecationDecorators z(deprecated..deprecationDecoratorr#r,r)rTr#rSr$rsrcs$Gdddtfdd}|S)a Return a decorator that marks a property as deprecated. To deprecate a regular callable or class, see L{deprecated}. @type version: L{incremental.Version} @param version: The version in which the callable will be marked as having been deprecated. The decorated function will be annotated with this version, having it set as its C{deprecatedVersion} attribute. @param replacement: what should be used in place of the callable. Either pass in a string, which will be inserted into the warning message, or a callable, which will be expanded to its full import path. @type replacement: C{str} or callable @return: A new property with deprecated setter and getter. @rtype: C{property} @since: 16.1.0 c@ eZdZdZddZddZdS)z/deprecatedProperty.._DeprecatedPropertyzQ Extension of the build-in property to allow deprecated setters. cstfdd}|S)Ncstjtdd|i|SrE)rr2rJrKrOselfr#r$rPJs z^deprecatedProperty.._DeprecatedProperty._deprecatedWrapper..deprecatedFunctionr )rXrOrPr#rWr$_deprecatedWrapperIszBdeprecatedProperty.._DeprecatedProperty._deprecatedWrappercSst|||SN)propertysetterrY)rXrOr#r#r$r\Uz6deprecatedProperty.._DeprecatedProperty.setterN)rrrr8rYr\r#r#r#r$_DeprecatedPropertyDs r^csLtdtfdd}t|t|_|}|_|S)NcrDrErIrKrNr#r$rP]rQzLdeprecatedProperty..deprecationDecorator..deprecatedFunction)rr rCr.rRr2)rOrPresultr^r)r,rNr$rTXs z0deprecatedProperty..deprecationDecorator)r[rUr#r`r$r-srcCstS)zR Return the warning method currently used to record deprecation warnings. rr#r#r#r$rnsrcCs|adS)z Set the warning method to use to record deprecation warnings. The callable should take message, category and stacklevel. The return value is ignored. Nra) newMethodr#r#r$rusrc@s(eZdZdZddZddZddZdS) _InternalStatez An L{_InternalState} is a helper object for a L{_ModuleProxy}, so that it can easily access its own attributes, bypassing its logic for delegating to another object that it's proxying for. @ivar proxy: a L{_ModuleProxy} cCst|d|dSNproxy)object __setattr__)rXrer#r#r$__init__r]z_InternalState.__init__cCstt|d|Srd)rf__getattribute__)rXr!r#r#r$risz_InternalState.__getattribute__cCstt|d||Srd)rfrgri)rXr!valuer#r#r$rgsz_InternalState.__setattr__N)rrrr8rhrirgr#r#r#r$rcs  rcc@s6eZdZdZddZdefddZddZd d Zd S) _ModuleProxya Python module wrapper to hook module-level attribute access. Access to deprecated attributes first checks L{_ModuleProxy._deprecatedAttributes}, if the attribute does not appear there then access falls through to L{_ModuleProxy._module}, the wrapped module object. @ivar _module: Module on which to hook attribute access. @type _module: C{module} @ivar _deprecatedAttributes: Mapping of attribute names to objects that retrieve the module attribute's original value. @type _deprecatedAttributes: C{dict} mapping C{str} to L{_DeprecatedAttribute} @ivar _lastWasPath: Heuristic guess as to whether warnings about this package should be ignored for the next call. If the last attribute access of this module was a C{getattr} of C{__path__}, we will assume that it was the import system doing it and we won't emit a warning for the next access, even if it is to a deprecated attribute. The CPython import system always tries to access C{__path__}, then the attribute itself, then the attribute itself again, in both successful and failed cases. @type _lastWasPath: C{bool} cCst|}||_i|_d|_dS)NF)rc_module_deprecatedAttributes _lastWasPath)rXmodulestater#r#r$rhs z_ModuleProxy.__init__returncCs"t|}dt|jd|jdS)z Get a string containing the type of the module proxy and a representation of the wrapped module object. )rctyperrl)rXrpr#r#r$__repr__sz_ModuleProxy.__repr__cCs t|}d|_t|j||dS)z@ Set an attribute on the wrapped module object. FN)rcrnsetattrrl)rXr!rjrpr#r#r$rgsz_ModuleProxy.__setattr__cCsZt|}|jr d}n|j|}|dur|}nt|j|}|dkr(d|_|Sd|_|S)aG Get an attribute from the module object, possibly emitting a warning. If the specified name has been deprecated, then a warning is issued. (Unless certain obscure conditions are met; see L{_ModuleProxy._lastWasPath} for more information about what might quash such a warning.) N__path__TF)rcrnrmgetgetattrrl)rXr!rpdeprecatedAttributerjr#r#r$ris    z_ModuleProxy.__getattribute__N) rrrr8rhstrrurgrir#r#r#r$rks  rkc@rV)_DeprecatedAttributeaE Wrapper for deprecated attributes. This is intended to be used by L{_ModuleProxy}. Calling L{_DeprecatedAttribute.get} will issue a warning and retrieve the underlying attribute's value. @type module: C{module} @ivar module: The original module instance containing this attribute @type fqpn: C{str} @ivar fqpn: Fully qualified Python name for the deprecated attribute @type version: L{incremental.Version} @ivar version: Version that the attribute was deprecated in @type message: C{str} @ivar message: Deprecation message cCs,||_||_|jd||_||_||_dS)z7 Initialise a deprecated name wrapper. rN)rorr/r,message)rXror!r,r}r#r#r$rhs  z_DeprecatedAttribute.__init__cCs:t|j|j}t|j|jtd|j}t|t dd|S)zU Get the underlying attribute value and issue a deprecation warning. z: rG) ryrorr3r/r,r0r}rrJ)rXr_r}r#r#r$rxs z_DeprecatedAttribute.getN)rrrr8rhrxr#r#r#r$r|s r|cCs2t|d}t||||}t|d}|||<dS)a Mark a module-level attribute as being deprecated. @type proxy: L{_ModuleProxy} @param proxy: The module proxy instance proxying the deprecated attributes @type name: C{str} @param name: Attribute name @type version: L{incremental.Version} @param version: Version that the attribute was deprecated in @type message: C{str} @param message: Deprecation message rlrmN)rfrir|)rer!r,r}rlattrrmr#r#r$_deprecateAttributes   rcCs>tj|}t|tsttt|}|tj|<t||||dS)aE Declare a module-level attribute as being deprecated. @type version: L{incremental.Version} @param version: Version that the attribute was deprecated in @type message: C{str} @param message: Deprecation message @type moduleName: C{str} @param moduleName: Fully-qualified Python name of the module containing the deprecated attribute; if called from the same module as the attributes are being deprecated in, using the C{__name__} global can be helpful @type name: C{str} @param name: Attribute name to deprecate N)sysmodules isinstancerkrr r)r,r}r"r!ror#r#r$r*s   rc CsLtj|j}t|tt|tddt|j D|j |j didddS)a Issue a warning string, identifying C{offender} as the responsible code. This function is used to deprecate some behavior of a function. It differs from L{warnings.warn} in that it is not limited to deprecating the behavior of a function currently on the call stack. @param offender: The function that is being deprecated. @param warningString: The string that should be emitted by this warning. @type warningString: C{str} @since: 11.0 css|]\}}|VqdSrZr#).0_ lineNumberr#r#r$ [sz$warnAboutFunction..__warningregistry__N)categoryfilenamelinenororegistrymodule_globals) rrrrrJr getabsfilemaxr __code__r __globals__ setdefault)offenderr2offenderModuler#r#r$warnAboutFunctionEs   rcCsi}t|jt|}|jduri}||j<|dkr0|jdur$td|t|jd||j<t|j|D]\}}|||<q6|D]#\}}||jvrY||vrTtd|||<qC|jdurc|||<qCtd|S)a Take an I{inspect.ArgSpec}, a tuple of positional arguments, and a dict of keyword arguments, and return a mapping of arguments that were actually passed to their passed values. @param argspec: The argument specification for the function to inspect. @type argspec: I{inspect.ArgSpec} @param positional: The positional arguments that were passed. @type positional: L{tuple} @param keyword: The keyword arguments that were passed. @type keyword: L{dict} @return: A dictionary mapping argument names (those declared in C{argspec}) to values that were passed explicitly by the user. @rtype: L{dict} mapping L{str} to L{object} NrToo many arguments.Already passed. no such param)r:rLkeywordsvarargs TypeErrorzipitems)argspec positionalkeywordr_unpassedrMr!rjr#r#r$_passedArgSpecbs&       rc Cshi}d}d}t|jD]q\}\}}|jtjjkr+||d||<t||d}q |jtjjkr9i}||<q |jtjj tjj fvrU|t|krT||||<|d7}q |jtjj krt||vrs|j tjj krntd||j ||<q td|d|jt||krtd|D]$\}} ||jvr||vrtd| ||<q|dur| ||<qtd |S) a Take an L{inspect.Signature}, a tuple of positional arguments, and a dict of keyword arguments, and return a mapping of arguments that were actually passed to their passed values. @param signature: The signature of the function to inspect. @type signature: L{inspect.Signature} @param positional: The positional arguments that were passed. @type positional: L{tuple} @param keyword: The keyword arguments that were passed. @type keyword: L{dict} @return: A dictionary mapping argument names (those declared in C{signature}) to values that were passed explicitly by the user. @rtype: L{dict} mapping L{str} to L{object} Nrr5zmissing keyword arg 'z' parameter is invalid kind: rrr) enumerate parametersrkindr ParameterVAR_POSITIONALr: VAR_KEYWORDPOSITIONAL_OR_KEYWORDPOSITIONAL_ONLY KEYWORD_ONLYdefaultemptyrkeys) signaturerrr_rM numPositionalnr!paramrjr#r#r$_passedSignaturesF      rcsfdd}|S)a Decorator which causes its decoratee to raise a L{TypeError} if two of the given arguments are passed at the same time. @param argumentPairs: pairs of argument identifiers, each pair indicating an argument that may not be passed in conjunction with another. @type argumentPairs: sequence of 2-sequences of L{str} @return: A decorator, used like so:: @_mutuallyExclusiveArguments([["tweedledum", "tweedledee"]]) def function(tweedledum=1, tweedledee=2): "Don't pass tweedledum and tweedledee at the same time." @rtype: 1-argument callable taking a callable and returning a callable. cs,tttfdd}|S)NcsN||}D]\}}||vr||vrtd||tfq|i|S)Nz5The %r and %r arguments to %s are mutually exclusive.)rr%)rLrM argumentsthisthat)_passed argumentPairsspecwrappeer#r$wrappeds   z=_mutuallyExclusiveArguments..wrapper..wrapped)rrrr )rrr)rrrr$wrappers  z,_mutuallyExclusiveArguments..wrapperr#)rrr#rr$_mutuallyExclusiveArgumentss r_Tc.)boundr,r!r)rqcsdtdtffdd }|S)aw Return a decorator that marks a keyword parameter of a callable as deprecated. A warning will be emitted if a caller supplies a value for the parameter, whether the caller uses a keyword or positional syntax. @type version: L{incremental.Version} @param version: The version in which the parameter will be marked as having been deprecated. @type name: L{str} @param name: The name of the deprecated parameter. @type replacement: L{str} @param replacement: Optional text indicating what should be used in place of the deprecated parameter. @since: Twisted 21.2.0 rrqcstddtddt}r!|dt}|d7}tj}|vrI|jtj j krIt | fdd}nfd d}t tt|}t|||S) NzThe z parameter to r(z'The {!r} parameter was deprecated in {}r+rcs0t|ks |vrttdd|i|SrE)r:rrJrK)r!parameterIndexr2rr#r$checkDeprecatedParameterszMdeprecatedKeywordParameter..wrapper..checkDeprecatedParametercs$|vr ttdd|i|SrErIrK)r!r2rr#r$r%s)r3r%r1rr*rrrrrrlistindexrrr rC)rr-paramsr decoratedr!r)r,)rr2rr$rs*  z+deprecatedKeywordParameter..wrapper)r)r,r!r)rr#rr$rs&rrZ)NN)1r8__all__rrdisr functoolsr typesr typingr rrrrrwarningsrr incrementalrrr0r%rrrr*r.r3rrCrrrrrcrkr|rrrrrrrr{rr#r#r#r$sXN        #  'A P/*<&