m2m模型翻译
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

150 lines
4.1 KiB

6 months ago
  1. """ Caching facility for SymPy """
  2. class _cache(list):
  3. """ List of cached functions """
  4. def print_cache(self):
  5. """print cache info"""
  6. for item in self:
  7. name = item.__name__
  8. myfunc = item
  9. while hasattr(myfunc, '__wrapped__'):
  10. if hasattr(myfunc, 'cache_info'):
  11. info = myfunc.cache_info()
  12. break
  13. else:
  14. myfunc = myfunc.__wrapped__
  15. else:
  16. info = None
  17. print(name, info)
  18. def clear_cache(self):
  19. """clear cache content"""
  20. for item in self:
  21. myfunc = item
  22. while hasattr(myfunc, '__wrapped__'):
  23. if hasattr(myfunc, 'cache_clear'):
  24. myfunc.cache_clear()
  25. break
  26. else:
  27. myfunc = myfunc.__wrapped__
  28. # global cache registry:
  29. CACHE = _cache()
  30. # make clear and print methods available
  31. print_cache = CACHE.print_cache
  32. clear_cache = CACHE.clear_cache
  33. from functools import lru_cache, wraps
  34. def __cacheit(maxsize):
  35. """caching decorator.
  36. important: the result of cached function must be *immutable*
  37. Examples
  38. ========
  39. >>> from sympy import cacheit
  40. >>> @cacheit
  41. ... def f(a, b):
  42. ... return a+b
  43. >>> @cacheit
  44. ... def f(a, b): # noqa: F811
  45. ... return [a, b] # <-- WRONG, returns mutable object
  46. to force cacheit to check returned results mutability and consistency,
  47. set environment variable SYMPY_USE_CACHE to 'debug'
  48. """
  49. def func_wrapper(func):
  50. cfunc = lru_cache(maxsize, typed=True)(func)
  51. @wraps(func)
  52. def wrapper(*args, **kwargs):
  53. try:
  54. retval = cfunc(*args, **kwargs)
  55. except TypeError as e:
  56. if not e.args or not e.args[0].startswith('unhashable type:'):
  57. raise
  58. retval = func(*args, **kwargs)
  59. return retval
  60. wrapper.cache_info = cfunc.cache_info
  61. wrapper.cache_clear = cfunc.cache_clear
  62. CACHE.append(wrapper)
  63. return wrapper
  64. return func_wrapper
  65. ########################################
  66. def __cacheit_nocache(func):
  67. return func
  68. def __cacheit_debug(maxsize):
  69. """cacheit + code to check cache consistency"""
  70. def func_wrapper(func):
  71. cfunc = __cacheit(maxsize)(func)
  72. @wraps(func)
  73. def wrapper(*args, **kw_args):
  74. # always call function itself and compare it with cached version
  75. r1 = func(*args, **kw_args)
  76. r2 = cfunc(*args, **kw_args)
  77. # try to see if the result is immutable
  78. #
  79. # this works because:
  80. #
  81. # hash([1,2,3]) -> raise TypeError
  82. # hash({'a':1, 'b':2}) -> raise TypeError
  83. # hash((1,[2,3])) -> raise TypeError
  84. #
  85. # hash((1,2,3)) -> just computes the hash
  86. hash(r1), hash(r2)
  87. # also see if returned values are the same
  88. if r1 != r2:
  89. raise RuntimeError("Returned values are not the same")
  90. return r1
  91. return wrapper
  92. return func_wrapper
  93. def _getenv(key, default=None):
  94. from os import getenv
  95. return getenv(key, default)
  96. # SYMPY_USE_CACHE=yes/no/debug
  97. USE_CACHE = _getenv('SYMPY_USE_CACHE', 'yes').lower()
  98. # SYMPY_CACHE_SIZE=some_integer/None
  99. # special cases :
  100. # SYMPY_CACHE_SIZE=0 -> No caching
  101. # SYMPY_CACHE_SIZE=None -> Unbounded caching
  102. scs = _getenv('SYMPY_CACHE_SIZE', '1000')
  103. if scs.lower() == 'none':
  104. SYMPY_CACHE_SIZE = None
  105. else:
  106. try:
  107. SYMPY_CACHE_SIZE = int(scs)
  108. except ValueError:
  109. raise RuntimeError(
  110. 'SYMPY_CACHE_SIZE must be a valid integer or None. ' + \
  111. 'Got: %s' % SYMPY_CACHE_SIZE)
  112. if USE_CACHE == 'no':
  113. cacheit = __cacheit_nocache
  114. elif USE_CACHE == 'yes':
  115. cacheit = __cacheit(SYMPY_CACHE_SIZE)
  116. elif USE_CACHE == 'debug':
  117. cacheit = __cacheit_debug(SYMPY_CACHE_SIZE) # a lot slower
  118. else:
  119. raise RuntimeError(
  120. 'unrecognized value for SYMPY_USE_CACHE: %s' % USE_CACHE)