from importlib.machinery import SourceFileLoader
from typing import Tuple, Dict, Any, List
from urllib.parse import urljoin
+from distutils.version import LooseVersion
import jinja2
# TODO: why this is not None directly?
if annotation is inspect.Signature.empty: return None
- # To avoid getting <class 'foo.bar'> for classes (and getting foo.bar
+ # To avoid getting <class 'foo.bar'> for types (and getting foo.bar
# instead) but getting the actual type for types annotated with e.g.
- # List[int], we need to branch on isclass()
- if inspect.isclass(annotation): return extract_type(annotation)
- return str(annotation)
+ # List[int], we need to check if the annotation is actually from the
+ # typing module or it's directly a type. In Python 3.7 this worked with
+ # inspect.isclass(annotation), but on 3.6 that gives True for annotations
+ # as well and then we would get just List instead of List[int].
+ if annotation.__module__ == 'typing': return str(annotation)
+ return extract_type(annotation)
def render(config, template: str, page, env: jinja2.Environment):
template = env.get_template(template)
# to have in the docs, so filter them out. Uh... kinda ugly.
_filtered_builtin_functions = set([
('__delattr__', "Implement delattr(self, name)."),
- ('__dir__', "Default dir() implementation."),
('__eq__', "Return self==value."),
- ('__format__', "Default object formatter."),
('__ge__', "Return self>=value."),
('__getattribute__', "Return getattr(self, name)."),
('__gt__', "Return self>value."),
('__ne__', "Return self!=value."),
('__new__',
"Create and return a new object. See help(type) for accurate signature."),
- ('__reduce__', "Helper for pickle."),
- ('__reduce_ex__', "Helper for pickle."),
('__repr__', "Return repr(self)."),
('__setattr__', "Implement setattr(self, name, value)."),
- ('__sizeof__', "Size of object in memory, in bytes."),
('__str__', "Return str(self)."),
('__subclasshook__',
"Abstract classes can override this to customize issubclass().\n\n"
"overrides the normal algorithm (and the outcome is cached).\n")
])
+# Python 3.6 has slightly different docstrings than 3.7
+if LooseVersion(sys.version) >= LooseVersion("3.7"):
+ _filtered_builtin_functions.update({
+ ('__dir__', "Default dir() implementation."),
+ ('__format__', "Default object formatter."),
+ ('__reduce__', "Helper for pickle."),
+ ('__reduce_ex__', "Helper for pickle."),
+ ('__sizeof__', "Size of object in memory, in bytes."),
+ })
+else:
+ _filtered_builtin_functions.update({
+ ('__dir__', "__dir__() -> list\ndefault dir() implementation"),
+ ('__format__', "default object formatter"),
+ ('__reduce__', "helper for pickle"),
+ ('__reduce_ex__', "helper for pickle"),
+ ('__sizeof__', "__sizeof__() -> int\nsize of object in memory, in bytes")
+ })
+
_filtered_builtin_properties = set([
('__weakref__', "list of weak references to the object (if defined)")
])
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8" />
+ <title>math | 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>
+ math <span class="m-thin">module</span>
+ </h1>
+ <p>This module is always available. It provides access to the
+mathematical functions defined by the C standard.</p>
+ <div class="m-block m-default">
+ <h3>Contents</h3>
+ <ul>
+ <li>
+ Reference
+ <ul>
+ <li><a href="#functions">Functions</a></li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ <section id="functions">
+ <h2><a href="#functions">Functions</a></h2>
+ <dl class="m-doc">
+ <dt>
+ <span class="m-doc-wrap-bumper">def <a href="" class="m-doc-self">log</a>(</span><span class="m-doc-wrap">...)</span>
+ </dt>
+ <dd>log(x[, base])</dd>
+ </dl>
+ </section>
+ </div>
+ </div>
+ </div>
+</article></main>
+</body>
+</html>
# DEALINGS IN THE SOFTWARE.
#
+import math
import os
import sys
-import math
+import unittest
+
+from distutils.version import LooseVersion
from . import BaseTestCase
self.assertEqual(*self.actual_expected_contents('inspect_annotations.html'))
self.assertEqual(*self.actual_expected_contents('inspect_annotations.Foo.html'))
+ @unittest.skipUnless(LooseVersion(sys.version) >= LooseVersion('3.7'),
+ "signature with / for pow() is not present in 3.6")
def test_math(self):
# From math export only pow() so we have the verification easier, and
# in addition log() because it doesn't provide any signature metadata
assert not hasattr(math, '__all__')
self.assertEqual(*self.actual_expected_contents('math.html'))
+
+ @unittest.skipUnless(LooseVersion(sys.version) < LooseVersion('3.7'),
+ "docstring for log() is different in 3.7")
+ def test_math36(self):
+ # From math export only pow() so we have the verification easier, and
+ # in addition log() because it doesn't provide any signature metadata
+ assert not hasattr(math, '__all__')
+ math.__all__ = ['log']
+
+ self.run_python({
+ 'INPUT_MODULES': [math]
+ })
+
+ del math.__all__
+ assert not hasattr(math, '__all__')
+
+ self.assertEqual(*self.actual_expected_contents('math.html', 'math36.html'))