Adding a new decorator to indicate when a module is deprecated in favor of a Salt extension

This commit is contained in:
Gareth J. Greenaway 2023-06-28 11:12:39 -07:00 committed by Megan Wilhite
parent 2d02017d6c
commit 2efc71ad12
2 changed files with 47 additions and 13 deletions

View file

@ -34,6 +34,7 @@ import salt.utils.platform
import salt.utils.stringutils
import salt.utils.versions
from salt.utils.decorators import Depends
from salt.utils.decorators.extension_deprecation import extension_deprecation_message
try:
# Try the stdlib C extension first
@ -149,7 +150,7 @@ class LoadedFunc:
return self.loader.run(run_func, *args, **kwargs)
def __repr__(self):
return "<{} name={!r}>".format(self.__class__.__name__, self.name)
return f"<{self.__class__.__name__} name={self.name!r}>"
class LoadedMod:
@ -172,10 +173,10 @@ class LoadedMod:
Run the wrapped function in the loader's context.
"""
try:
return self.loader["{}.{}".format(self.mod, name)]
return self.loader[f"{self.mod}.{name}"]
except KeyError:
raise AttributeError(
"No attribute by the name of {} was found on {}".format(name, self.mod)
f"No attribute by the name of {name} was found on {self.mod}"
)
def __repr__(self):
@ -311,10 +312,10 @@ class LazyLoader(salt.utils.lazy.LazyDict):
super().__init__() # late init the lazy loader
# create all of the import namespaces
_generate_module("{}.int".format(self.loaded_base_name))
_generate_module("{}.int.{}".format(self.loaded_base_name, tag))
_generate_module("{}.ext".format(self.loaded_base_name))
_generate_module("{}.ext.{}".format(self.loaded_base_name, tag))
_generate_module(f"{self.loaded_base_name}.int")
_generate_module(f"{self.loaded_base_name}.int.{tag}")
_generate_module(f"{self.loaded_base_name}.ext")
_generate_module(f"{self.loaded_base_name}.ext.{tag}")
def clean_modules(self):
"""
@ -372,19 +373,19 @@ class LazyLoader(salt.utils.lazy.LazyDict):
"""
mod_name = function_name.split(".")[0]
if mod_name in self.loaded_modules:
return "'{}' is not available.".format(function_name)
return f"'{function_name}' is not available."
else:
try:
reason = self.missing_modules[mod_name]
except KeyError:
return "'{}' is not available.".format(function_name)
return f"'{function_name}' is not available."
else:
if reason is not None:
return "'{}' __virtual__ returned False: {}".format(
mod_name, reason
)
else:
return "'{}' __virtual__ returned False".format(mod_name)
return f"'{mod_name}' __virtual__ returned False"
def _refresh_file_mapping(self):
"""
@ -497,7 +498,7 @@ class LazyLoader(salt.utils.lazy.LazyDict):
for suffix in self.suffix_order:
if "" == suffix:
continue # Next suffix (__init__ must have a suffix)
init_file = "__init__{}".format(suffix)
init_file = f"__init__{suffix}"
if init_file in subfiles:
break
else:
@ -978,6 +979,11 @@ class LazyLoader(salt.utils.lazy.LazyDict):
# functions defined(or namespaced) on the loaded module.
continue
# When the module is deprecated wrap functions in deprecation
# warning.
if hasattr(mod, "__deprecated__"):
func = extension_deprecation_message(*mod.__deprecated__)(func)
# Let's get the function name.
# If the module has the __func_alias__ attribute, it must be a
# dictionary mapping in the form of(key -> value):
@ -990,7 +996,7 @@ class LazyLoader(salt.utils.lazy.LazyDict):
try:
full_funcname = ".".join((tgt_mod, funcname))
except TypeError:
full_funcname = "{}.{}".format(tgt_mod, funcname)
full_funcname = f"{tgt_mod}.{funcname}"
# Save many references for lookups
# Careful not to overwrite existing (higher priority) functions
if full_funcname not in self._dict:
@ -1017,7 +1023,7 @@ class LazyLoader(salt.utils.lazy.LazyDict):
if not isinstance(key, str):
raise KeyError("The key must be a string.")
if "." not in key:
raise KeyError("The key '{}' should contain a '.'".format(key))
raise KeyError(f"The key '{key}' should contain a '.'")
mod_name, _ = key.split(".", 1)
with self._lock:
# It is possible that the key is in the dictionary after

View file

@ -0,0 +1,28 @@
import warnings
from salt.utils.decorators.extension_deprecation import extension_deprecation_message
@extension_deprecation_message(3009, "salt_mod", "http://www.example.com")
def salt_func():
return True
def test_extension_deprecation():
"""
this tests for a condition where an included jinja template
is removed from the salt filesystem, but is still loaded from
the cache.
"""
expected_deprecation_message = (
"The 'salt_mod' functionality in Salt has been deprecated and "
"its functionality will be removed in version 3009.0 (Potassium) "
"in favor of the saltext.salt_mod Salt Extension. (http://www.example.com)"
)
with warnings.catch_warnings(record=True) as catch_warnings:
ret = salt_func()
assert ret
assert len(catch_warnings) == 1
assert issubclass(catch_warnings[-1].category, FutureWarning)
assert str(catch_warnings[-1].message) == expected_deprecation_message