Opened 10 years ago

Last modified 4 years ago

## #9556 closed enhancement

# Dynamic attributes for symbolic expressions — at Initial Version

Reported by: | SimonKing | Owned by: | segfaulting doctests |
---|---|---|---|

Priority: | major | Milestone: | sage-5.11 |

Component: | symbolics | Keywords: | symbolic expression dynamic attribute sd48 |

Cc: | burcin, kcrisman, vbraun, eviatarbach | Merged in: | |

Authors: | Reviewers: | ||

Report Upstream: | N/A | Work issues: | |

Branch: | Commit: | ||

Dependencies: | Stopgaps: |

### Description

Let `e`

be a symbolic expression. It may happen that `e.operator()`

has a certain callable attribute, say, `foo`

, that is not a method of `Function`

. In this situation, one would like to use `e.foo()`

, which is supposed to return `e.operator().foo(*e.operands())`

- apparently this is useful for working with hypergeometric functions.

**Example**

sage: from sage.symbolic.function import BuiltinFunction sage: class ExampleBuiltin(BuiltinFunction): ... def __init__(self): ... BuiltinFunction.__init__(self, 'ex_func', nargs=0) #arbitrary no of args ... def some_function_name(self, *args): ... return len(args) ... sage: ex_func = ExampleBuiltin() sage: ex_func ex_func

We obtain a symbolic expression by calling `ex_func`

:

sage: e = ex_func(x,x+1, x+2) sage: type(e) <type 'sage.symbolic.expression.Expression'>

We add a callable and a non-callable attribute to `ex_func`

:

sage: def some_function(slf, *L): print slf,'called with',L ... sage: ex_func.foo_bar = some_function sage: ex_func.bar_foo = 4

Now, both the new method and the callable attribute `foo_bar`

of
`ex_func`

are available from `e`

, but not the non-callable:

sage: e.some_function_name() 3 sage: e.foo_bar() ex_func called with (x, x + 1, x + 2) sage: e.bar_foo Traceback (most recent call last): ... AttributeError: <type 'sage.symbolic.expression.Expression'> has no attribute 'bar_foo'

Tab completion and introspection work:

sage: 'foo_bar' in dir(e) # indirect doctest True sage: 'some_function_name' in dir(e) True sage: 'bar_foo' in dir(e) False sage: import sagenb.misc.support as s sage: s.completions('e.some', globals(), system='python') ['e.some_function_name']

**Problems**

When I ran `sage -testall`

, several doctests segfaulted:

sage -t -verbose "devel/sage/sage/functions/hyperbolic.py" sage -t -verbose "devel/sage/sage/games/hexad.py" sage -t -verbose "devel/sage/sage/matrix/tests.py" sage -t -verbose "devel/sage/sage/misc/sage_eval.py" sage -t -verbose "devel/sage/sage/plot/animate.py" sage -t -verbose "devel/sage/sage/quadratic_forms/quadratic_form__mass__Conway_Sloane_masses.py" sage -t -verbose "devel/sage/sage/rings/polynomial/polynomial_element.pyx"

I tried (using `sage -t -verbose`

) to find out what exactly fails. When I ran some of these failing examples in an interactive session, no segfault occured. So, is there a nasty side effect?

**Note:**See TracTickets for help on using tickets.

The patch implements dynamic attributes, but some doctests segfault