def test_class_attributes_as_member_list(): class Foo: """ Class docstring. Attributes ---------- an_attribute Another description that is not used. """ @property def an_attribute(self): """Test attribute""" return None attr_doc = """:Attributes: :obj:`an_attribute <an_attribute>` Test attribute""" assert attr_doc in str(SphinxClassDoc(Foo)) assert "Another description" not in str(SphinxClassDoc(Foo)) attr_doc2 = """.. rubric:: Attributes .. autosummary:: :toctree: an_attribute""" cfg = dict(attributes_as_param_list=False) assert attr_doc2 in str(SphinxClassDoc(Foo, config=cfg)) assert "Another description" not in str(SphinxClassDoc(Foo, config=cfg))
def test_unknown_section(): doc_text = """ Test having an unknown section Mope ---- This should be ignored and warned about """ class BadSection(object): """Class with bad section. Nope ---- This class has a nope section. """ pass with warnings.catch_warnings(record=True) as w: NumpyDocString(doc_text) assert len(w) == 1 assert "Unknown section Mope" == str(w[0].message) with warnings.catch_warnings(record=True) as w: SphinxClassDoc(BadSection) assert len(w) == 1 assert_true('test_docscrape.test_unknown_section.<locals>.BadSection' in str(w[0].message) or 'test_docscrape.BadSection' in str(w[0].message))
def test_unknown_section(): doc_text = """ Test having an unknown section Mope ---- This should be ignored and warned about """ class BadSection: """Class with bad section. Nope ---- This class has a nope section. """ pass with pytest.warns(UserWarning, match="Unknown section Mope") as record: NumpyDocString(doc_text) assert len(record) == 1 # SphinxClassDoc has _obj.__name__ == "BadSection". Test that this is # included in the message msg_match = "Unknown section Nope in the docstring of BadSection" with pytest.warns(UserWarning, match=msg_match) as record: SphinxClassDoc(BadSection) assert len(record) == 1
def test_section_twice(): doc_text = """ Test having a section Notes twice Notes ----- See the next note for more information Notes ----- That should break... """ with pytest.raises(ValueError, match="The section Notes appears twice"): NumpyDocString(doc_text) # if we have a numpydoc object, we know where the error came from class Dummy: """ Dummy class. Notes ----- First note. Notes ----- Second note. """ def spam(self, a, b): """Spam\n\nSpam spam.""" pass def ham(self, c, d): """Cheese\n\nNo cheese.""" pass def dummy_func(arg): """ Dummy function. Notes ----- First note. Notes ----- Second note. """ with pytest.raises(ValueError, match="Dummy class"): SphinxClassDoc(Dummy) with pytest.raises(ValueError, match="dummy_func"): SphinxFunctionDoc(dummy_func)
def test_class_members_doc_sphinx(): class Foo: @property def x(self): """Test attribute""" return None doc = SphinxClassDoc(Foo, class_doc_txt) non_blank_line_by_line_compare( str(doc), """ Foo :Parameters: **f** : callable ``f(t, y, *f_args)`` Aaa. **jac** : callable ``jac(t, y, *jac_args)`` Bbb. .. rubric:: Examples For usage examples, see `ode`. .. rubric:: Attributes .. currentmodule:: test_docscrape.Foo .. autosummary:: :toctree: x ===== ========== **t** (float) Current time. **y** (ndarray) Current variable values. ===== ========== .. rubric:: Methods ===== ========== **a** **b** **c** ===== ========== """)
def test_autoclass(): cfg=dict(show_class_members=True, show_inherited_class_members=True) doc = SphinxClassDoc(str, ''' A top section before .. autoclass:: str ''', config=cfg) line_by_line_compare(str(doc), r''' A top section before .. autoclass:: str .. rubric:: Methods ''', 5)
def test_templated_sections(): doc = SphinxClassDoc(None, class_doc_txt, config={'template': jinja2.Template('{{examples}}\n{{parameters}}')}) line_by_line_compare(str(doc), """ .. rubric:: Examples For usage examples, see `ode`. :Parameters: f : callable ``f(t, y, *f_args)`` Aaa. jac : callable ``jac(t, y, *jac_args)`` Bbb. """)
def get_doc_object(obj, what=None, doc=None, config={}, builder=None): if what is None: if inspect.isclass(obj): what = "class" elif inspect.ismodule(obj): what = "module" elif isinstance(obj, Callable): what = "function" else: what = "object" if what == "class" and hasattr(obj, "run") and hasattr(obj, "audit"): what = "footing" template_dirs = [os.path.join(os.path.dirname(__file__), "templates")] if builder is not None: template_loader = BuiltinTemplateLoader() template_loader.init(builder, dirs=template_dirs) else: template_loader = FileSystemLoader(template_dirs) template_env = SandboxedEnvironment(loader=template_loader) config["template"] = template_env.get_template("footings_docstring.rst") if what == "footing": return SphinxFootingsDoc(obj, func_doc=SphinxFunctionDoc, doc=doc, config=config) elif what == "class": return SphinxClassDoc(obj, func_doc=SphinxFunctionDoc, doc=doc, config=config) elif what in ("function", "method"): return SphinxFunctionDoc(obj, doc=doc, config=config) else: if doc is None: doc = pydoc.getdoc(obj) return SphinxObjDoc(obj, doc, config=config)
def test_class_members_doc_sphinx(): doc = SphinxClassDoc(None, class_doc_txt) non_blank_line_by_line_compare( str(doc), """ Foo :Parameters: **f** : callable ``f(t, y, *f_args)`` Aaa. **jac** : callable ``jac(t, y, *jac_args)`` Bbb. .. rubric:: Examples For usage examples, see `ode`. .. rubric:: Attributes === ========== t (float) Current time. y (ndarray) Current variable values. === ========== .. rubric:: Methods === ========== a b c === ========== """)
def test_section_twice(): doc_text = """ Test having a section Notes twice Notes ----- See the next note for more information Notes ----- That should break... """ assert_raises(ValueError, NumpyDocString, doc_text) # if we have a numpydoc object, we know where the error came from class Dummy(object): """ Dummy class. Notes ----- First note. Notes ----- Second note. """ def spam(self, a, b): """Spam\n\nSpam spam.""" pass def ham(self, c, d): """Cheese\n\nNo cheese.""" pass def dummy_func(arg): """ Dummy function. Notes ----- First note. Notes ----- Second note. """ try: SphinxClassDoc(Dummy) except ValueError as e: # python 3 version or python 2 version assert_true("test_section_twice.<locals>.Dummy" in str(e) or 'test_docscrape.Dummy' in str(e)) try: SphinxFunctionDoc(dummy_func) except ValueError as e: # python 3 version or python 2 version assert_true("test_section_twice.<locals>.dummy_func" in str(e) or 'function dummy_func' in str(e))
def test_class_members_doc_sphinx(): class Foo: @property def an_attribute(self): """Test attribute""" return None @property def no_docstring(self): return None @property def no_docstring2(self): return None @property def multiline_sentence(self): """This is a sentence. It spans multiple lines.""" return None @property def midword_period(self): """The sentence for numpy.org.""" return None @property def no_period(self): """This does not have a period so we truncate its summary to the first linebreak Apparently. """ return None doc = SphinxClassDoc(Foo, class_doc_txt) line_by_line_compare( str(doc), """ Foo :Parameters: f : callable ``f(t, y, *f_args)`` Aaa. jac : callable ``jac(t, y, *jac_args)`` Bbb. .. rubric:: Examples For usage examples, see `ode`. :Attributes: t : float Current time. y : ndarray Current variable values. * hello * world :obj:`an_attribute <an_attribute>` : float Test attribute no_docstring : str But a description no_docstring2 : str .. :obj:`multiline_sentence <multiline_sentence>` This is a sentence. :obj:`midword_period <midword_period>` The sentence for numpy.org. :obj:`no_period <no_period>` This does not have a period .. rubric:: Methods ===== ========== **a** **b** **c** ===== ========== """)
def add_content(self, more_content, no_docstring=False): if self.doc_as_attr: super(GWpyClassDocumenter, self).add_content( more_content, no_docstring=no_docstring) else: name = safe_getattr(self.object, '__name__', None) if name: # create our own templating environment builder = self.env.app.builder or None template_dirs = [os.path.join(package_dir, 'ext', 'autosummary', 'templates')] if builder is not None: if builder.config.templates_path: template_dirs = (builder.config.templates_path + template_dirs) # allow the user to override the templates template_loader = BuiltinTemplateLoader() template_loader.init(builder, dirs=template_dirs) else: template_loader = FileSystemLoader(template_dirs) template_env = SandboxedEnvironment(loader=template_loader) template = template_env.get_template('autoclass/class.rst') def get_members(obj, typ, include_public=[]): items = [] want_all = (self.options.inherited_members or self.options.members is ALL) members = zip(*self.get_object_members(want_all)[1])[0] if self.options.exclude_members: members = [m for m in members if m not in self.options.exclude_members] for name in members: try: documenter = get_documenter( safe_getattr(obj, name), obj) except AttributeError: continue if documenter.objtype == typ: items.append(name) public = [x for x in items if x in include_public or not x.startswith('_')] return public, items ns = {} config = self.env.app.config npconfig = dict( use_plots=config.numpydoc_use_plots, show_class_members=config.numpydoc_show_class_members) ns['docstring'] = SphinxClassDoc(self.object, config=npconfig) ns['members'] = vars(self.object) ns['methods'], ns['all_methods'] = get_members(self.object, 'method', ['__init__']) ns['attributes'], ns['all_attributes'] = get_members( self.object, 'attribute') parts = self.fullname.split('.') mod_name, obj_name = '.'.join(parts[:-1]), parts[-1] ns['fullname'] = name ns['module'] = mod_name ns['objname'] = obj_name ns['name'] = parts[-1] for line in template.render(**ns).split('\n'): if line not in [None, 'None']: self.add_line(line, '<autodoc>') self.doc_as_attr = True