Modernize extension
- update dependencies - use tox for testing - use type hints - use pathlib and ipaddress from standard library instead of path and ipcalc - fix Sphinx deprecation warnings
This commit is contained in:
		
							parent
							
								
									c721d1bf9c
								
							
						
					
					
						commit
						7c675a6fdb
					
				
					 13 changed files with 801 additions and 465 deletions
				
			
		
							
								
								
									
										2
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -5,6 +5,8 @@ | ||||||
| .coverage | .coverage | ||||||
| .idea/ | .idea/ | ||||||
| .ropeproject/ | .ropeproject/ | ||||||
|  | /.*_cache/ | ||||||
|  | /.python-version | ||||||
| /.tox/ | /.tox/ | ||||||
| __pycache__/ | __pycache__/ | ||||||
| _build/ | _build/ | ||||||
|  |  | ||||||
|  | @ -5,6 +5,9 @@ unreleased | ||||||
| ---------- | ---------- | ||||||
| 
 | 
 | ||||||
| * add development documentation in development.rst | * add development documentation in development.rst | ||||||
|  | * use tox as test runner | ||||||
|  | * add type annotations | ||||||
|  | * fix Sphinx 6 deprecation warnings | ||||||
| 
 | 
 | ||||||
| 0.5.1 - 2021-09-04 | 0.5.1 - 2021-09-04 | ||||||
| ------------------ | ------------------ | ||||||
|  |  | ||||||
|  | @ -11,7 +11,7 @@ Running test | ||||||
| To install all dependencies and run the tests use:: | To install all dependencies and run the tests use:: | ||||||
| 
 | 
 | ||||||
|     pipenv install --dev |     pipenv install --dev | ||||||
|     pipenv run pytest |     pipenv run tox | ||||||
| 
 | 
 | ||||||
| Release a new version | Release a new version | ||||||
| --------------------- | --------------------- | ||||||
|  | @ -31,7 +31,7 @@ Start by deciding the new release number and perform the following steps: | ||||||
|   shortlog <previous_tag>..HEAD`` could help to create a good release tag |   shortlog <previous_tag>..HEAD`` could help to create a good release tag | ||||||
|   message) :: |   message) :: | ||||||
| 
 | 
 | ||||||
|      git tag -s -a 0.5.1 |      git tag -s -a <version> | ||||||
| 
 | 
 | ||||||
| * build the release artifacts :: | * build the release artifacts :: | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										7
									
								
								Pipfile
									
										
									
									
									
								
							
							
						
						
									
										7
									
								
								Pipfile
									
										
									
									
									
								
							|  | @ -6,12 +6,11 @@ verify_ssl = true | ||||||
| [dev-packages] | [dev-packages] | ||||||
| coverage = "*" | coverage = "*" | ||||||
| twine = "*" | twine = "*" | ||||||
| path = "*" |  | ||||||
| pytest = "*" | pytest = "*" | ||||||
|  | tox = "*" | ||||||
|  | black = "*" | ||||||
| 
 | 
 | ||||||
| [packages] | [packages] | ||||||
| jandd-sphinxext-ip = { path = ".", editable = true } | jandd-sphinxext-ip = { path = ".", editable = true } | ||||||
| Sphinx = ">=4" | Sphinx = ">=5" | ||||||
| docutils = "*" | docutils = "*" | ||||||
| six = "*" |  | ||||||
| ipcalc = ">=1.99" |  | ||||||
|  |  | ||||||
							
								
								
									
										1027
									
								
								Pipfile.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										1027
									
								
								Pipfile.lock
									
										
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -1 +0,0 @@ | ||||||
| __import__("pkg_resources").declare_namespace(__name__) |  | ||||||
|  | @ -1 +0,0 @@ | ||||||
| __import__("pkg_resources").declare_namespace(__name__) |  | ||||||
|  | @ -10,13 +10,15 @@ | ||||||
| """ | """ | ||||||
| __version__ = "0.5.1" | __version__ = "0.5.1" | ||||||
| 
 | 
 | ||||||
|  | import ipaddress | ||||||
| from collections import defaultdict | from collections import defaultdict | ||||||
| from typing import Iterable, List, Optional, Tuple | from typing import Iterable, List, Optional, Tuple, Any, cast | ||||||
| 
 | 
 | ||||||
