chore: 添加虚拟环境到仓库
- 添加 backend_service/venv 虚拟环境 - 包含所有Python依赖包 - 注意:虚拟环境约393MB,包含12655个文件
This commit is contained in:
@@ -0,0 +1,791 @@
|
||||
"""Options manager for :class:`~.Poly` and public API functions. """
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
__all__ = ["Options"]
|
||||
|
||||
from sympy.core.basic import Basic
|
||||
from sympy.core.expr import Expr
|
||||
from sympy.core.sympify import sympify
|
||||
from sympy.polys.polyerrors import GeneratorsError, OptionError, FlagError
|
||||
from sympy.utilities import numbered_symbols, topological_sort, public
|
||||
from sympy.utilities.iterables import has_dups, is_sequence
|
||||
|
||||
import sympy.polys
|
||||
|
||||
import re
|
||||
|
||||
class Option:
|
||||
"""Base class for all kinds of options. """
|
||||
|
||||
option: str | None = None
|
||||
|
||||
is_Flag = False
|
||||
|
||||
requires: list[str] = []
|
||||
excludes: list[str] = []
|
||||
|
||||
after: list[str] = []
|
||||
before: list[str] = []
|
||||
|
||||
@classmethod
|
||||
def default(cls):
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def preprocess(cls, option):
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def postprocess(cls, options):
|
||||
pass
|
||||
|
||||
|
||||
class Flag(Option):
|
||||
"""Base class for all kinds of flags. """
|
||||
|
||||
is_Flag = True
|
||||
|
||||
|
||||
class BooleanOption(Option):
|
||||
"""An option that must have a boolean value or equivalent assigned. """
|
||||
|
||||
@classmethod
|
||||
def preprocess(cls, value):
|
||||
if value in [True, False]:
|
||||
return bool(value)
|
||||
else:
|
||||
raise OptionError("'%s' must have a boolean value assigned, got %s" % (cls.option, value))
|
||||
|
||||
|
||||
class OptionType(type):
|
||||
"""Base type for all options that does registers options. """
|
||||
|
||||
def __init__(cls, *args, **kwargs):
|
||||
@property
|
||||
def getter(self):
|
||||
try:
|
||||
return self[cls.option]
|
||||
except KeyError:
|
||||
return cls.default()
|
||||
|
||||
setattr(Options, cls.option, getter)
|
||||
Options.__options__[cls.option] = cls
|
||||
|
||||
|
||||
@public
|
||||
class Options(dict):
|
||||
"""
|
||||
Options manager for polynomial manipulation module.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
>>> from sympy.polys.polyoptions import Options
|
||||
>>> from sympy.polys.polyoptions import build_options
|
||||
|
||||
>>> from sympy.abc import x, y, z
|
||||
|
||||
>>> Options((x, y, z), {'domain': 'ZZ'})
|
||||
{'auto': False, 'domain': ZZ, 'gens': (x, y, z)}
|
||||
|
||||
>>> build_options((x, y, z), {'domain': 'ZZ'})
|
||||
{'auto': False, 'domain': ZZ, 'gens': (x, y, z)}
|
||||
|
||||
**Options**
|
||||
|
||||
* Expand --- boolean option
|
||||
* Gens --- option
|
||||
* Wrt --- option
|
||||
* Sort --- option
|
||||
* Order --- option
|
||||
* Field --- boolean option
|
||||
* Greedy --- boolean option
|
||||
* Domain --- option
|
||||
* Split --- boolean option
|
||||
* Gaussian --- boolean option
|
||||
* Extension --- option
|
||||
* Modulus --- option
|
||||
* Symmetric --- boolean option
|
||||
* Strict --- boolean option
|
||||
|
||||
**Flags**
|
||||
|
||||
* Auto --- boolean flag
|
||||
* Frac --- boolean flag
|
||||
* Formal --- boolean flag
|
||||
* Polys --- boolean flag
|
||||
* Include --- boolean flag
|
||||
* All --- boolean flag
|
||||
* Gen --- flag
|
||||
* Series --- boolean flag
|
||||
|
||||
"""
|
||||
|
||||
__order__ = None
|
||||
__options__: dict[str, type[Option]] = {}
|
||||
|
||||
gens: tuple[Expr, ...]
|
||||
domain: sympy.polys.domains.Domain
|
||||
|
||||
def __init__(self, gens, args, flags=None, strict=False):
|
||||
dict.__init__(self)
|
||||
|
||||
if gens and args.get('gens', ()):
|
||||
raise OptionError(
|
||||
"both '*gens' and keyword argument 'gens' supplied")
|
||||
elif gens:
|
||||
args = dict(args)
|
||||
args['gens'] = gens
|
||||
|
||||
defaults = args.pop('defaults', {})
|
||||
|
||||
def preprocess_options(args):
|
||||
for option, value in args.items():
|
||||
try:
|
||||
cls = self.__options__[option]
|
||||
except KeyError:
|
||||
raise OptionError("'%s' is not a valid option" % option)
|
||||
|
||||
if issubclass(cls, Flag):
|
||||
if flags is None or option not in flags:
|
||||
if strict:
|
||||
raise OptionError("'%s' flag is not allowed in this context" % option)
|
||||
|
||||
if value is not None:
|
||||
self[option] = cls.preprocess(value)
|
||||
|
||||
preprocess_options(args)
|
||||
|
||||
for key in dict(defaults):
|
||||
if key in self:
|
||||
del defaults[key]
|
||||
else:
|
||||
for option in self.keys():
|
||||
cls = self.__options__[option]
|
||||
|
||||
if key in cls.excludes:
|
||||
del defaults[key]
|
||||
break
|
||||
|
||||
preprocess_options(defaults)
|
||||
|
||||
for option in self.keys():
|
||||
cls = self.__options__[option]
|
||||
|
||||
for require_option in cls.requires:
|
||||
if self.get(require_option) is None:
|
||||
raise OptionError("'%s' option is only allowed together with '%s'" % (option, require_option))
|
||||
|
||||
for exclude_option in cls.excludes:
|
||||
if self.get(exclude_option) is not None:
|
||||
raise OptionError("'%s' option is not allowed together with '%s'" % (option, exclude_option))
|
||||
|
||||
for option in self.__order__:
|
||||
self.__options__[option].postprocess(self)
|
||||
|
||||
@classmethod
|
||||
def _init_dependencies_order(cls):
|
||||
"""Resolve the order of options' processing. """
|
||||
if cls.__order__ is None:
|
||||
vertices, edges = [], set()
|
||||
|
||||
for name, option in cls.__options__.items():
|
||||
vertices.append(name)
|
||||
|
||||
edges.update((_name, name) for _name in option.after)
|
||||
|
||||
edges.update((name, _name) for _name in option.before)
|
||||
|
||||
try:
|
||||
cls.__order__ = topological_sort((vertices, list(edges)))
|
||||
except ValueError:
|
||||
raise RuntimeError(
|
||||
"cycle detected in sympy.polys options framework")
|
||||
|
||||
def clone(self, updates={}):
|
||||
"""Clone ``self`` and update specified options. """
|
||||
obj = dict.__new__(self.__class__)
|
||||
|
||||
for option, value in self.items():
|
||||
obj[option] = value
|
||||
|
||||
for option, value in updates.items():
|
||||
obj[option] = value
|
||||
|
||||
return obj
|
||||
|
||||
def __setattr__(self, attr, value):
|
||||
if attr in self.__options__:
|
||||
self[attr] = value
|
||||
else:
|
||||
super().__setattr__(attr, value)
|
||||
|
||||
@property
|
||||
def args(self):
|
||||
args = {}
|
||||
|
||||
for option, value in self.items():
|
||||
if value is not None and option != 'gens':
|
||||
cls = self.__options__[option]
|
||||
|
||||
if not issubclass(cls, Flag):
|
||||
args[option] = value
|
||||
|
||||
return args
|
||||
|
||||
@property
|
||||
def options(self):
|
||||
options = {}
|
||||
|
||||
for option, cls in self.__options__.items():
|
||||
if not issubclass(cls, Flag):
|
||||
options[option] = getattr(self, option)
|
||||
|
||||
return options
|
||||
|
||||
@property
|
||||
def flags(self):
|
||||
flags = {}
|
||||
|
||||
for option, cls in self.__options__.items():
|
||||
if issubclass(cls, Flag):
|
||||
flags[option] = getattr(self, option)
|
||||
|
||||
return flags
|
||||
|
||||
|
||||
class Expand(BooleanOption, metaclass=OptionType):
|
||||
"""``expand`` option to polynomial manipulation functions. """
|
||||
|
||||
option = 'expand'
|
||||
|
||||
requires: list[str] = []
|
||||
excludes: list[str] = []
|
||||
|
||||
@classmethod
|
||||
def default(cls):
|
||||
return True
|
||||
|
||||
|
||||
class Gens(Option, metaclass=OptionType):
|
||||
"""``gens`` option to polynomial manipulation functions. """
|
||||
|
||||
option = 'gens'
|
||||
|
||||
requires: list[str] = []
|
||||
excludes: list[str] = []
|
||||
|
||||
@classmethod
|
||||
def default(cls):
|
||||
return ()
|
||||
|
||||
@classmethod
|
||||
def preprocess(cls, gens):
|
||||
if isinstance(gens, Basic):
|
||||
gens = (gens,)
|
||||
elif len(gens) == 1 and is_sequence(gens[0]):
|
||||
gens = gens[0]
|
||||
|
||||
if gens == (None,):
|
||||
gens = ()
|
||||
elif has_dups(gens):
|
||||
raise GeneratorsError("duplicated generators: %s" % str(gens))
|
||||
elif any(gen.is_commutative is False for gen in gens):
|
||||
raise GeneratorsError("non-commutative generators: %s" % str(gens))
|
||||
|
||||
return tuple(gens)
|
||||
|
||||
|
||||
class Wrt(Option, metaclass=OptionType):
|
||||
"""``wrt`` option to polynomial manipulation functions. """
|
||||
|
||||
option = 'wrt'
|
||||
|
||||
requires: list[str] = []
|
||||
excludes: list[str] = []
|
||||
|
||||
_re_split = re.compile(r"\s*,\s*|\s+")
|
||||
|
||||
@classmethod
|
||||
def preprocess(cls, wrt):
|
||||
if isinstance(wrt, Basic):
|
||||
return [str(wrt)]
|
||||
elif isinstance(wrt, str):
|
||||
wrt = wrt.strip()
|
||||
if wrt.endswith(','):
|
||||
raise OptionError('Bad input: missing parameter.')
|
||||
if not wrt:
|
||||
return []
|
||||
return list(cls._re_split.split(wrt))
|
||||
elif hasattr(wrt, '__getitem__'):
|
||||
return list(map(str, wrt))
|
||||
else:
|
||||
raise OptionError("invalid argument for 'wrt' option")
|
||||
|
||||
|
||||
class Sort(Option, metaclass=OptionType):
|
||||
"""``sort`` option to polynomial manipulation functions. """
|
||||
|
||||
option = 'sort'
|
||||
|
||||
requires: list[str] = []
|
||||
excludes: list[str] = []
|
||||
|
||||
@classmethod
|
||||
def default(cls):
|
||||
return []
|
||||
|
||||
@classmethod
|
||||
def preprocess(cls, sort):
|
||||
if isinstance(sort, str):
|
||||
return [ gen.strip() for gen in sort.split('>') ]
|
||||
elif hasattr(sort, '__getitem__'):
|
||||
return list(map(str, sort))
|
||||
else:
|
||||
raise OptionError("invalid argument for 'sort' option")
|
||||
|
||||
|
||||
class Order(Option, metaclass=OptionType):
|
||||
"""``order`` option to polynomial manipulation functions. """
|
||||
|
||||
option = 'order'
|
||||
|
||||
requires: list[str] = []
|
||||
excludes: list[str] = []
|
||||
|
||||
@classmethod
|
||||
def default(cls):
|
||||
return sympy.polys.orderings.lex
|
||||
|
||||
@classmethod
|
||||
def preprocess(cls, order):
|
||||
return sympy.polys.orderings.monomial_key(order)
|
||||
|
||||
|
||||
class Field(BooleanOption, metaclass=OptionType):
|
||||
"""``field`` option to polynomial manipulation functions. """
|
||||
|
||||
option = 'field'
|
||||
|
||||
requires: list[str] = []
|
||||
excludes = ['domain', 'split', 'gaussian']
|
||||
|
||||
|
||||
class Greedy(BooleanOption, metaclass=OptionType):
|
||||
"""``greedy`` option to polynomial manipulation functions. """
|
||||
|
||||
option = 'greedy'
|
||||
|
||||
requires: list[str] = []
|
||||
excludes = ['domain', 'split', 'gaussian', 'extension', 'modulus', 'symmetric']
|
||||
|
||||
|
||||
class Composite(BooleanOption, metaclass=OptionType):
|
||||
"""``composite`` option to polynomial manipulation functions. """
|
||||
|
||||
option = 'composite'
|
||||
|
||||
@classmethod
|
||||
def default(cls):
|
||||
return None
|
||||
|
||||
requires: list[str] = []
|
||||
excludes = ['domain', 'split', 'gaussian', 'extension', 'modulus', 'symmetric']
|
||||
|
||||
|
||||
class Domain(Option, metaclass=OptionType):
|
||||
"""``domain`` option to polynomial manipulation functions. """
|
||||
|
||||
option = 'domain'
|
||||
|
||||
requires: list[str] = []
|
||||
excludes = ['field', 'greedy', 'split', 'gaussian', 'extension']
|
||||
|
||||
after = ['gens']
|
||||
|
||||
_re_realfield = re.compile(r"^(R|RR)(_(\d+))?$")
|
||||
_re_complexfield = re.compile(r"^(C|CC)(_(\d+))?$")
|
||||
_re_finitefield = re.compile(r"^(FF|GF)\((\d+)\)$")
|
||||
_re_polynomial = re.compile(r"^(Z|ZZ|Q|QQ|ZZ_I|QQ_I|R|RR|C|CC)\[(.+)\]$")
|
||||
_re_fraction = re.compile(r"^(Z|ZZ|Q|QQ)\((.+)\)$")
|
||||
_re_algebraic = re.compile(r"^(Q|QQ)\<(.+)\>$")
|
||||
|
||||
@classmethod
|
||||
def preprocess(cls, domain):
|
||||
if isinstance(domain, sympy.polys.domains.Domain):
|
||||
return domain
|
||||
elif hasattr(domain, 'to_domain'):
|
||||
return domain.to_domain()
|
||||
elif isinstance(domain, str):
|
||||
if domain in ['Z', 'ZZ']:
|
||||
return sympy.polys.domains.ZZ
|
||||
|
||||
if domain in ['Q', 'QQ']:
|
||||
return sympy.polys.domains.QQ
|
||||
|
||||
if domain == 'ZZ_I':
|
||||
return sympy.polys.domains.ZZ_I
|
||||
|
||||
if domain == 'QQ_I':
|
||||
return sympy.polys.domains.QQ_I
|
||||
|
||||
if domain == 'EX':
|
||||
return sympy.polys.domains.EX
|
||||
|
||||
r = cls._re_realfield.match(domain)
|
||||
|
||||
if r is not None:
|
||||
_, _, prec = r.groups()
|
||||
|
||||
if prec is None:
|
||||
return sympy.polys.domains.RR
|
||||
else:
|
||||
return sympy.polys.domains.RealField(int(prec))
|
||||
|
||||
r = cls._re_complexfield.match(domain)
|
||||
|
||||
if r is not None:
|
||||
_, _, prec = r.groups()
|
||||
|
||||
if prec is None:
|
||||
return sympy.polys.domains.CC
|
||||
else:
|
||||
return sympy.polys.domains.ComplexField(int(prec))
|
||||
|
||||
r = cls._re_finitefield.match(domain)
|
||||
|
||||
if r is not None:
|
||||
return sympy.polys.domains.FF(int(r.groups()[1]))
|
||||
|
||||
r = cls._re_polynomial.match(domain)
|
||||
|
||||
if r is not None:
|
||||
ground, gens = r.groups()
|
||||
|
||||
gens = list(map(sympify, gens.split(',')))
|
||||
|
||||
if ground in ['Z', 'ZZ']:
|
||||
return sympy.polys.domains.ZZ.poly_ring(*gens)
|
||||
elif ground in ['Q', 'QQ']:
|
||||
return sympy.polys.domains.QQ.poly_ring(*gens)
|
||||
elif ground in ['R', 'RR']:
|
||||
return sympy.polys.domains.RR.poly_ring(*gens)
|
||||
elif ground == 'ZZ_I':
|
||||
return sympy.polys.domains.ZZ_I.poly_ring(*gens)
|
||||
elif ground == 'QQ_I':
|
||||
return sympy.polys.domains.QQ_I.poly_ring(*gens)
|
||||
else:
|
||||
return sympy.polys.domains.CC.poly_ring(*gens)
|
||||
|
||||
r = cls._re_fraction.match(domain)
|
||||
|
||||
if r is not None:
|
||||
ground, gens = r.groups()
|
||||
|
||||
gens = list(map(sympify, gens.split(',')))
|
||||
|
||||
if ground in ['Z', 'ZZ']:
|
||||
return sympy.polys.domains.ZZ.frac_field(*gens)
|
||||
else:
|
||||
return sympy.polys.domains.QQ.frac_field(*gens)
|
||||
|
||||
r = cls._re_algebraic.match(domain)
|
||||
|
||||
if r is not None:
|
||||
gens = list(map(sympify, r.groups()[1].split(',')))
|
||||
return sympy.polys.domains.QQ.algebraic_field(*gens)
|
||||
|
||||
raise OptionError('expected a valid domain specification, got %s' % domain)
|
||||
|
||||
@classmethod
|
||||
def postprocess(cls, options):
|
||||
if 'gens' in options and 'domain' in options and options['domain'].is_Composite and \
|
||||
(set(options['domain'].symbols) & set(options['gens'])):
|
||||
raise GeneratorsError(
|
||||
"ground domain and generators interfere together")
|
||||
elif ('gens' not in options or not options['gens']) and \
|
||||
'domain' in options and options['domain'] == sympy.polys.domains.EX:
|
||||
raise GeneratorsError("you have to provide generators because EX domain was requested")
|
||||
|
||||
|
||||
class Split(BooleanOption, metaclass=OptionType):
|
||||
"""``split`` option to polynomial manipulation functions. """
|
||||
|
||||
option = 'split'
|
||||
|
||||
requires: list[str] = []
|
||||
excludes = ['field', 'greedy', 'domain', 'gaussian', 'extension',
|
||||
'modulus', 'symmetric']
|
||||
|
||||
@classmethod
|
||||
def postprocess(cls, options):
|
||||
if 'split' in options:
|
||||
raise NotImplementedError("'split' option is not implemented yet")
|
||||
|
||||
|
||||
class Gaussian(BooleanOption, metaclass=OptionType):
|
||||
"""``gaussian`` option to polynomial manipulation functions. """
|
||||
|
||||
option = 'gaussian'
|
||||
|
||||
requires: list[str] = []
|
||||
excludes = ['field', 'greedy', 'domain', 'split', 'extension',
|
||||
'modulus', 'symmetric']
|
||||
|
||||
@classmethod
|
||||
def postprocess(cls, options):
|
||||
if 'gaussian' in options and options['gaussian'] is True:
|
||||
options['domain'] = sympy.polys.domains.QQ_I
|
||||
Extension.postprocess(options)
|
||||
|
||||
|
||||
class Extension(Option, metaclass=OptionType):
|
||||
"""``extension`` option to polynomial manipulation functions. """
|
||||
|
||||
option = 'extension'
|
||||
|
||||
requires: list[str] = []
|
||||
excludes = ['greedy', 'domain', 'split', 'gaussian', 'modulus',
|
||||
'symmetric']
|
||||
|
||||
@classmethod
|
||||
def preprocess(cls, extension):
|
||||
if extension == 1:
|
||||
return bool(extension)
|
||||
elif extension == 0:
|
||||
raise OptionError("'False' is an invalid argument for 'extension'")
|
||||
else:
|
||||
if not hasattr(extension, '__iter__'):
|
||||
extension = {extension}
|
||||
else:
|
||||
if not extension:
|
||||
extension = None
|
||||
else:
|
||||
extension = set(extension)
|
||||
|
||||
return extension
|
||||
|
||||
@classmethod
|
||||
def postprocess(cls, options):
|
||||
if 'extension' in options and options['extension'] is not True:
|
||||
options['domain'] = sympy.polys.domains.QQ.algebraic_field(
|
||||
*options['extension'])
|
||||
|
||||
|
||||
class Modulus(Option, metaclass=OptionType):
|
||||
"""``modulus`` option to polynomial manipulation functions. """
|
||||
|
||||
option = 'modulus'
|
||||
|
||||
requires: list[str] = []
|
||||
excludes = ['greedy', 'split', 'domain', 'gaussian', 'extension']
|
||||
|
||||
@classmethod
|
||||
def preprocess(cls, modulus):
|
||||
modulus = sympify(modulus)
|
||||
|
||||
if modulus.is_Integer and modulus > 0:
|
||||
return int(modulus)
|
||||
else:
|
||||
raise OptionError(
|
||||
"'modulus' must a positive integer, got %s" % modulus)
|
||||
|
||||
@classmethod
|
||||
def postprocess(cls, options):
|
||||
if 'modulus' in options:
|
||||
modulus = options['modulus']
|
||||
symmetric = options.get('symmetric', True)
|
||||
options['domain'] = sympy.polys.domains.FF(modulus, symmetric)
|
||||
|
||||
|
||||
class Symmetric(BooleanOption, metaclass=OptionType):
|
||||
"""``symmetric`` option to polynomial manipulation functions. """
|
||||
|
||||
option = 'symmetric'
|
||||
|
||||
requires = ['modulus']
|
||||
excludes = ['greedy', 'domain', 'split', 'gaussian', 'extension']
|
||||
|
||||
|
||||
class Strict(BooleanOption, metaclass=OptionType):
|
||||
"""``strict`` option to polynomial manipulation functions. """
|
||||
|
||||
option = 'strict'
|
||||
|
||||
@classmethod
|
||||
def default(cls):
|
||||
return True
|
||||
|
||||
|
||||
class Auto(BooleanOption, Flag, metaclass=OptionType):
|
||||
"""``auto`` flag to polynomial manipulation functions. """
|
||||
|
||||
option = 'auto'
|
||||
|
||||
after = ['field', 'domain', 'extension', 'gaussian']
|
||||
|
||||
@classmethod
|
||||
def default(cls):
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def postprocess(cls, options):
|
||||
if ('domain' in options or 'field' in options) and 'auto' not in options:
|
||||
options['auto'] = False
|
||||
|
||||
|
||||
class Frac(BooleanOption, Flag, metaclass=OptionType):
|
||||
"""``auto`` option to polynomial manipulation functions. """
|
||||
|
||||
option = 'frac'
|
||||
|
||||
@classmethod
|
||||
def default(cls):
|
||||
return False
|
||||
|
||||
|
||||
class Formal(BooleanOption, Flag, metaclass=OptionType):
|
||||
"""``formal`` flag to polynomial manipulation functions. """
|
||||
|
||||
option = 'formal'
|
||||
|
||||
@classmethod
|
||||
def default(cls):
|
||||
return False
|
||||
|
||||
|
||||
class Polys(BooleanOption, Flag, metaclass=OptionType):
|
||||
"""``polys`` flag to polynomial manipulation functions. """
|
||||
|
||||
option = 'polys'
|
||||
|
||||
|
||||
class Include(BooleanOption, Flag, metaclass=OptionType):
|
||||
"""``include`` flag to polynomial manipulation functions. """
|
||||
|
||||
option = 'include'
|
||||
|
||||
@classmethod
|
||||
def default(cls):
|
||||
return False
|
||||
|
||||
|
||||
class All(BooleanOption, Flag, metaclass=OptionType):
|
||||
"""``all`` flag to polynomial manipulation functions. """
|
||||
|
||||
option = 'all'
|
||||
|
||||
@classmethod
|
||||
def default(cls):
|
||||
return False
|
||||
|
||||
|
||||
class Gen(Flag, metaclass=OptionType):
|
||||
"""``gen`` flag to polynomial manipulation functions. """
|
||||
|
||||
option = 'gen'
|
||||
|
||||
@classmethod
|
||||
def default(cls):
|
||||
return 0
|
||||
|
||||
@classmethod
|
||||
def preprocess(cls, gen):
|
||||
if isinstance(gen, (Basic, int)):
|
||||
return gen
|
||||
else:
|
||||
raise OptionError("invalid argument for 'gen' option")
|
||||
|
||||
|
||||
class Series(BooleanOption, Flag, metaclass=OptionType):
|
||||
"""``series`` flag to polynomial manipulation functions. """
|
||||
|
||||
option = 'series'
|
||||
|
||||
@classmethod
|
||||
def default(cls):
|
||||
return False
|
||||
|
||||
|
||||
class Symbols(Flag, metaclass=OptionType):
|
||||
"""``symbols`` flag to polynomial manipulation functions. """
|
||||
|
||||
option = 'symbols'
|
||||
|
||||
@classmethod
|
||||
def default(cls):
|
||||
return numbered_symbols('s', start=1)
|
||||
|
||||
@classmethod
|
||||
def preprocess(cls, symbols):
|
||||
if hasattr(symbols, '__iter__'):
|
||||
return iter(symbols)
|
||||
else:
|
||||
raise OptionError("expected an iterator or iterable container, got %s" % symbols)
|
||||
|
||||
|
||||
class Method(Flag, metaclass=OptionType):
|
||||
"""``method`` flag to polynomial manipulation functions. """
|
||||
|
||||
option = 'method'
|
||||
|
||||
@classmethod
|
||||
def preprocess(cls, method):
|
||||
if isinstance(method, str):
|
||||
return method.lower()
|
||||
else:
|
||||
raise OptionError("expected a string, got %s" % method)
|
||||
|
||||
|
||||
def build_options(gens, args=None):
|
||||
"""Construct options from keyword arguments or ... options. """
|
||||
if args is None:
|
||||
gens, args = (), gens
|
||||
|
||||
if len(args) != 1 or 'opt' not in args or gens:
|
||||
return Options(gens, args)
|
||||
else:
|
||||
return args['opt']
|
||||
|
||||
|
||||
def allowed_flags(args, flags):
|
||||
"""
|
||||
Allow specified flags to be used in the given context.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
>>> from sympy.polys.polyoptions import allowed_flags
|
||||
>>> from sympy.polys.domains import ZZ
|
||||
|
||||
>>> allowed_flags({'domain': ZZ}, [])
|
||||
|
||||
>>> allowed_flags({'domain': ZZ, 'frac': True}, [])
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
FlagError: 'frac' flag is not allowed in this context
|
||||
|
||||
>>> allowed_flags({'domain': ZZ, 'frac': True}, ['frac'])
|
||||
|
||||
"""
|
||||
flags = set(flags)
|
||||
|
||||
for arg in args.keys():
|
||||
try:
|
||||
if Options.__options__[arg].is_Flag and arg not in flags:
|
||||
raise FlagError(
|
||||
"'%s' flag is not allowed in this context" % arg)
|
||||
except KeyError:
|
||||
raise OptionError("'%s' is not a valid option" % arg)
|
||||
|
||||
|
||||
def set_defaults(options, **defaults):
|
||||
"""Update options with default values. """
|
||||
if 'defaults' not in options:
|
||||
options = dict(options)
|
||||
options['defaults'] = defaults
|
||||
|
||||
return options
|
||||
|
||||
Options._init_dependencies_order()
|
||||
Reference in New Issue
Block a user