Not ideal (as the resulting docs are confusing), but at least something.
Creating two copies of the same class could easily lead to infinite
recursion in code paths that don't expect it, so not doing that.
def crawl_class(state: State, path: List[str], class_):
assert inspect.isclass(class_)
- # TODO: if this fires, it means there's a class duplicated in more than one
- # __all__ (or it gets picked up implicitly and then in __all__) -- how to
- # handle gracefully?
- assert id(class_) not in state.crawled
+ # If this fires, it means there's a class duplicated in more than one
+ # __all__ (or it gets picked up implicitly and then in __all__). It usually
+ # means there's a mess in imports, unfortunately this is more common than
+ # one would hope so we can't just assert.
+ if id(class_) in state.crawled:
+ for name, previous_entry in state.name_map.items():
+ if previous_entry.object == class_: break
+ else: assert False
+ logging.error("Class %s previously found in %s, only one occurence will be chosen. Ensure each class is exposed only in a single module for generating correct documentation.", '.'.join(path), '.'.join(previous_entry.path))
+ state.name_map['.'.join(path)] = previous_entry
+ return
+
state.crawled.add(id(class_))
class_entry = Empty()
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8" />
+ <title>inspect_duplicate_class.Bar | My Python Project</title>
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
+ <link rel="stylesheet" href="m-dark+documentation.compiled.css" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</head>
+<body>
+<header><nav id="navigation">
+ <div class="m-container">
+ <div class="m-row">
+ <a href="index.html" id="m-navbar-brand" class="m-col-t-8 m-col-m-none m-left-m">My Python Project</a>
+ </div>
+ </div>
+</nav></header>
+<main><article>
+ <div class="m-container m-container-inflatable">
+ <div class="m-row">
+ <div class="m-col-l-10 m-push-l-1">
+ <h1>
+ <span class="m-breadcrumb"><a href="inspect_duplicate_class.html">inspect_duplicate_class</a>.<wbr/></span>Bar <span class="m-thin">class</span>
+ </h1>
+ <p>A class present in two modules.</p>
+ </div>
+ </div>
+ </div>
+</article></main>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8" />
+ <title>inspect_duplicate_class | My Python Project</title>
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
+ <link rel="stylesheet" href="m-dark+documentation.compiled.css" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</head>
+<body>
+<header><nav id="navigation">
+ <div class="m-container">
+ <div class="m-row">
+ <a href="index.html" id="m-navbar-brand" class="m-col-t-8 m-col-m-none m-left-m">My Python Project</a>
+ </div>
+ </div>
+</nav></header>
+<main><article>
+ <div class="m-container m-container-inflatable">
+ <div class="m-row">
+ <div class="m-col-l-10 m-push-l-1">
+ <h1>
+ inspect_duplicate_class <span class="m-thin">module</span>
+ </h1>
+ <div class="m-block m-default">
+ <h3>Contents</h3>
+ <ul>
+ <li>
+ Reference
+ <ul>
+ <li><a href="#packages">Modules</a></li>
+ <li><a href="#classes">Classes</a></li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ <section id="namespaces">
+ <h2><a href="#namespaces">Modules</a></h2>
+ <dl class="m-doc">
+ <dt>module <a href="inspect_duplicate_class.sub.html" class="m-doc">sub</a></dt>
+ <dd>A submodule.</dd>
+ </dl>
+ </section>
+ <section id="classes">
+ <h2><a href="#classes">Classes</a></h2>
+ <dl class="m-doc">
+ <dt>class <a href="inspect_duplicate_class.Bar.html" class="m-doc">Bar</a></dt>
+ <dd>A class present in two modules.</dd>
+ </dl>
+ </section>
+ </div>
+ </div>
+ </div>
+</article></main>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8" />
+ <title>inspect_duplicate_class.sub | My Python Project</title>
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
+ <link rel="stylesheet" href="m-dark+documentation.compiled.css" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</head>
+<body>
+<header><nav id="navigation">
+ <div class="m-container">
+ <div class="m-row">
+ <a href="index.html" id="m-navbar-brand" class="m-col-t-8 m-col-m-none m-left-m">My Python Project</a>
+ </div>
+ </div>
+</nav></header>
+<main><article>
+ <div class="m-container m-container-inflatable">
+ <div class="m-row">
+ <div class="m-col-l-10 m-push-l-1">
+ <h1>
+ <span class="m-breadcrumb"><a href="inspect_duplicate_class.html">inspect_duplicate_class</a>.<wbr/></span>sub <span class="m-thin">module</span>
+ </h1>
+ <p>A submodule.</p>
+ <div class="m-block m-default">
+ <h3>Contents</h3>
+ <ul>
+ <li>
+ Reference
+ <ul>
+ <li><a href="#classes">Classes</a></li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ <section id="classes">
+ <h2><a href="#classes">Classes</a></h2>
+ <dl class="m-doc">
+ <dt>class <a href="inspect_duplicate_class.Bar.html" class="m-doc">Bar</a></dt>
+ <dd>A class present in two modules.</dd>
+ </dl>
+ </section>
+ </div>
+ </div>
+ </div>
+</article></main>
+</body>
+</html>
--- /dev/null
+
+from .sub import Foo as Bar
+
+__all__ = ['sub', 'Bar']
--- /dev/null
+"""A submodule."""
+
+class Foo:
+ """A class present in two modules."""
+ pass
def test(self):
self.run_python({})
self.assertEqual(*self.actual_expected_contents('inspect_value_formatting.html'))
+
+class DuplicateClass(BaseInspectTestCase):
+ def test(self):
+ self.run_python({})
+ self.assertEqual(*self.actual_expected_contents('inspect_duplicate_class.html'))
+ self.assertEqual(*self.actual_expected_contents('inspect_duplicate_class.sub.html'))
+ self.assertEqual(*self.actual_expected_contents('inspect_duplicate_class.Bar.html'))