Skip to content

gh-125633: Add function ispackage to stdlib inspect #125634

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

Merged
merged 14 commits into from
Oct 27, 2024
Merged
5 changes: 5 additions & 0 deletions Doc/library/inspect.rst
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,11 @@ attributes (see :ref:`import-mod-attrs` for module attributes):
Return ``True`` if the object is a bound method written in Python.


.. function:: ispackage(object)

Return ``True`` if the object is a package.


.. function:: isfunction(object)

Return ``True`` if the object is a Python function, which includes functions
Expand Down
4 changes: 4 additions & 0 deletions Doc/whatsnew/3.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,10 @@ inspect
If true, string :term:`annotations <annotation>` are displayed without surrounding quotes.
(Contributed by Jelle Zijlstra in :gh:`101552`.)

* Add function :func:`inspect.ispackage` to determine whether an object is a
package or not.
(Contributed by Zhikang Yan in :gh:`125634`.)


json
----
Expand Down
13 changes: 10 additions & 3 deletions Lib/inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@

Here are some of the useful functions provided by this module:

ismodule(), isclass(), ismethod(), isfunction(), isgeneratorfunction(),
isgenerator(), istraceback(), isframe(), iscode(), isbuiltin(),
isroutine() - check object types
ismodule(), isclass(), ismethod(), ispackage(), isfunction(),
isgeneratorfunction(), isgenerator(), istraceback(), isframe(),
iscode(), isbuiltin(), isroutine() - check object types
getmembers() - get members of an object that satisfy a given condition

getfile(), getsourcefile(), getsource() - find an object's source code
Expand Down Expand Up @@ -128,6 +128,7 @@
"ismethoddescriptor",
"ismethodwrapper",
"ismodule",
"ispackage",
"isroutine",
"istraceback",
"markcoroutinefunction",
Expand Down Expand Up @@ -186,6 +187,12 @@ def ismethod(object):
"""Return true if the object is an instance method."""
return isinstance(object, types.MethodType)

def ispackage(object):
"""Return true if the object is a package."""
if ismodule(object) and object.__spec__ is not None:
return object.__spec__.parent == object.__spec__.name
return False

def ismethoddescriptor(object):
"""Return true if the object is a method descriptor.

Expand Down
Empty file.
8 changes: 6 additions & 2 deletions Lib/test/test_inspect/test_inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,14 @@

from test.test_inspect import inspect_fodder as mod
from test.test_inspect import inspect_fodder2 as mod2
from test.test_inspect import inspect_simple_pkg as pkg
from test.test_inspect import inspect_stringized_annotations
from test.test_inspect import inspect_deferred_annotations


# Functions tested in this suite:
# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
# isbuiltin, isroutine, isgenerator, ispackage, isgeneratorfunction, getmembers,
# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
# getclasstree, getargvalues, formatargvalues, currentframe,
# stack, trace, ismethoddescriptor, isdatadescriptor, ismethodwrapper
Expand Down Expand Up @@ -105,7 +106,7 @@ def unsorted_keyword_only_parameters_fn(*, throw, out, the, baby, with_,
class IsTestBase(unittest.TestCase):
predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
inspect.isframe, inspect.isfunction, inspect.ismethod,
inspect.ismodule, inspect.istraceback,
inspect.ismodule, inspect.istraceback, inspect.ispackage,
inspect.isgenerator, inspect.isgeneratorfunction,
inspect.iscoroutine, inspect.iscoroutinefunction,
inspect.isasyncgen, inspect.isasyncgenfunction,
Expand All @@ -121,6 +122,8 @@ def istest(self, predicate, exp):
predicate == inspect.iscoroutinefunction) and \
other == inspect.isfunction:
continue
if predicate == inspect.ispackage and other == inspect.ismodule:
continue
self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))

def test__all__(self):
Expand Down Expand Up @@ -176,6 +179,7 @@ def test_excluding_predicates(self):
self.istest(inspect.ismethod, 'git.argue')
self.istest(inspect.ismethod, 'mod.custom_method')
self.istest(inspect.ismodule, 'mod')
self.istest(inspect.ispackage, 'pkg')
self.istest(inspect.ismethoddescriptor, 'int.__add__')
self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
self.istest(inspect.isgenerator, '(x for x in range(2))')
Expand Down
1 change: 1 addition & 0 deletions Makefile.pre.in
Original file line number Diff line number Diff line change
Expand Up @@ -2498,6 +2498,7 @@ TESTSUBDIRS= idlelib/idle_test \
test/test_importlib/resources \
test/test_importlib/source \
test/test_inspect \
test/test_inspect/inspect_simple_pkg \
test/test_interpreters \
test/test_json \
test/test_module \
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Adding function :func:`inspect.ispackage` to determine whether an object is a
package or not.
Loading