Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
efcf82f9
Unverified
Kaydet (Commit)
efcf82f9
authored
Ock 15, 2019
tarafından
Serhiy Storchaka
Kaydeden (comit)
GitHub
Ock 15, 2019
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
bpo-35619: Improve support of custom data descriptors in help() and pydoc. (GH-11366)
üst
6fe9c446
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
182 additions
and
46 deletions
+182
-46
pydoc.py
Lib/pydoc.py
+16
-36
test_pydoc.py
Lib/test/test_pydoc.py
+164
-10
2018-12-30-19-50-36.bpo-35619.ZRXdhy.rst
...S.d/next/Library/2018-12-30-19-50-36.bpo-35619.ZRXdhy.rst
+2
-0
No files found.
Lib/pydoc.py
Dosyayı görüntüle @
efcf82f9
...
...
@@ -137,12 +137,6 @@ def stripid(text):
# The behaviour of %p is implementation-dependent in terms of case.
return
_re_stripid
.
sub
(
r'\1'
,
text
)
def
_is_some_method
(
obj
):
return
(
inspect
.
isfunction
(
obj
)
or
inspect
.
ismethod
(
obj
)
or
inspect
.
isbuiltin
(
obj
)
or
inspect
.
ismethoddescriptor
(
obj
))
def
_is_bound_method
(
fn
):
"""
Returns True if fn is a bound method, regardless of whether
...
...
@@ -158,7 +152,7 @@ def _is_bound_method(fn):
def
allmethods
(
cl
):
methods
=
{}
for
key
,
value
in
inspect
.
getmembers
(
cl
,
_is_some_method
):
for
key
,
value
in
inspect
.
getmembers
(
cl
,
inspect
.
isroutine
):
methods
[
key
]
=
1
for
base
in
cl
.
__bases__
:
methods
.
update
(
allmethods
(
base
))
# all your base are belong to us
...
...
@@ -379,15 +373,13 @@ class Doc:
# identifies something in a way that pydoc itself has issues handling;
# think 'super' and how it is a descriptor (which raises the exception
# by lacking a __name__ attribute) and an instance.
if
inspect
.
isgetsetdescriptor
(
object
):
return
self
.
docdata
(
*
args
)
if
inspect
.
ismemberdescriptor
(
object
):
return
self
.
docdata
(
*
args
)
try
:
if
inspect
.
ismodule
(
object
):
return
self
.
docmodule
(
*
args
)
if
inspect
.
isclass
(
object
):
return
self
.
docclass
(
*
args
)
if
inspect
.
isroutine
(
object
):
return
self
.
docroutine
(
*
args
)
except
AttributeError
:
pass
if
i
sinstance
(
object
,
property
):
return
self
.
docproperty
(
*
args
)
if
i
nspect
.
isdatadescriptor
(
object
):
return
self
.
docdata
(
*
args
)
return
self
.
docother
(
*
args
)
def
fail
(
self
,
object
,
name
=
None
,
*
args
):
...
...
@@ -809,7 +801,7 @@ class HTMLDoc(Doc):
except
Exception
:
# Some descriptors may meet a failure in their __get__.
# (bug #1785)
push
(
self
.
_docdescriptor
(
name
,
valu
e
,
mod
))
push
(
self
.
docdata
(
value
,
nam
e
,
mod
))
else
:
push
(
self
.
document
(
value
,
name
,
mod
,
funcs
,
classes
,
mdict
,
object
))
...
...
@@ -822,7 +814,7 @@ class HTMLDoc(Doc):
hr
.
maybe
()
push
(
msg
)
for
name
,
kind
,
homecls
,
value
in
ok
:
push
(
self
.
_docdescriptor
(
name
,
valu
e
,
mod
))
push
(
self
.
docdata
(
value
,
nam
e
,
mod
))
return
attrs
def
spilldata
(
msg
,
attrs
,
predicate
):
...
...
@@ -994,32 +986,27 @@ class HTMLDoc(Doc):
doc
=
doc
and
'<dd><tt>
%
s</tt></dd>'
%
doc
return
'<dl><dt>
%
s</dt>
%
s</dl>
\n
'
%
(
decl
,
doc
)
def
_docdescriptor
(
self
,
name
,
value
,
mod
):
def
docdata
(
self
,
object
,
name
=
None
,
mod
=
None
,
cl
=
None
):
"""Produce html documentation for a data descriptor."""
results
=
[]
push
=
results
.
append
if
name
:
push
(
'<dl><dt><strong>
%
s</strong></dt>
\n
'
%
name
)
if
value
.
__doc__
is
not
None
:
doc
=
self
.
markup
(
getdoc
(
value
),
self
.
preformat
)
if
object
.
__doc__
is
not
None
:
doc
=
self
.
markup
(
getdoc
(
object
),
self
.
preformat
)
push
(
'<dd><tt>
%
s</tt></dd>
\n
'
%
doc
)
push
(
'</dl>
\n
'
)
return
''
.
join
(
results
)
def
docproperty
(
self
,
object
,
name
=
None
,
mod
=
None
,
cl
=
None
):
"""Produce html documentation for a property."""
return
self
.
_docdescriptor
(
name
,
object
,
mod
)
docproperty
=
docdata
def
docother
(
self
,
object
,
name
=
None
,
mod
=
None
,
*
ignored
):
"""Produce HTML documentation for a data object."""
lhs
=
name
and
'<strong>
%
s</strong> = '
%
name
or
''
return
lhs
+
self
.
repr
(
object
)
def
docdata
(
self
,
object
,
name
=
None
,
mod
=
None
,
cl
=
None
):
"""Produce html documentation for a data descriptor."""
return
self
.
_docdescriptor
(
name
,
object
,
mod
)
def
index
(
self
,
dir
,
shadowed
=
None
):
"""Generate an HTML index for a directory of modules."""
modpkgs
=
[]
...
...
@@ -1292,7 +1279,7 @@ location listed above.
except
Exception
:
# Some descriptors may meet a failure in their __get__.
# (bug #1785)
push
(
self
.
_docdescriptor
(
name
,
valu
e
,
mod
))
push
(
self
.
docdata
(
value
,
nam
e
,
mod
))
else
:
push
(
self
.
document
(
value
,
name
,
mod
,
object
))
...
...
@@ -1304,7 +1291,7 @@ location listed above.
hr
.
maybe
()
push
(
msg
)
for
name
,
kind
,
homecls
,
value
in
ok
:
push
(
self
.
_docdescriptor
(
name
,
valu
e
,
mod
))
push
(
self
.
docdata
(
value
,
nam
e
,
mod
))
return
attrs
def
spilldata
(
msg
,
attrs
,
predicate
):
...
...
@@ -1420,26 +1407,21 @@ location listed above.
doc
=
getdoc
(
object
)
or
''
return
decl
+
'
\n
'
+
(
doc
and
self
.
indent
(
doc
)
.
rstrip
()
+
'
\n
'
)
def
_docdescriptor
(
self
,
name
,
value
,
mod
):
def
docdata
(
self
,
object
,
name
=
None
,
mod
=
None
,
cl
=
None
):
"""Produce text documentation for a data descriptor."""
results
=
[]
push
=
results
.
append
if
name
:
push
(
self
.
bold
(
name
))
push
(
'
\n
'
)
doc
=
getdoc
(
value
)
or
''
doc
=
getdoc
(
object
)
or
''
if
doc
:
push
(
self
.
indent
(
doc
))
push
(
'
\n
'
)
return
''
.
join
(
results
)
def
docproperty
(
self
,
object
,
name
=
None
,
mod
=
None
,
cl
=
None
):
"""Produce text documentation for a property."""
return
self
.
_docdescriptor
(
name
,
object
,
mod
)
def
docdata
(
self
,
object
,
name
=
None
,
mod
=
None
,
cl
=
None
):
"""Produce text documentation for a data descriptor."""
return
self
.
_docdescriptor
(
name
,
object
,
mod
)
docproperty
=
docdata
def
docother
(
self
,
object
,
name
=
None
,
mod
=
None
,
parent
=
None
,
maxlen
=
None
,
doc
=
None
):
"""Produce text documentation for a data object."""
...
...
@@ -1673,9 +1655,7 @@ def render_doc(thing, title='Python Library Documentation: %s', forceload=0,
if
not
(
inspect
.
ismodule
(
object
)
or
inspect
.
isclass
(
object
)
or
inspect
.
isroutine
(
object
)
or
inspect
.
isgetsetdescriptor
(
object
)
or
inspect
.
ismemberdescriptor
(
object
)
or
isinstance
(
object
,
property
)):
inspect
.
isdatadescriptor
(
object
)):
# If the passed object is a piece of data or an instance,
# document its available methods instead of its value.
object
=
type
(
object
)
...
...
Lib/test/test_pydoc.py
Dosyayı görüntüle @
efcf82f9
...
...
@@ -743,15 +743,6 @@ class PydocDocTest(unittest.TestCase):
self
.
assertEqual
(
pydoc
.
splitdoc
(
example_string
),
(
'I Am A Doc'
,
'
\n
Here is my description'
))
def
test_is_object_or_method
(
self
):
doc
=
pydoc
.
Doc
()
# Bound Method
self
.
assertTrue
(
pydoc
.
_is_some_method
(
doc
.
fail
))
# Method Descriptor
self
.
assertTrue
(
pydoc
.
_is_some_method
(
int
.
__add__
))
# String
self
.
assertFalse
(
pydoc
.
_is_some_method
(
"I am not a method"
))
def
test_is_package_when_not_package
(
self
):
with
test
.
support
.
temp_cwd
()
as
test_dir
:
self
.
assertFalse
(
pydoc
.
ispackage
(
test_dir
))
...
...
@@ -1093,6 +1084,12 @@ class TestDescriptions(unittest.TestCase):
assert
len
(
lines
)
>=
2
return
lines
[
2
]
@staticmethod
def
_get_summary_lines
(
o
):
text
=
pydoc
.
plain
(
pydoc
.
render_doc
(
o
))
lines
=
text
.
split
(
'
\n
'
)
return
'
\n
'
.
join
(
lines
[
2
:])
# these should include "self"
def
test_unbound_python_method
(
self
):
self
.
assertEqual
(
self
.
_get_summary_line
(
textwrap
.
TextWrapper
.
wrap
),
...
...
@@ -1108,7 +1105,6 @@ class TestDescriptions(unittest.TestCase):
t
=
textwrap
.
TextWrapper
()
self
.
assertEqual
(
self
.
_get_summary_line
(
t
.
wrap
),
"wrap(text) method of textwrap.TextWrapper instance"
)
def
test_field_order_for_named_tuples
(
self
):
Person
=
namedtuple
(
'Person'
,
[
'nickname'
,
'firstname'
,
'agegroup'
])
s
=
pydoc
.
render_doc
(
Person
)
...
...
@@ -1138,6 +1134,164 @@ class TestDescriptions(unittest.TestCase):
self
.
assertEqual
(
self
.
_get_summary_line
(
os
.
stat
),
"stat(path, *, dir_fd=None, follow_symlinks=True)"
)
@requires_docstrings
def
test_staticmethod
(
self
):
class
X
:
@staticmethod
def
sm
(
x
,
y
):
'''A static method'''
...
self
.
assertEqual
(
self
.
_get_summary_lines
(
X
.
__dict__
[
'sm'
]),
"<staticmethod object>"
)
self
.
assertEqual
(
self
.
_get_summary_lines
(
X
.
sm
),
"""
\
sm(x, y)
A static method
"""
)
self
.
assertIn
(
"""
| Static methods defined here:
|
\x20\x20
| sm(x, y)
| A static method
"""
,
pydoc
.
plain
(
pydoc
.
render_doc
(
X
)))
@requires_docstrings
def
test_classmethod
(
self
):
class
X
:
@classmethod
def
cm
(
cls
,
x
):
'''A class method'''
...
self
.
assertEqual
(
self
.
_get_summary_lines
(
X
.
__dict__
[
'cm'
]),
"<classmethod object>"
)
self
.
assertEqual
(
self
.
_get_summary_lines
(
X
.
cm
),
"""
\
cm(x) method of builtins.type instance
A class method
"""
)
self
.
assertIn
(
"""
| Class methods defined here:
|
\x20\x20
| cm(x) from builtins.type
| A class method
"""
,
pydoc
.
plain
(
pydoc
.
render_doc
(
X
)))
@requires_docstrings
def
test_getset_descriptor
(
self
):
# Currently these attributes are implemented as getset descriptors
# in CPython.
self
.
assertEqual
(
self
.
_get_summary_line
(
int
.
numerator
),
"numerator"
)
self
.
assertEqual
(
self
.
_get_summary_line
(
float
.
real
),
"real"
)
self
.
assertEqual
(
self
.
_get_summary_line
(
Exception
.
args
),
"args"
)
self
.
assertEqual
(
self
.
_get_summary_line
(
memoryview
.
obj
),
"obj"
)
@requires_docstrings
def
test_member_descriptor
(
self
):
# Currently these attributes are implemented as member descriptors
# in CPython.
self
.
assertEqual
(
self
.
_get_summary_line
(
complex
.
real
),
"real"
)
self
.
assertEqual
(
self
.
_get_summary_line
(
range
.
start
),
"start"
)
self
.
assertEqual
(
self
.
_get_summary_line
(
slice
.
start
),
"start"
)
self
.
assertEqual
(
self
.
_get_summary_line
(
property
.
fget
),
"fget"
)
self
.
assertEqual
(
self
.
_get_summary_line
(
StopIteration
.
value
),
"value"
)
@requires_docstrings
def
test_slot_descriptor
(
self
):
class
Point
:
__slots__
=
'x'
,
'y'
self
.
assertEqual
(
self
.
_get_summary_line
(
Point
.
x
),
"x"
)
@requires_docstrings
def
test_dict_attr_descriptor
(
self
):
class
NS
:
pass
self
.
assertEqual
(
self
.
_get_summary_line
(
NS
.
__dict__
[
'__dict__'
]),
"__dict__"
)
@requires_docstrings
def
test_structseq_member_descriptor
(
self
):
self
.
assertEqual
(
self
.
_get_summary_line
(
type
(
sys
.
hash_info
)
.
width
),
"width"
)
self
.
assertEqual
(
self
.
_get_summary_line
(
type
(
sys
.
flags
)
.
debug
),
"debug"
)
self
.
assertEqual
(
self
.
_get_summary_line
(
type
(
sys
.
version_info
)
.
major
),
"major"
)
self
.
assertEqual
(
self
.
_get_summary_line
(
type
(
sys
.
float_info
)
.
max
),
"max"
)
@requires_docstrings
def
test_namedtuple_field_descriptor
(
self
):
Box
=
namedtuple
(
'Box'
,
(
'width'
,
'height'
))
self
.
assertEqual
(
self
.
_get_summary_lines
(
Box
.
width
),
"""
\
Alias for field number 0
"""
)
@requires_docstrings
def
test_property
(
self
):
class
Rect
:
@property
def
area
(
self
):
'''Area of the rect'''
return
self
.
w
*
self
.
h
self
.
assertEqual
(
self
.
_get_summary_lines
(
Rect
.
area
),
"""
\
Area of the rect
"""
)
self
.
assertIn
(
"""
| area
| Area of the rect
"""
,
pydoc
.
plain
(
pydoc
.
render_doc
(
Rect
)))
@requires_docstrings
def
test_custom_non_data_descriptor
(
self
):
class
Descr
:
def
__get__
(
self
,
obj
,
cls
):
if
obj
is
None
:
return
self
return
42
class
X
:
attr
=
Descr
()
text
=
pydoc
.
plain
(
pydoc
.
render_doc
(
X
.
attr
))
self
.
assertEqual
(
self
.
_get_summary_lines
(
X
.
attr
),
"""
\
<test.test_pydoc.TestDescriptions.test_custom_non_data_descriptor.<locals>.Descr object>"""
)
X
.
attr
.
__doc__
=
'Custom descriptor'
self
.
assertEqual
(
self
.
_get_summary_lines
(
X
.
attr
),
"""
\
<test.test_pydoc.TestDescriptions.test_custom_non_data_descriptor.<locals>.Descr object>"""
)
X
.
attr
.
__name__
=
'foo'
self
.
assertEqual
(
self
.
_get_summary_lines
(
X
.
attr
),
"""
\
foo(...)
Custom descriptor
"""
)
@requires_docstrings
def
test_custom_data_descriptor
(
self
):
class
Descr
:
def
__get__
(
self
,
obj
,
cls
):
if
obj
is
None
:
return
self
return
42
def
__set__
(
self
,
obj
,
cls
):
1
/
0
class
X
:
attr
=
Descr
()
text
=
pydoc
.
plain
(
pydoc
.
render_doc
(
X
.
attr
))
self
.
assertEqual
(
self
.
_get_summary_lines
(
X
.
attr
),
""
)
X
.
attr
.
__doc__
=
'Custom descriptor'
text
=
pydoc
.
plain
(
pydoc
.
render_doc
(
X
.
attr
))
self
.
assertEqual
(
self
.
_get_summary_lines
(
X
.
attr
),
"""
\
Custom descriptor
"""
)
X
.
attr
.
__name__
=
'foo'
text
=
pydoc
.
plain
(
pydoc
.
render_doc
(
X
.
attr
))
self
.
assertEqual
(
self
.
_get_summary_lines
(
X
.
attr
),
"""
\
foo
Custom descriptor
"""
)
class
PydocServerTest
(
unittest
.
TestCase
):
"""Tests for pydoc._start_server"""
...
...
Misc/NEWS.d/next/Library/2018-12-30-19-50-36.bpo-35619.ZRXdhy.rst
0 → 100644
Dosyayı görüntüle @
efcf82f9
Improved support of custom data descriptors in :func:`help` and
:mod:`pydoc`.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment