123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- """Thread-safe global parameters"""
- from .cache import clear_cache
- from contextlib import contextmanager
- from threading import local
- class _global_parameters(local):
- """
- Thread-local global parameters.
- Explanation
- ===========
- This class generates thread-local container for SymPy's global parameters.
- Every global parameters must be passed as keyword argument when generating
- its instance.
- A variable, `global_parameters` is provided as default instance for this class.
- WARNING! Although the global parameters are thread-local, SymPy's cache is not
- by now.
- This may lead to undesired result in multi-threading operations.
- Examples
- ========
- >>> from sympy.abc import x
- >>> from sympy.core.cache import clear_cache
- >>> from sympy.core.parameters import global_parameters as gp
- >>> gp.evaluate
- True
- >>> x+x
- 2*x
- >>> log = []
- >>> def f():
- ... clear_cache()
- ... gp.evaluate = False
- ... log.append(x+x)
- ... clear_cache()
- >>> import threading
- >>> thread = threading.Thread(target=f)
- >>> thread.start()
- >>> thread.join()
- >>> print(log)
- [x + x]
- >>> gp.evaluate
- True
- >>> x+x
- 2*x
- References
- ==========
- .. [1] https://docs.python.org/3/library/threading.html
- """
- def __init__(self, **kwargs):
- self.__dict__.update(kwargs)
- def __setattr__(self, name, value):
- if getattr(self, name) != value:
- clear_cache()
- return super().__setattr__(name, value)
- global_parameters = _global_parameters(evaluate=True, distribute=True, exp_is_pow=False)
- @contextmanager
- def evaluate(x):
- """ Control automatic evaluation
- Explanation
- ===========
- This context manager controls whether or not all SymPy functions evaluate
- by default.
- Note that much of SymPy expects evaluated expressions. This functionality
- is experimental and is unlikely to function as intended on large
- expressions.
- Examples
- ========
- >>> from sympy import evaluate
- >>> from sympy.abc import x
- >>> print(x + x)
- 2*x
- >>> with evaluate(False):
- ... print(x + x)
- x + x
- """
- old = global_parameters.evaluate
- try:
- global_parameters.evaluate = x
- yield
- finally:
- global_parameters.evaluate = old
- @contextmanager
- def distribute(x):
- """ Control automatic distribution of Number over Add
- Explanation
- ===========
- This context manager controls whether or not Mul distribute Number over
- Add. Plan is to avoid distributing Number over Add in all of sympy. Once
- that is done, this contextmanager will be removed.
- Examples
- ========
- >>> from sympy.abc import x
- >>> from sympy.core.parameters import distribute
- >>> print(2*(x + 1))
- 2*x + 2
- >>> with distribute(False):
- ... print(2*(x + 1))
- 2*(x + 1)
- """
- old = global_parameters.distribute
- try:
- global_parameters.distribute = x
- yield
- finally:
- global_parameters.distribute = old
- @contextmanager
- def _exp_is_pow(x):
- """
- Control whether `e^x` should be represented as ``exp(x)`` or a ``Pow(E, x)``.
- Examples
- ========
- >>> from sympy import exp
- >>> from sympy.abc import x
- >>> from sympy.core.parameters import _exp_is_pow
- >>> with _exp_is_pow(True): print(type(exp(x)))
- <class 'sympy.core.power.Pow'>
- >>> with _exp_is_pow(False): print(type(exp(x)))
- exp
- """
- old = global_parameters.exp_is_pow
- clear_cache()
- try:
- global_parameters.exp_is_pow = x
- yield
- finally:
- clear_cache()
- global_parameters.exp_is_pow = old
|