Skip to content

Replace sage_wraps by decorator library #30884

@tobiasdiez

Description

@tobiasdiez

Replace the sage custom sage_wrap and decorator_defaults methods by the well-maintained decorator library https://github.com/micheles/decorator.

My motivation is to replace sage's autodoc sphinx extension with the built-in one. For this, the Phyton introspection code needs to work without sage's customization. This ticket is a first step towards this goal. But independently of this motivation the approach using decorator library already provides cleaner code and better introspection results with respect to annotations (e.g. typing information). See the following test script for a comparison:

import inspect
from pathlib import Path
from sage.misc.decorators import decorator_keywords, sage_wraps
from decorator import decorator, getfullargspec
from sage.misc.sageinspect import sage_getargspec

@decorator
def warn_slow(func, timelimit=60, *args, **kw):
    print('%s took %d seconds', func.__name__, timelimit)
    return func(*args, **kw)

@warn_slow
def preprocess_input_files(inputdir: Path, tempdir):
    pass

@warn_slow(timelimit=600)
def run_calculation(tempdir, outdir):
    pass

print("With decorator")
print(getfullargspec(preprocess_input_files))
# FullArgSpec(args=['inputdir', 'tempdir'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={'inputdir': <class 'pathlib.Path'>})
print(inspect.getfullargspec(preprocess_input_files))
# FullArgSpec(args=['inputdir', 'tempdir'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={'inputdir': <class 'pathlib.Path'>})
# !! Yields full information as expected
print(sage_getargspec(preprocess_input_files))
# ArgSpec(args=['inputdir', 'tempdir'], varargs=None, keywords=None, defaults=None)
# !! No annotation information
print(getfullargspec(run_calculation))
# FullArgSpec(args=['tempdir', 'outdir'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})
print(inspect.getfullargspec(run_calculation))
# FullArgSpec(args=['tempdir', 'outdir'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})
print(sage_getargspec(preprocess_input_files))
# ArgSpec(args=['inputdir', 'tempdir'], varargs=None, keywords=None, defaults=None)

@decorator_keywords
def warn_slow_sage(func=None, timelimit=60):
     @sage_wraps(func)
     def wrapper(*args, **kwargs):
         print('%s took %d seconds', func.__name__, timelimit)
         return func(*args, **kw)
     return wrapper

@warn_slow_sage
def preprocess_input_files_sage(inputdir: Path, tempdir):
    pass

@warn_slow_sage(timelimit=600)
def run_calculation_sage(tempdir, outdir):
    pass

print("With sage")
print(getfullargspec(preprocess_input_files_sage))
# FullArgSpec(args=[], varargs='args', varkw='kwargs', defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})
print(inspect.getfullargspec(preprocess_input_files_sage))
# FullArgSpec(args=[], varargs='args', varkw='kwargs', defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})
# !! No args nor annotation
print(sage_getargspec(preprocess_input_files_sage))
# ArgSpec(args=['inputdir', 'tempdir'], varargs=None, keywords=None, defaults=None)
print(getfullargspec(run_calculation_sage))
# !! No annotation info
# FullArgSpec(args=[], varargs='args', varkw='kwargs', defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})
print(inspect.getfullargspec(run_calculation_sage))
# FullArgSpec(args=[], varargs='args', varkw='kwargs', defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})
print(sage_getargspec(preprocess_input_files_sage))
# ArgSpec(args=['inputdir', 'tempdir'], varargs=None, keywords=None, defaults=None)

Replacing sage_getargspec with inspect.getfullargspec will be done in a follow-up ticket (as this is already big enough).

Todo (as follow-up): Migrate cachefunction etc to decorator framework. The documentation https://github.com/micheles/decorator/blob/master/docs/documentation.md#the-solution contains an example (memoize) of how this may look like.

Depends on #26254

CC: @mkoeppe @kwankyu

Component: doctest framework

Work Issues: Fix patchbot warnings

Author: Tobias Diez

Branch/Commit: public/documentation/replaceDecorator @ 1b656a3

Issue created by migration from https://trac.sagemath.org/ticket/30884

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions