Hi all,
I've been working on removing C, and now that all the simple cases are
done, I'm getting to the harder ones - those where SymPy code is called
during the import (which will fail if the SymPy code being called has
not yet fully imported).
There's the solvable cases - stuff like ask.py's known-properties
database, where the initialization can be moved from module-level code
to a function, so the initialization will happen on demand, after the
"import sympy" statement has completed.
And now I'm at an unsolvable case: anything that uses S will run class
initialization code. And replacing that code with something delayed
would be impractical.
Here's the bottom end of such a stack trace:
File "sets/fancysets.py", line 173, in <module>
class Reals(with_metaclass(Singleton, Interval)):
File "core/compatibility.py", line 181, in __new__
return meta(name, bases, d)
File "core/singleton.py", line 70, in __init__
the_instance = ctor(cls)
File "sets/fancysets.py", line 176, in __new__
return Interval.__new__(cls, -S.Infinity, S.Infinity)
File "sets/sets.py", line 744, in __new__
if (end < start) == True:
File "core/numbers.py", line 1005, in __lt__
other = other.evalf()
File "core/evalf.py", line 1343, in evalf
_create_evalf_table()
File "core/evalf.py", line 1184, in _create_evalf_table
from sympy.functions.combinatorial.numbers import bernoulli
ImportError: cannot import name bernoulli
What happens is that the "Reals" class gets initialized, which is a
Singleton, so its Singleton metaclass runs the constructor to get "the
instance":
File "core/singleton.py", line 70, in __init__
the_instance = ctor(cls)
In the case of Reals, the constructor quite reasonably tries to define
th set of Reals as the Interval between -Infinity and Infinity.
Unfortunately, this runs SymPy code during class definition time, which
is during import time, at which time we can't rely on SymPy being fully
available yet. In this particular instance, the code runs into
_create_evalf_table, but minor restructuring could shift the actual
point of failure almost anywhere - all that's needed is an import that
runs some piece of SymPy code that isn't imported yet.
Question is: WHAT DO WE DO?
===========================
1) What *will* work is to replace the attribute with a function.
Attributes need to be initialized before use, functions don't need to
work until they are actually needed.
Except then S.Foo would have to be rewritten as S.Foo() for all values
of Foo. Anybody who ever used SymPy and picked up the S.Foo idiom for
his code will curse us to hell if we do that.
2) We could defer creation of the_instance. S would first simply collect
names for its namespace, and trigger instance creation on request (which
could be done from sympy.__init__.py).
Any uses of S at import time would fail and need to be fixed (except
those in the Singleton class constructors). I do not know how many files
would be affected by that -> not nice, but maybe an option.
3) We could change the code that accesses the_instance so that actual
construction is delayed until actual use.
the_instance is used only inside the __init__ function of Singleton:
class Singleton(ManagedProperties):
...
def __init__(cls, name, bases, dict_):
...
# The creation call that needs to be delayed:
the_instance = ctor(cls)
def __new__(cls):
# Easy: call ctor(cls) on the first __new__.
return the_instance
...
# Harder: route S's getattr to a function that
# runs ctor(cl) to construct the_instance.
setattr(S, name, the_instance)
I don't have a full grasp of what ManagedProperties does yet, so this
may or may not be doable.
Questions? Comments? More ideas how to deal with this?
--
You received this message because you are subscribed to the Google Groups
"sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to sympy+unsubscr...@googlegroups.com.
To post to this group, send email to sympy@googlegroups.com.
Visit this group at http://groups.google.com/group/sympy.
To view this discussion on the web visit
https://groups.google.com/d/msgid/sympy/54FA0980.9070304%40durchholz.org.
For more options, visit https://groups.google.com/d/optout.