| from docutils import nodes | from docutils import nodes | ||||||
| from ipcalc import IP, Network | from docutils.nodes import Element | ||||||
| from sphinx import addnodes | from sphinx import addnodes | ||||||
| from sphinx.addnodes import desc_signature, pending_xref | from sphinx.addnodes import desc_signature, pending_xref | ||||||
|  | from sphinx.application import Sphinx | ||||||
| from sphinx.builders import Builder | from sphinx.builders import Builder | ||||||
| from sphinx.directives import ObjectDescription, T | from sphinx.directives import ObjectDescription, T | ||||||
| from sphinx.domains import Domain, ObjType | from sphinx.domains import Domain, ObjType | ||||||
|  | @ -39,32 +41,32 @@ class IPRangeDirective(ObjectDescription): | ||||||
| 
 | 
 | ||||||
|     has_content = True |     has_content = True | ||||||
|     required_arguments = 1 |     required_arguments = 1 | ||||||
|     title_prefix = None |     title_prefix: str = "" | ||||||
|     range_spec = None |     range_spec: str = "" | ||||||
| 
 | 
 | ||||||
|     def get_title_prefix(self) -> str: |     def get_title_prefix(self) -> str: | ||||||
|         if self.title_prefix is None: |  | ||||||
|             raise NotImplemented("subclasses must set title_prefix") |  | ||||||
|         return self.title_prefix |         return self.title_prefix | ||||||
| 
 | 
 | ||||||
|     def handle_signature(self, sig: str, signode: desc_signature) -> T: |     def handle_signature(self, sig: str, sig_node: desc_signature) -> str: | ||||||
|         signode += addnodes.desc_name(text="{} {}".format(self.get_title_prefix(), sig)) |         sig_node += addnodes.desc_name( | ||||||
|  |             text="{} {}".format(self.get_title_prefix(), sig) | ||||||
|  |         ) | ||||||
|         self.range_spec = sig |         self.range_spec = sig | ||||||
|         return sig |         return sig | ||||||
| 
 | 
 | ||||||
|     def transform_content(self, contentnode: addnodes.desc_content) -> None: |     def transform_content(self, content_node: addnodes.desc_content) -> None: | ||||||
|         ip_range_node = ip_range() |         ip_range_node = ip_range() | ||||||
|         ip_range_node["range_spec"] = self.range_spec |         ip_range_node["range_spec"] = self.range_spec | ||||||
|         contentnode += ip_range_node |         content_node += ip_range_node | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class IPV4RangeDirective(IPRangeDirective): | class IPV4RangeDirective(IPRangeDirective): | ||||||
|     title_prefix = _("IPv4 range") |     title_prefix = _("IPv4 range") | ||||||
| 
 | 
 | ||||||
|     def add_target_and_index(self, name: T, sig: str, signode: desc_signature) -> None: |     def add_target_and_index(self, name: T, sig: str, sig_node: desc_signature) -> None: | ||||||
|         anchor = "ip-ipv4range-{0}".format(sig) |         anchor = "ip-ipv4range-{0}".format(sig) | ||||||
|         signode["ids"].append(anchor) |         sig_node["ids"].append(anchor) | ||||||
|         ips = self.env.get_domain("ip") |         ips = cast(IPDomain, self.env.get_domain("ip")) | ||||||
|         ips.add_ip4_range(sig) |         ips.add_ip4_range(sig) | ||||||
|         idx_text = "{}; {}".format(self.title_prefix, name) |         idx_text = "{}; {}".format(self.title_prefix, name) | ||||||
|         self.indexnode["entries"] = [ |         self.indexnode["entries"] = [ | ||||||
|  | @ -78,7 +80,7 @@ class IPV6RangeDirective(IPRangeDirective): | ||||||
|     def add_target_and_index(self, name: T, sig: str, signode: desc_signature) -> None: |     def add_target_and_index(self, name: T, sig: str, signode: desc_signature) -> None: | ||||||
|         anchor = "ip-ipv6range-{0}".format(sig) |         anchor = "ip-ipv6range-{0}".format(sig) | ||||||
|         signode["ids"].append(anchor) |         signode["ids"].append(anchor) | ||||||
|         ips = self.env.get_domain("ip") |         ips = cast(IPDomain, self.env.get_domain("ip")) | ||||||
|         ips.add_ip6_range(sig) |         ips.add_ip6_range(sig) | ||||||
|         idx_text = "{}; {}".format(self.title_prefix, name) |         idx_text = "{}; {}".format(self.title_prefix, name) | ||||||
|         self.indexnode["entries"] = [ |         self.indexnode["entries"] = [ | ||||||
|  | @ -101,7 +103,7 @@ class IPXRefRole(XRefRole): | ||||||
|     ) -> Tuple[str, str]: |     ) -> Tuple[str, str]: | ||||||
|         refnode.attributes.update(env.ref_context) |         refnode.attributes.update(env.ref_context) | ||||||
| 
 | 
 | ||||||
|         ips = env.get_domain("ip") |         ips = cast(IPDomain, env.get_domain("ip")) | ||||||
|         if refnode["reftype"] == "v4": |         if refnode["reftype"] == "v4": | ||||||
|             ips.add_ip4_address_reference(target) |             ips.add_ip4_address_reference(target) | ||||||
|         elif refnode["reftype"] == "v6": |         elif refnode["reftype"] == "v6": | ||||||
|  | @ -122,7 +124,7 @@ class IPXRefRole(XRefRole): | ||||||
|     ) -> Tuple[List[nodes.Node], List[nodes.system_message]]: |     ) -> Tuple[List[nodes.Node], List[nodes.system_message]]: | ||||||
|         node_list, message = super().result_nodes(document, env, node, is_ref) |         node_list, message = super().result_nodes(document, env, node, is_ref) | ||||||
| 
 | 
 | ||||||
