(func)
| 1020 | |
| 1021 | |
| 1022 | def _fixture_cache(func): |
| 1023 | cache = {} |
| 1024 | |
| 1025 | # Can't use += on a bound method's property. Therefore, this is a |
| 1026 | # list rather than a variable so that it can be accessed from the |
| 1027 | # pytest_collection_modifyitems(). |
| 1028 | num_tests_use_this_fixture = [0] |
| 1029 | |
| 1030 | num_times_fixture_used = 0 |
| 1031 | |
| 1032 | # Using functools.lru_cache would require the function arguments |
| 1033 | # to be hashable, which wouldn't allow caching fixtures that |
| 1034 | # depend on numpy arrays. For example, a fixture that takes a |
| 1035 | # numpy array as input, then calculates uses a slow method to |
| 1036 | # compute a known correct output for that input. Therefore, |
| 1037 | # including a fallback for serializable types. |
| 1038 | def get_cache_key(*args, **kwargs): |
| 1039 | try: |
| 1040 | hash((args, kwargs)) |
| 1041 | return (args, kwargs) |
| 1042 | except TypeError: |
| 1043 | pass |
| 1044 | |
| 1045 | try: |
| 1046 | return pickle.dumps((args, kwargs)) |
| 1047 | except TypeError as e: |
| 1048 | raise TypeError( |
| 1049 | "TVM caching of fixtures requires arguments to the fixture " |
| 1050 | "to be either hashable or serializable" |
| 1051 | ) from e |
| 1052 | |
| 1053 | @functools.wraps(func) |
| 1054 | def wrapper(*args, **kwargs): |
| 1055 | if num_tests_use_this_fixture[0] == 0: |
| 1056 | raise RuntimeError( |
| 1057 | "Fixture use count is 0. " |
| 1058 | "This can occur if tvm.testing.plugin isn't registered. " |
| 1059 | "If using outside of the TVM test directory, " |
| 1060 | "please add `pytest_plugins = ['tvm.testing.plugin']` to your conftest.py" |
| 1061 | ) |
| 1062 | |
| 1063 | try: |
| 1064 | cache_key = get_cache_key(*args, **kwargs) |
| 1065 | |
| 1066 | try: |
| 1067 | cached_value = cache[cache_key] |
| 1068 | except KeyError: |
| 1069 | cached_value = cache[cache_key] = func(*args, **kwargs) |
| 1070 | |
| 1071 | yield copy.deepcopy( |
| 1072 | cached_value, |
| 1073 | # allowed_class_list should be a list of classes that |
| 1074 | # are safe to copy using copy.deepcopy, but do not |
| 1075 | # implement __deepcopy__, __reduce__, or |
| 1076 | # __reduce_ex__. |
| 1077 | _DeepCopyAllowedClasses(allowed_class_list=[]), |
| 1078 | ) |
| 1079 |
no outgoing calls
no test coverage detected
searching dependent graphs…