Skip to content

Commit e76130c

Browse files
Zain Hudafacebook-github-bot
authored andcommitted
add experimental decorator
Summary: adding a simple decorator to allow us to flag APIs as experimental for users, optional flags to specify additional information such as package versions and dates usage: ```python experimental def f(x): ... ``` logs will show: ``` function is *experimental* and may change or be removed without notice. ``` Differential Revision: D75014138
1 parent bb90344 commit e76130c

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

torchrec/utils/__init__.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Copyright (c) Meta Platforms, Inc. and affiliates.
2+
# All rights reserved.
3+
#
4+
# This source code is licensed under the BSD-style license found in the
5+
# LICENSE file in the root directory of this source tree.
6+
7+
# pyre-strict
8+
9+
from . import experimental # noqa

torchrec/utils/experimental.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) Meta Platforms, Inc. and affiliates.
3+
# All rights reserved.
4+
#
5+
# This source code is licensed under the BSD-style license found in the
6+
# LICENSE file in the root directory of this source tree.
7+
8+
# pyre-strict
9+
from __future__ import annotations
10+
11+
import functools
12+
import warnings
13+
from typing import Any, Callable, overload, ParamSpec, Type, TypeVar, Union
14+
15+
P = ParamSpec("P")
16+
R = TypeVar("R")
17+
T = TypeVar("T")
18+
19+
20+
@overload
21+
def experimental(
22+
obj: Callable[P, R],
23+
feature: str | None = None,
24+
since: str | None = None,
25+
) -> Callable[P, R]: ...
26+
27+
28+
@overload
29+
def experimental(
30+
obj: Type[T],
31+
feature: str | None = None,
32+
since: str | None = None,
33+
) -> Type[T]: ...
34+
35+
36+
def experimental(
37+
obj: Union[Callable[P, R], Type[T]],
38+
feature: str | None = None,
39+
since: str | None = None,
40+
) -> Union[Callable[P, R], Type[T]]:
41+
tag: str = feature or obj.__name__ # pyre-ignore[16]
42+
message_parts: list[str] = [
43+
f"`{tag}` is *experimental* and may change or be removed without notice."
44+
]
45+
if since:
46+
message_parts.insert(0, f"[since {since}]")
47+
warning_message: str = " ".join(message_parts)
48+
49+
@functools.lru_cache(maxsize=1)
50+
def _issue_warning() -> None:
51+
warnings.warn(warning_message, UserWarning, stacklevel=3)
52+
53+
if isinstance(obj, type):
54+
orig_init: Callable[..., None] = obj.__init__
55+
56+
@functools.wraps(orig_init)
57+
def new_init(self, *args: Any, **kwargs: Any) -> Any: # pyre-ignore[3]
58+
_issue_warning()
59+
return orig_init(self, *args, **kwargs)
60+
61+
obj.__init__ = new_init
62+
return obj
63+
else:
64+
65+
@functools.wraps(obj)
66+
def wrapper(*args: Any, **kwargs: Any) -> Any: # pyre-ignore[3]
67+
_issue_warning()
68+
return obj(*args, **kwargs) # pyre-ignore[29]
69+
70+
return wrapper

0 commit comments

Comments
 (0)