-
Notifications
You must be signed in to change notification settings - Fork 6.5k
[Utils] Add deprecate function and move testing_utils under utils #659
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The documentation is not available anymore as the PR was closed or merged. |
| DeprecationWarning, | ||
| " file" | ||
| ) | ||
| deprecate("steps_offset!=1", "1.0.0", deprecation_message, standard_warn=False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a big change and I like to keep it for a bit until we force people to not pass steps_offset anymore.
|
|
||
| offset = kwargs["offset"] | ||
| deprecated_offset = deprecate( | ||
| "offset", "0.5.0", "Please pass `steps_offset` to `__init__` instead.", take_from=kwargs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bump as we would have already missed this version
|
|
||
| offset = kwargs["offset"] | ||
| deprecated_offset = deprecate( | ||
| "offset", "0.5.0", "Please pass `steps_offset` to `__init__` instead.", take_from=kwargs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bump as we would have already missed this version
| " `'images'` instead.", | ||
| DeprecationWarning, | ||
| ) | ||
| deprecate("samples", "0.6.0", "Please use `.images` or `'images'` instead.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bump twice as we would have already missed this version and it's important
| from diffusers.utils import deprecate | ||
|
|
||
|
|
||
| class DeprecateTester(unittest.TestCase): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test best describes all the functionality that we need to ensure
patil-suraj
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for working on this, this will be very useful!
And really nice tests 😍 ! Love this way of explaining new features with tests.
src/diffusers/utils/testing_utils.py
Outdated
| def deprecate(*args, take_from: Optional[Union[Dict, Any]] = None, standard_warn=True): | ||
| from .. import __version__ | ||
|
|
||
| deprecated_kwargs = take_from | ||
| values = () | ||
| if not isinstance(args[0], tuple): | ||
| args = (args,) | ||
|
|
||
| for attribute, version_name, message in args: | ||
| if version.parse(version.parse(__version__).base_version) >= version.parse(version_name): | ||
| raise ValueError( | ||
| f"The deprecation tuple {(attribute, version_name, message)} should be removed since diffusers'" | ||
| f" version {__version__} is >= {version_name}" | ||
| ) | ||
|
|
||
| warning = None | ||
| if isinstance(deprecated_kwargs, dict) and attribute in deprecated_kwargs: | ||
| values += (deprecated_kwargs.pop(attribute),) | ||
| warning = f"The `{attribute}` argument is deprecated and will be removed in version {version_name}." | ||
| elif hasattr(deprecated_kwargs, attribute): | ||
| values += (getattr(deprecated_kwargs, attribute),) | ||
| warning = f"The `{attribute}` attribute is deprecated and will be removed in version {version_name}." | ||
| elif deprecated_kwargs is None: | ||
| warning = f"`{attribute}` is deprecated and will be removed in version {version_name}." | ||
|
|
||
| if warning is not None: | ||
| warning = warning + " " if standard_warn else "" | ||
| warnings.warn(warning + message, DeprecationWarning) | ||
|
|
||
| if isinstance(deprecated_kwargs, dict) and len(deprecated_kwargs) > 0: | ||
| call_frame = inspect.getouterframes(inspect.currentframe())[1] | ||
| filename = call_frame.filename | ||
| line_number = call_frame.lineno | ||
| function = call_frame.function | ||
| key, value = next(iter(deprecated_kwargs.items())) | ||
| raise TypeError(f"{function} in {filename} line {line_number-1} got an unexpected keyword argument `{key}`") | ||
|
|
||
| if len(values) == 0: | ||
| return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very cool!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Big +1
pcuenca
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is extremely cool, and so useful! It was very helpful to start by reading the tests.
Seeing that deprecate was inside testing_utils.py sounded a bit off, so I looked more closely to see what was there and realized that we would be breaking import diffusers when PyTorch is not installed. In any case, I believe that the semantics of the function call for moving it to another place.
| deprecated_offset = deprecate( | ||
| "offset", "0.5.0", "Please pass `steps_offset` to `__init__` instead.", take_from=kwargs | ||
| ) | ||
| offset = deprecated_offset or self.config.steps_offset |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great naming here, the intention is very clear!
src/diffusers/utils/testing_utils.py
Outdated
| def deprecate(*args, take_from: Optional[Union[Dict, Any]] = None, standard_warn=True): | ||
| from .. import __version__ | ||
|
|
||
| deprecated_kwargs = take_from | ||
| values = () | ||
| if not isinstance(args[0], tuple): | ||
| args = (args,) | ||
|
|
||
| for attribute, version_name, message in args: | ||
| if version.parse(version.parse(__version__).base_version) >= version.parse(version_name): | ||
| raise ValueError( | ||
| f"The deprecation tuple {(attribute, version_name, message)} should be removed since diffusers'" | ||
| f" version {__version__} is >= {version_name}" | ||
| ) | ||
|
|
||
| warning = None | ||
| if isinstance(deprecated_kwargs, dict) and attribute in deprecated_kwargs: | ||
| values += (deprecated_kwargs.pop(attribute),) | ||
| warning = f"The `{attribute}` argument is deprecated and will be removed in version {version_name}." | ||
| elif hasattr(deprecated_kwargs, attribute): | ||
| values += (getattr(deprecated_kwargs, attribute),) | ||
| warning = f"The `{attribute}` attribute is deprecated and will be removed in version {version_name}." | ||
| elif deprecated_kwargs is None: | ||
| warning = f"`{attribute}` is deprecated and will be removed in version {version_name}." | ||
|
|
||
| if warning is not None: | ||
| warning = warning + " " if standard_warn else "" | ||
| warnings.warn(warning + message, DeprecationWarning) | ||
|
|
||
| if isinstance(deprecated_kwargs, dict) and len(deprecated_kwargs) > 0: | ||
| call_frame = inspect.getouterframes(inspect.currentframe())[1] | ||
| filename = call_frame.filename | ||
| line_number = call_frame.lineno | ||
| function = call_frame.function | ||
| key, value = next(iter(deprecated_kwargs.items())) | ||
| raise TypeError(f"{function} in {filename} line {line_number-1} got an unexpected keyword argument `{key}`") | ||
|
|
||
| if len(values) == 0: | ||
| return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Big +1
| from typing import Union | ||
| from typing import Any, Dict, Optional, Union | ||
|
|
||
| import torch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this breaks import diffusers if PyTorch is not installed.
We should move deprecate to its own file. Not sure whether we should call it deprecate.py, deprecation_utils.py or something more general in case we need more functionality in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good! I'll add it to deprecation_utils.py
Regarding import torch, this should be done in another PR - this is unrelated to this PR (import torch was there before). We should definitely make sure though that the library doesn't break when torch is not installed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regarding
import torch, this should be done in another PR - this is unrelated to this PR (import torchwas there before).
Yes, but testing_utils was only imported when testing, that's really the difference (not the import). I should have made it clearer in my comment :)
…ggingface#659) * [Utils] Add deprecate function * up * up * uP * up * up * up * up * uP * up * fix * up * move to deprecation utils file * fix * fix * fix more
…ace#659) (This goes on to produce compilation errors, but one step at a time)
…ggingface#659) * [Utils] Add deprecate function * up * up * uP * up * up * up * up * uP * up * fix * up * move to deprecation utils file * fix * fix * fix more
Improved deprecation functionality
We are introducing multiple deprecation cycles already and currently are missing structure on how to handle this exactly and by adding
**kwargsto the scheduler config init we have lost functionality. More specifically:PNDMScheduler(num_inference_steps=5)nothing happens because it's swallowed by **kwargs. However we should, just as before [Pytorch] add dep. warning for pytorch schedulers #651 throw a TypeError in this case.=> This PR solves this by introducing a
deprecatefunction (which should be mainly used by maintainers) that automatically forces us to remove deprecated functionality correctly + solves 2. by throwing a type error. In addition it removes boiler plate code and should make it more efficient for us to deprecate things.The API of
deprecateis as follows:=> This forces us to remove this statement when version >= 0.7.0, gives a nice default error message and makes sure that
kwargscan only have deprecated args.Please take a look into the changes here and the tests to better understand all the functionality