Skip to content

Commit b64efe3

Browse files
authored
Add doc_from util (#97)
1 parent dbb9311 commit b64efe3

File tree

2 files changed

+101
-0
lines changed

2 files changed

+101
-0
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from __future__ import annotations
2+
3+
from typing import Callable, Union
4+
5+
from typing_extensions import TypeAlias
6+
7+
DocSourceType: TypeAlias = Union[type, Callable]
8+
9+
10+
def doc_from(source: DocSourceType, **kwargs) -> Callable[[DocSourceType], DocSourceType]:
11+
def decorator(destination: DocSourceType) -> DocSourceType:
12+
assert type(source) is type(destination), \
13+
"docstring must be copied from class to class or from method to method"
14+
15+
doc = source.__doc__
16+
17+
assert doc, 'source docstring cannot be empty'
18+
assert not destination.__doc__, 'destination docstring must be empty'
19+
20+
if kwargs:
21+
doc = doc.format(**kwargs)
22+
23+
destination.__doc__ = doc
24+
25+
return destination
26+
27+
return decorator

tests/utils/test_doc.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
from __future__ import annotations
2+
3+
import pytest
4+
5+
from yandex_cloud_ml_sdk._utils.doc import doc_from
6+
7+
8+
def test_doc_from_class() -> None:
9+
class A:
10+
"""A doc"""
11+
12+
@doc_from(A)
13+
class B:
14+
def b(self):
15+
return 1
16+
17+
assert B.__doc__ == 'A doc'
18+
assert B().b() == 1
19+
20+
21+
def test_doc_from_method() -> None:
22+
class A:
23+
def a(self):
24+
"""a doc"""
25+
26+
class B:
27+
@doc_from(A.a)
28+
def b(self):
29+
return 1
30+
31+
assert B.b.__doc__ == 'a doc'
32+
assert B().b() == 1
33+
34+
35+
def test_doc_format() -> None:
36+
class A:
37+
"""A doc {placeholder}"""
38+
39+
@doc_from(A, placeholder="B")
40+
class B:
41+
def b(self):
42+
return 1
43+
44+
assert B.__doc__ == 'A doc B'
45+
46+
47+
def test_doc_wrong_types() -> None:
48+
class A:
49+
"""A doc"""
50+
51+
with pytest.raises(AssertionError):
52+
@doc_from(A)
53+
class B:
54+
"""B doc"""
55+
56+
assert B # type: ignore[truthy-function]
57+
58+
with pytest.raises(AssertionError):
59+
class B2:
60+
@doc_from(A)
61+
def b(self):
62+
return 1
63+
64+
assert B2 # type: ignore[truthy-function]
65+
66+
class A2:
67+
"""A2 doc {placeholder}"""
68+
69+
with pytest.raises(KeyError):
70+
@doc_from(A2, place="B")
71+
class B3:
72+
pass
73+
74+
assert B3 # type: ignore[truthy-function]

0 commit comments

Comments
 (0)