|         ip = env.get_domain("ip") |         ip = cast(IPDomain, env.get_domain("ip")) | ||||||
|         if self.reftype in ["v4", "v6"] and self.target not in ip.data["ip_dict"]: |         if self.reftype in ["v4", "v6"] and self.target not in ip.data["ip_dict"]: | ||||||
|             return node_list, message |             return node_list, message | ||||||
|         if ( |         if ( | ||||||
|  | @ -138,7 +140,7 @@ class IPXRefRole(XRefRole): | ||||||
|             ip.add_ip_address_anchor(self.target, env.docname, target_id) |             ip.add_ip_address_anchor(self.target, env.docname, target_id) | ||||||
| 
 | 
 | ||||||
|         target_node = nodes.target("", "", ids=[target_id]) |         target_node = nodes.target("", "", ids=[target_id]) | ||||||
|         doc_title = next(d for d in document.traverse(nodes.title)).astext() |         doc_title = next(d for d in document.findall(nodes.title)).astext() | ||||||
| 
 | 
 | ||||||
|         node_text = node.astext() |         node_text = node.astext() | ||||||
| 
 | 
 | ||||||
|  | @ -157,6 +159,25 @@ class IPXRefRole(XRefRole): | ||||||
| class IPDomain(Domain): | class IPDomain(Domain): | ||||||
|     """Custom domain for IP addresses and ranges.""" |     """Custom domain for IP addresses and ranges.""" | ||||||
| 
 | 
 | ||||||
|  |     def merge_domaindata(self, docnames: list[str], otherdata: dict) -> None: | ||||||
|  |         # TODO: implement merge_domaindata | ||||||
|  |         print( | ||||||
|  |             f"merge_domaindata called for docnames: {docnames} with otherdata: {otherdata}" | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |     def resolve_any_xref( | ||||||
|  |         self, | ||||||
|  |         env: BuildEnvironment, | ||||||
|  |         fromdocname: str, | ||||||
|  |         builder: Builder, | ||||||
|  |         target: str, | ||||||
|  |         node: pending_xref, | ||||||
|  |         contnode: Element, | ||||||
|  |     ) -> list[tuple[str, Element]]: | ||||||
|  |         # TODO: implement resolve_any_xref | ||||||
|  |         print("resolve_any_xref called") | ||||||
|  |         return [] | ||||||
|  | 
 | ||||||
|     name = "ip" |     name = "ip" | ||||||
|     label = "IP addresses and ranges." |     label = "IP addresses and ranges." | ||||||
| 
 | 
 | ||||||
|  | @ -194,23 +215,23 @@ class IPDomain(Domain): | ||||||
|         for obj in self.data["range_nodes"]: |         for obj in self.data["range_nodes"]: | ||||||
|             yield obj |             yield obj | ||||||
| 
 | 
 | ||||||
|     def add_ip4_range(self, sig: desc_signature): |     def add_ip4_range(self, sig: str): | ||||||
|         logger.debug("add_ip4_range: %s", sig) |         logger.debug("add_ip4_range: %s", sig) | ||||||
|         self._add_ip_range("v4", sig) |         self._add_ip_range("v4", sig) | ||||||
| 
 | 
 | ||||||
|     def add_ip6_range(self, sig: desc_signature): |     def add_ip6_range(self, sig: str): | ||||||
|         logger.debug("add_ip6_range: %s", sig) |         logger.debug("add_ip6_range: %s", sig) | ||||||
|         self._add_ip_range("v6", sig) |         self._add_ip_range("v6", sig) | ||||||
| 
 | 
 | ||||||
|     def _add_ip_range(self, family: str, sig: desc_signature): |     def _add_ip_range(self, family: str, sig: str): | ||||||
|         name = "ip{}range.{}".format(family, sig) |         name = "ip{}range.{}".format(family, sig) | ||||||
|         anchor = "ip-ip{}range-{}".format(family, sig) |         anchor = "ip-ip{}range-{}".format(family, sig) | ||||||
|         try: |         try: | ||||||
|             ip_range = Network(sig) |             new_ip_range = ipaddress.ip_network(sig) | ||||||
|             self.data["range_nodes"].append( |             self.data["range_nodes"].append( | ||||||
|                 (name, family, sig, self.env.docname, anchor, 0) |                 (name, family, sig, self.env.docname, anchor, 0) | ||||||
|             ) |             ) | ||||||
|             self.data["ranges"][sig].append((ip_range, self.env.docname, anchor)) |             self.data["ranges"][sig].append((new_ip_range, self.env.docname, anchor)) | ||||||
|         except ValueError as e: |         except ValueError as e: | ||||||
|             logger.error("invalid ip range address '%s': %s", sig, e) |             logger.error("invalid ip range address '%s': %s", sig, e) | ||||||
| 
 | 
 | ||||||
|  | @ -224,13 +245,13 @@ class IPDomain(Domain): | ||||||
| 
 | 
 | ||||||
|     def _add_ip_address_reference(self, family, sig): |     def _add_ip_address_reference(self, family, sig): | ||||||
|         try: |         try: | ||||||
|             self.data["ip_dict"][sig] = IP(sig) |             self.data["ip_dict"][sig] = ipaddress.ip_address(sig) | ||||||
|         except ValueError as e: |         except ValueError as e: | ||||||
|             logger.error("invalid ip address '%s': %s", sig, e) |             logger.error("invalid ip address '%s': %s", sig, e) | ||||||
| 
 | 
 | ||||||
|     def add_ip_address_anchor(self, sig, docname, anchor): |     def add_ip_address_anchor(self, sig, docname, anchor): | ||||||
|         try: |         try: | ||||||
|             ip = IP(sig) |             ip = ipaddress.ip_address(sig) | ||||||
|             self.data["ip_refs"][sig].append((ip, docname, anchor)) |             self.data["ip_refs"][sig].append((ip, docname, anchor)) | ||||||
|         except ValueError as e: |         except ValueError as e: | ||||||
|             logger.error("invalid ip address '%s': %s", sig, e) |             logger.error("invalid ip address '%s': %s", sig, e) | ||||||
|  | @ -247,7 +268,7 @@ class IPDomain(Domain): | ||||||
|         name = "iprange{}.{}".format(family, sig) |         name = "iprange{}.{}".format(family, sig) | ||||||
|         anchor = "ip-iprange{}-{}".format(family, sig) |         anchor = "ip-iprange{}-{}".format(family, sig) | ||||||
|         try: |         try: | ||||||
|             ip_range = Network(sig) |             ip_range = ipaddress.ip_network(sig) | ||||||
|             self.data["range_refs"].append( |             self.data["range_refs"].append( | ||||||
|                 ( |                 ( | ||||||
|                     name, |                     name, | ||||||
|  | @ -274,15 +295,11 @@ class IPDomain(Domain): | ||||||
|     ) -> Optional[nodes.Element]: |     ) -> Optional[nodes.Element]: | ||||||
|         match = [] |         match = [] | ||||||
| 
 | 
 | ||||||
|         def address_tuple(docname, anchor, ip_range) -> Tuple[str, str, str]: |         def address_tuple(docname, anchor, ip_range: Any) -> Tuple[str, str, str]: | ||||||
|             return ( |             return ( | ||||||
|                 docname, |                 docname, | ||||||
|                 anchor, |                 anchor, | ||||||
|                 _( |                 _("IPv{0} range {1}".format(ip_range.version, ip_range.compressed)), | ||||||
|                     "IPv{0} range {1}".format( |  | ||||||
|                         ip_range.version(), ip_range.to_compressed() |  | ||||||
|                     ) |  | ||||||
|                 ), |  | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
|         if typ in ("v4", "v6"): |         if typ in ("v4", "v6"): | ||||||
|  | @ -318,26 +335,26 @@ class IPDomain(Domain): | ||||||
|         return None |         return None | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def process_ip_nodes(app, doctree, fromdocname): | def process_ip_nodes(app: Sphinx, doctree: nodes.Node, fromdocname: str): | ||||||
|     env = app.builder.env |     env = app.builder.env | ||||||
|     ips = env.get_domain(IPDomain.name) |     ips = env.get_domain(IPDomain.name) | ||||||
| 
 | 
 | ||||||
|     header = (_("IP address"), _("Used by")) |     header = (_("IP address"), _("Used by")) | ||||||
|     column_widths = (2, 5) |     column_widths = (2, 5) | ||||||
| 
 | 
 | ||||||
|     for node in doctree.traverse(ip_range): |     for node in doctree.findall(ip_range): | ||||||
|         content = [] |         content = [] | ||||||
|         net = Network(node["range_spec"]) |         net = ipaddress.ip_network(node["range_spec"], strict=False) | ||||||
|         addresses = defaultdict(list) |         addresses = defaultdict(list) | ||||||
|         for ip_address_sig, refs in ips.data["ip_refs"].items(): |         for ip_address_sig, refs in ips.data["ip_refs"].items(): | ||||||
|             for ip_address, todocname, anchor in refs: |             for ip_address, to_doc_name, anchor in refs: | ||||||
|                 if ip_address in net: |                 if ip_address in net: | ||||||
|                     addresses[ip_address_sig].append((ip_address, todocname, anchor)) |                     addresses[ip_address_sig].append((ip_address, to_doc_name, anchor)) | ||||||
|                     logger.debug( |                     logger.debug( | ||||||
|                         "found %s in network %s on %s", |                         "found %s in network %s on %s", | ||||||
|                         ip_address_sig, |                         ip_address_sig, | ||||||
|                         net.to_compressed(), |                         net.compressed, | ||||||
|                         todocname, |                         to_doc_name, | ||||||
|                     ) |                     ) | ||||||
|         if addresses: |         if addresses: | ||||||
|             table = nodes.table() |             table = nodes.table() | ||||||
|  | @ -360,30 +377,30 @@ def process_ip_nodes(app, doctree, fromdocname): | ||||||
|                 (key, addresses[key]) for key in sorted(addresses, key=sort_by_ip) |                 (key, addresses[key]) for key in sorted(addresses, key=sort_by_ip) | ||||||
|             ]: |             ]: | ||||||
|                 para = nodes.paragraph() |                 para = nodes.paragraph() | ||||||
|                 para += nodes.literal("", ip_info[0][0].to_compressed()) |                 para += nodes.literal("", ip_info[0][0].compressed) | ||||||
| 
 | 
 | ||||||
|                 ref_node = nodes.paragraph() |                 ref_node = nodes.paragraph() | ||||||
|                 ref_nodes = [] |                 ref_nodes = [] | ||||||
|                 referenced_docs = set() |                 referenced_docs = set() | ||||||
| 
 | 
 | ||||||
|                 for item in ip_info: |                 for item in ip_info: | ||||||
|                     ip_address, todocname, anchor = item |                     ip_address, to_doc_name, anchor = item | ||||||
|                     if todocname in referenced_docs: |                     if to_doc_name in referenced_docs: | ||||||
|                         continue |                         continue | ||||||
|                     referenced_docs.add(todocname) |                     referenced_docs.add(to_doc_name) | ||||||
| 
 | 
 | ||||||
|                     title = env.titles[todocname] |                     title = env.titles[to_doc_name] | ||||||
|                     innernode = nodes.Text(title.astext()) |                     inner_node = nodes.Text(title.astext()) | ||||||
|                     newnode = make_refnode( |                     new_node = make_refnode( | ||||||
|                         app.builder, |                         app.builder, | ||||||
|                         fromdocname, |                         fromdocname, | ||||||
|                         todocname, |                         to_doc_name, | ||||||
|                         anchor, |                         anchor, | ||||||
|                         innernode, |                         inner_node, | ||||||
|                         title.astext(), |                         title.astext(), | ||||||
|                     ) |                     ) | ||||||
| 
 | 
 | ||||||
|                     ref_nodes.append(newnode) |                     ref_nodes.append(new_node) | ||||||
|                 for count in range(len(ref_nodes)): |                 for count in range(len(ref_nodes)): | ||||||
|                     ref_node.append(ref_nodes[count]) |                     ref_node.append(ref_nodes[count]) | ||||||
|                     if count < len(ref_nodes) - 1: |                     if count < len(ref_nodes) - 1: | ||||||
|  | @ -407,10 +424,10 @@ def create_table_row(rowdata): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def sort_by_ip(item): | def sort_by_ip(item): | ||||||
|     return IP(item).ip |     return ipaddress.ip_address(item) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def setup(app): | def setup(app: Sphinx): | ||||||
|     app.add_domain(IPDomain) |     app.add_domain(IPDomain) | ||||||
|     app.connect("doctree-resolved", process_ip_nodes) |     app.connect("doctree-resolved", process_ip_nodes) | ||||||
|     return { |     return { | ||||||
|  | @ -15,7 +15,7 @@ author = Jan Dittberner | ||||||
| author_email = jan@dittberner.info | author_email = jan@dittberner.info | ||||||
| keywords = sphinx, extension, IP | keywords = sphinx, extension, IP | ||||||
| license = GPLv3+ | license = GPLv3+ | ||||||
| license_file = COPYING | license_files = COPYING | ||||||
| platforms = any | platforms = any | ||||||
| version = 0.5.1 | version = 0.5.1 | ||||||
| classifiers = | classifiers = | ||||||
|  | @ -31,8 +31,4 @@ zip_safe = False | ||||||
| include_package_data = True | include_package_data = True | ||||||
| packages = find: | packages = find: | ||||||
| install_requires = | install_requires = | ||||||
|     Sphinx >= 4 |     Sphinx >= 5 | ||||||
|     ipcalc >= 1.99 |  | ||||||
| namespace_packages = |  | ||||||
|     jandd |  | ||||||
|     jandd.sphinxext |  | ||||||
|  |  | ||||||
|  | @ -12,14 +12,14 @@ | ||||||
| # | # | ||||||
| # All configuration values have a default; values that are commented out | # All configuration values have a default; values that are commented out | ||||||
| # serve to show the default. | # serve to show the default. | ||||||
| 
 | import os | ||||||
| # import sys | import sys | ||||||
| # import os | from typing import Dict | ||||||
| 
 | 
 | ||||||
| # If extensions (or modules to document with autodoc) are in another directory, | # If extensions (or modules to document with autodoc) are in another directory, | ||||||
| # add these directories to sys.path here. If the directory is relative to the | # add these directories to sys.path here. If the directory is relative to the | ||||||
| # documentation root, use os.path.abspath to make it absolute, like shown here. | # documentation root, use os.path.abspath to make it absolute, like shown here. | ||||||
| # sys.path.insert(0, os.path.abspath('..')) | sys.path.insert(0, os.path.abspath(os.path.join("..", ".."))) | ||||||
| 
 | 
 | ||||||
| # -- General configuration ------------------------------------------------ | # -- General configuration ------------------------------------------------ | ||||||
| 
 | 
 | ||||||
|  | @ -47,7 +47,7 @@ master_doc = "index" | ||||||
| 
 | 
 | ||||||
| # General information about the project. | # General information about the project. | ||||||
| project = "Sphinxext IP Tests" | project = "Sphinxext IP Tests" | ||||||
| copyright = "2016-2021, Jan Dittberner" | copyright = "2016-2023, Jan Dittberner" | ||||||
| author = "Jan Dittberner" | author = "Jan Dittberner" | ||||||
| 
 | 
 | ||||||
| # The version info for the project you're documenting, acts as replacement for | # The version info for the project you're documenting, acts as replacement for | ||||||
|  | @ -104,7 +104,6 @@ pygments_style = "sphinx" | ||||||
| # If true, `todo` and `todoList` produce output, else they produce nothing. | # If true, `todo` and `todoList` produce output, else they produce nothing. | ||||||
| todo_include_todos = False | todo_include_todos = False | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| # -- Options for HTML output ---------------------------------------------- | # -- Options for HTML output ---------------------------------------------- | ||||||
| 
 | 
 | ||||||
| # The theme to use for HTML and HTML Help pages.  See the documentation for | # The theme to use for HTML and HTML Help pages.  See the documentation for | ||||||
|  | @ -207,15 +206,15 @@ htmlhelp_basename = "SphinxextIPTestsdoc" | ||||||
| 
 | 
 | ||||||
| # -- Options for LaTeX output --------------------------------------------- | # -- Options for LaTeX output --------------------------------------------- | ||||||
| 
 | 
 | ||||||
| latex_elements = { | latex_elements: Dict[str, str] = { | ||||||
|     # The paper size ('letterpaper' or 'a4paper'). |     # The paper size ('letterpaper' or 'a4paper'). | ||||||
|     #'papersize': 'letterpaper', |     # 'papersize': 'letterpaper', | ||||||
|     # The font size ('10pt', '11pt' or '12pt'). |     # The font size ('10pt', '11pt' or '12pt'). | ||||||
|     #'pointsize': '10pt', |     # 'pointsize': '10pt', | ||||||
|     # Additional stuff for the LaTeX preamble. |     # Additional stuff for the LaTeX preamble. | ||||||
|     #'preamble': '', |     # 'preamble': '', | ||||||
|     # Latex figure (float) alignment |     # Latex figure (float) alignment | ||||||
|     #'figure_align': 'htbp', |     # 'figure_align': 'htbp', | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| # Grouping the document tree into LaTeX files. List of tuples | # Grouping the document tree into LaTeX files. List of tuples | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| # -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||||||
| 
 | import shutil | ||||||
| import unittest | import unittest | ||||||
| from io import StringIO | from io import StringIO | ||||||
| 
 | 
 | ||||||
|  | @ -23,7 +23,7 @@ class TestIPExtension(unittest.TestCase): | ||||||
| 
 | 
 | ||||||
|     def tearDown(self): |     def tearDown(self): | ||||||
|         self.app.cleanup() |         self.app.cleanup() | ||||||
|         (test_root / "_build").rmtree(True) |         shutil.rmtree((test_root / "_build")) | ||||||
| 
 | 
 | ||||||
|     def test_ip_domaindata(self): |     def test_ip_domaindata(self): | ||||||
|         self.assertIn("ip", self.app.env.domaindata) |         self.assertIn("ip", self.app.env.domaindata) | ||||||
|  |  | ||||||
|  | @ -12,8 +12,8 @@ import shutil | ||||||
| import sys | import sys | ||||||
| import tempfile | import tempfile | ||||||
| from functools import wraps | from functools import wraps | ||||||
|  | from pathlib import Path | ||||||
| 
 | 
 | ||||||
| from path import Path |  | ||||||
| from sphinx import application | from sphinx import application | ||||||
| 
 | 
 | ||||||
| __all__ = [ | __all__ = [ | ||||||
|  | @ -25,14 +25,13 @@ __all__ = [ | ||||||
|     "SphinxTestApplication", |     "SphinxTestApplication", | ||||||
|     "with_app", |     "with_app", | ||||||
|     "gen_with_app", |     "gen_with_app", | ||||||
|     "Path", |  | ||||||
|     "with_tempdir", |     "with_tempdir", | ||||||
|     "write_file", |     "write_file", | ||||||
|     "sprint", |     "sprint", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| test_root = Path(__file__).parent.joinpath("root").abspath() | test_root = Path(__file__).parent.joinpath("root").absolute() | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def _excstr(exc): | def _excstr(exc): | ||||||
|  | @ -96,9 +95,9 @@ class SphinxTestApplication(application.Sphinx): | ||||||
| 
 | 
 | ||||||
|     def __init__( |     def __init__( | ||||||
|         self, |         self, | ||||||
|         srcdir=None, |         src_dir=None, | ||||||
|         confdir=None, |         confdir=None, | ||||||
|         outdir=None, |         out_dir=None, | ||||||
|         doctreedir=None, |         doctreedir=None, | ||||||
|         buildername="html", |         buildername="html", | ||||||
|         confoverrides=None, |         confoverrides=None, | ||||||
|  | @ -115,26 +114,26 @@ class SphinxTestApplication(application.Sphinx): | ||||||
| 
 | 
 | ||||||
|         self.cleanup_trees = [test_root / "generated"] |         self.cleanup_trees = [test_root / "generated"] | ||||||
| 
 | 
 | ||||||
|         if srcdir is None: |         if src_dir is None: | ||||||
|             srcdir = test_root |             src_dir = test_root | ||||||
|         if srcdir == "(temp)": |         if src_dir == "(temp)": | ||||||
|             tempdir = Path(tempfile.mkdtemp()) |             tempdir = Path(tempfile.mkdtemp()) | ||||||
|             self.cleanup_trees.append(tempdir) |             self.cleanup_trees.append(tempdir) | ||||||
|             temproot = tempdir / "root" |             temp_root = tempdir / "root" | ||||||
|             test_root.copytree(temproot) |             shutil.copytree(test_root.resolve(), temp_root.resolve()) | ||||||
|             srcdir = temproot |             src_dir = temp_root | ||||||
|         else: |         else: | ||||||
|             srcdir = Path(srcdir) |             src_dir = Path(src_dir) | ||||||
|         self.builddir = srcdir.joinpath("_build") |         self.builddir = src_dir.joinpath("_build") | ||||||
|         if confdir is None: |         if confdir is None: | ||||||
|             confdir = srcdir |             confdir = src_dir | ||||||
|         if outdir is None: |         if out_dir is None: | ||||||
|             outdir = srcdir.joinpath(self.builddir, buildername) |             out_dir = src_dir.joinpath(self.builddir, buildername) | ||||||
|             if not outdir.isdir(): |             if not out_dir.is_dir(): | ||||||
|                 outdir.makedirs() |                 out_dir.mkdir(parents=True) | ||||||
|             self.cleanup_trees.insert(0, outdir) |             self.cleanup_trees.insert(0, out_dir) | ||||||
|         if doctreedir is None: |         if doctreedir is None: | ||||||
|             doctreedir = srcdir.joinpath(srcdir, self.builddir, "doctrees") |             doctreedir = src_dir.joinpath(src_dir, self.builddir, "doctrees") | ||||||
|             if cleanenv: |             if cleanenv: | ||||||
|                 self.cleanup_trees.insert(0, doctreedir) |                 self.cleanup_trees.insert(0, doctreedir) | ||||||
|         if confoverrides is None: |         if confoverrides is None: | ||||||
|  | @ -150,9 +149,9 @@ class SphinxTestApplication(application.Sphinx): | ||||||
| 
 | 
 | ||||||
|         application.Sphinx.__init__( |         application.Sphinx.__init__( | ||||||
|             self, |             self, | ||||||
|             srcdir, |             str(src_dir), | ||||||
|             confdir, |             confdir, | ||||||
|             outdir, |             out_dir, | ||||||
|             doctreedir, |             doctreedir, | ||||||
|             buildername, |             buildername, | ||||||
|             confoverrides, |             confoverrides, | ||||||
|  | @ -211,7 +210,7 @@ def with_tempdir(func): | ||||||
|     def new_func(): |     def new_func(): | ||||||
|         tempdir = Path(tempfile.mkdtemp()) |         tempdir = Path(tempfile.mkdtemp()) | ||||||
|         func(tempdir) |         func(tempdir) | ||||||
|         tempdir.rmtree() |         tempdir.rmdir() | ||||||
| 
 | 
 | ||||||
|     new_func.__name__ = func.__name__ |     new_func.__name__ = func.__name__ | ||||||
|     return new_func |     return new_func | ||||||
|  |  | ||||||
							
								
								
									
										26
									
								
								tox.ini
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								tox.ini
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,26 @@ | ||||||
|  | [tox] | ||||||
|  | requires = | ||||||
|  |     tox>=4 | ||||||
|  | env_list = lint, type, py{39,310,311,312} | ||||||
|  | 
 | ||||||
|  | [testenv] | ||||||
|  | description = run unit tests | ||||||
|  | deps = | ||||||
|  |     pytest>=7 | ||||||
|  |     pytest-sugar | ||||||
|  | commands = | ||||||
|  |     pytest {posargs:tests} | ||||||
|  | 
 | ||||||
|  | [testenv:lint] | ||||||
|  | description = run linters | ||||||
|  | skip_install = true | ||||||
|  | deps = | ||||||
|  |     black==22.12 | ||||||
|  | commands = black {posargs:.} | ||||||
|  | 
 | ||||||
|  | [testenv:type] | ||||||
|  | description = run type checks | ||||||
|  | deps = | ||||||
|  |     mypy>=0.991 | ||||||
|  | commands = | ||||||
|  |     mypy {posargs:--install-types --non-interactive jandd tests} | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue