diff --git a/src/sphinxnotes/any/directives.py b/src/sphinxnotes/any/directives.py index c335a34..607699d 100644 --- a/src/sphinxnotes/any/directives.py +++ b/src/sphinxnotes/any/directives.py @@ -11,9 +11,9 @@ from typing import Type from docutils import nodes +from docutils.nodes import Node, Element, fully_normalize_name from docutils.statemachine import StringList from docutils.parsers.rst import directives -from docutils.nodes import fully_normalize_name from sphinx import addnodes from sphinx.util.docutils import SphinxDirective @@ -81,10 +81,7 @@ def _build_object(self) -> Object: content='\n'.join(list(self.content.data))) - def _setup_nodes(self, obj:Object, - sectnode:nodes.Element, - ahrnode:nodes.Element|None, - contnode:nodes.Element) -> None: + def _setup_nodes(self, obj:Object, sectnode:Element, ahrnode:Element|None, contnode:Element) -> None: """ Attach necessary informations to nodes and note them. @@ -127,7 +124,7 @@ def _setup_nodes(self, obj:Object, contnode) - def _run_section(self, obj:Object) -> list[nodes.Node]: + def _run_section(self, obj:Object) -> list[Node]: # Get the title of the "section" where the directive is located sectnode = self.state.parent titlenode = sectnode.next_node(nodes.title) @@ -156,7 +153,7 @@ def _run_section(self, obj:Object) -> list[nodes.Node]: return [] - def _run_objdesc(self, obj:Object) -> list[nodes.Node]: + def _run_objdesc(self, obj:Object) -> list[Node]: descnode = addnodes.desc() # Generate signature node @@ -179,7 +176,7 @@ def _run_objdesc(self, obj:Object) -> list[nodes.Node]: return [descnode] - def run(self) -> list[nodes.Node]: + def run(self) -> list[Node]: obj = self._build_object() if self.schema.title_of(obj) == '_': # If no argument is given, or the first argument is '_', diff --git a/src/sphinxnotes/any/domain.py b/src/sphinxnotes/any/domain.py index e452678..1a08aa6 100644 --- a/src/sphinxnotes/any/domain.py +++ b/src/sphinxnotes/any/domain.py @@ -9,7 +9,7 @@ """ from __future__ import annotations -from typing import Tuple, Any, Iterator, Type, Set, Optional, TYPE_CHECKING +from typing import Any, Iterator, TYPE_CHECKING from docutils.nodes import Element, literal, Text @@ -44,14 +44,14 @@ class AnyDomain(Domain): #: Type (usually directive) name -> ObjType instance object_types:dict[str,ObjType]= {} #: Directive name -> directive class - directives:dict[str,Type[AnyDirective]] = {} + directives:dict[str,type[AnyDirective]] = {} #: Role name -> role callable roles:dict[str,RoleFunction] = {} #: A list of Index subclasses - indices:list[Type[AnyIndex]] = [] - #: AnyDomain specific: Type -> index class - _indices_for_reftype:dict[str,Type[AnyIndex]] = {} - #: AnyDomain specific: Type -> Schema instance + indices:list[type[AnyIndex]] = [] + #: AnyDomain specific: type -> index class + _indices_for_reftype:dict[str,type[AnyIndex]] = {} + #: AnyDomain specific: type -> Schema instance _schemas:dict[str,Schema] = {} initial_data:dict[str,Any] = { @@ -62,12 +62,12 @@ class AnyDomain(Domain): } @property - def objects(self) -> dict[Tuple[str,str], Tuple[str,str,Object]]: + def objects(self) -> dict[tuple[str,str], tuple[str,str,Object]]: """(objtype, objid) -> (docname, anchor, obj)""" return self.data.setdefault('objects', {}) @property - def references(self) -> dict[Tuple[str,str,str],Set[str]]: + def references(self) -> dict[tuple[str,str,str],set[str]]: """(objtype, objfield, objref) -> set(objid)""" return self.data.setdefault('references', {}) @@ -105,7 +105,7 @@ def clear_doc(self, docname:str) -> None: def resolve_xref(self, env:BuildEnvironment, fromdocname:str, builder:Builder, typ:str, target:str, node:pending_xref, contnode:Element, - ) -> Optional[Element]: + ) -> Element|None: assert isinstance(contnode, literal) logger.debug('[any] resolveing xref of %s', (typ, target)) @@ -151,7 +151,7 @@ def resolve_xref(self, env:BuildEnvironment, fromdocname:str, # Override parent method - def get_objects(self) -> Iterator[Tuple[str, str, str, str, str, int]]: + def get_objects(self) -> Iterator[tuple[str, str, str, str, str, int]]: for (objtype, objid), (docname, anchor, _) in self.data['objects'].items(): yield objid, objid, objtype, docname, anchor, 1 @@ -186,7 +186,7 @@ def add_schema(cls, schema:Schema) -> None: cls._indices_for_reftype[r] = index - def _get_index_anchor(self, reftype:str, refval:str) -> Tuple[str,str]: + def _get_index_anchor(self, reftype:str, refval:str) -> tuple[str,str]: """ Return the docname and anchor name of index page. Can be used for ``make_refnode()``. @@ -198,7 +198,7 @@ def _get_index_anchor(self, reftype:str, refval:str) -> Tuple[str,str]: def warn_missing_reference(app: Sphinx, domain: Domain, node: pending_xref - ) -> Optional[bool]: + ) -> bool|None: if domain and domain.name != AnyDomain.name: return None @@ -210,7 +210,7 @@ def warn_missing_reference(app: Sphinx, domain: Domain, node: pending_xref return True -def reftype_to_objtype_and_objfield(reftype:str) -> Tuple[str,Optional[str]]: +def reftype_to_objtype_and_objfield(reftype:str) -> tuple[str,str|None]: """Helper function for converting reftype(role name) to object infos.""" v = reftype.split('.', maxsplit=1) return v[0], v[1] if len(v) == 2 else None diff --git a/src/sphinxnotes/any/indices.py b/src/sphinxnotes/any/indices.py index d4ddd75..cbbe110 100644 --- a/src/sphinxnotes/any/indices.py +++ b/src/sphinxnotes/any/indices.py @@ -7,7 +7,7 @@ :copyright: Copyright 2021 Shengyu Zhang :license: BSD, see LICENSE for details. """ -from typing import Iterable, List, Tuple, Dict, Set, Optional, Type +from typing import Iterable from sphinx.domains import Index, IndexEntry from .schema import Schema @@ -19,14 +19,14 @@ class AnyIndex(Index): schema:Schema # TODO: document - field:Optional[str] = None + field:str|None = None name:str localname:str shortname:str @classmethod - def derive(cls, schema:Schema, field:str|None=None) -> Type["AnyIndex"]: + def derive(cls, schema:Schema, field:str|None=None) -> type["AnyIndex"]: """Generate an AnyIndex child class for indexing object.""" if field: typ = f'Any{schema.objtype.title()}{field.title()}Index' @@ -45,14 +45,14 @@ def derive(cls, schema:Schema, field:str|None=None) -> Type["AnyIndex"]: def generate(self, docnames:Iterable[str]|None = None - ) -> Tuple[List[Tuple[str,List[IndexEntry]]], bool]: + ) -> tuple[list[tuple[str,list[IndexEntry]]], bool]: """Override parent method.""" - content = {} # type: Dict[str, List[IndexEntry]] - # List of all references + content = {} # type: dict[str, list[IndexEntry]] + # list of all references objrefs = sorted(self.domain.data['references'].items()) # Reference value -> object IDs - objs_with_same_ref:Dict[str,Set[str]] = {} + objs_with_same_ref:dict[str,set[str]] = {} for (objtype, objfield, objref), objids in objrefs: if objtype != self.schema.objtype: diff --git a/src/sphinxnotes/any/perset.py b/src/sphinxnotes/any/perset.py deleted file mode 100644 index 44afef5..0000000 --- a/src/sphinxnotes/any/perset.py +++ /dev/null @@ -1,25 +0,0 @@ -""" - sphinxnotes.any.preset - ~~~~~~~~~~~~~~~~~~~~~~ - - Preset sechemas for sphinxnotes.any. - - :copyright: Copyright 2021 Shengyu Zhang - :license: BSD, see LICENSE for details. -""" - -from .domain import Schema, Field, dedent - -friend = Schema('friend', - {'avatar': Field(type=str), 'blog': Field(type=str)}, - description_template=dedent(""" - .. image:: {{ avatar }} - :width: 120px - :target: {{ blog }} - :alt: {{ names[0] }} - :align: left - - :blog: {{ blog }} - - {{ content | join('\n') }}"""), - reference_template='@{{ title }}') diff --git a/src/sphinxnotes/any/roles.py b/src/sphinxnotes/any/roles.py index 6c8960b..65d7234 100644 --- a/src/sphinxnotes/any/roles.py +++ b/src/sphinxnotes/any/roles.py @@ -8,7 +8,6 @@ :license: BSD, see LICENSE for details. """ from __future__ import annotations -from typing import Type from sphinx.util import logging from sphinx.roles import XRefRole @@ -29,7 +28,7 @@ class AnyRole(XRefRole): schema:Schema @classmethod - def derive(cls, schema:Schema, field:str|None=None) -> Type["AnyRole"]: + def derive(cls, schema:Schema, field:str|None=None) -> type["AnyRole"]: """Generate an AnyRole child class for referencing object.""" return type('Any%s%sRole' % (schema.objtype.title(), field.title() if field else ''), (cls,), diff --git a/src/sphinxnotes/any/schema.py b/src/sphinxnotes/any/schema.py index 0680f98..484c936 100644 --- a/src/sphinxnotes/any/schema.py +++ b/src/sphinxnotes/any/schema.py @@ -7,7 +7,7 @@ :copyright: Copyright 2021 Shengyu Zhang :license: BSD, see LICENSE for details. """ -from typing import Tuple, Dict, Iterator, List, Set, Optional, Union, Any +from typing import Iterator, Any from enum import Enum, auto from dataclasses import dataclass import pickle @@ -32,7 +32,7 @@ class SchemaError(AnyExtensionError): class Object(object): objtype:str name:str - attrs:Dict[str,str] + attrs:dict[str,str] content:str def hexdigest(self) -> str: @@ -90,20 +90,20 @@ def _as_plain(self, rawval:str) -> str: return rawval - def _as_words(self, rawval:str) -> List[str]: + def _as_words(self, rawval:str) -> list[str]: assert self.form == self.Form.WORDS assert rawval is not None return [x.strip() for x in rawval.split(' ') if x.strip() != ''] - def _as_lines(self, rawval:str) -> List[str]: + def _as_lines(self, rawval:str) -> list[str]: assert self.form == self.Form.LINES assert rawval is not None return rawval.split('\n') - def value_of(self, rawval:Optional[str]) -> Union[None,str,List[str]]: + def value_of(self, rawval:str|None) -> None|str|list[str]: if rawval is None: assert not self.required return None @@ -139,7 +139,7 @@ class Schema(object): # Object fields name:Field - attrs:Dict[str,Field] + attrs:dict[str,Field] content:Field # Class-wide shared template environment @@ -160,9 +160,9 @@ class Schema(object): ambiguous_reference_template:str def __init__(self, objtype:str, - name:Optional[Field]=Field(unique=True, referenceable=True), - attrs:Dict[str,Field]={}, - content:Optional[Field]=Field(), + name:Field|None=Field(unique=True, referenceable=True), + attrs:dict[str,Field]={}, + content:Field|None=Field(), description_template:str='{{ content }}', reference_template:str='{{ title }}', missing_reference_template:str='{{ title }} (missing reference)', @@ -199,7 +199,7 @@ def __init__(self, objtype:str, has_unique = field.unique - def object(self, name:Optional[str], attrs:Dict[str,str], content:Optional[str]) -> Object: + def object(self, name:str|None, attrs:dict[str,str], content:str|None) -> Object: """Generate a object""" obj = Object(objtype=self.objtype, name=name, @@ -211,11 +211,11 @@ def object(self, name:Optional[str], attrs:Dict[str,str], content:Optional[str]) return obj - def fields_of(self, obj:Object) -> Iterator[Tuple[str,Field,Union[None,str,List[str]]]]: + def fields_of(self, obj:Object) -> Iterator[tuple[str,Field,None|str|list[str]]]: """ Helper method for returning all fields of object and its raw values. -> Iterator[field_name, field_instance, field_value], - while the field_value is Union[string_value, string_list_value]. + while the field_value is string_value|string_list_value. """ if self.name: yield (self.NAME_KEY, self.name, self.name.value_of(obj.name) if obj else None) @@ -225,22 +225,22 @@ def fields_of(self, obj:Object) -> Iterator[Tuple[str,Field,Union[None,str,List[ yield (self.CONTENT_KEY, self.content, self.content.value_of(obj.content) if obj else None) - def name_of(self, obj:Object) -> Union[None,str,List[str]]: + def name_of(self, obj:Object) -> None|str|list[str]: assert obj return self.content.value_of(obj.name) - def attrs_of(self, obj:Object) -> Dict[str,Union[None,str,List[str]]]: + def attrs_of(self, obj:Object) -> dict[str,None|str|list[str]]: assert obj return {k: f.value_of(obj.attrs.get(k)) for k, f in self.attrs.items()} - def content_of(self, obj:Object) -> Union[None,str,List[str]]: + def content_of(self, obj:Object) -> None|str|list[str]: assert obj return self.content.value_of(obj.content) - def identifier_of(self, obj:Object) -> Tuple[Optional[str],str]: + def identifier_of(self, obj:Object) -> tuple[str|None,str]: """ Return unique identifier of object. If there is not any unique field, return (None, obj.hexdigest()) instead. @@ -259,7 +259,7 @@ def identifier_of(self, obj:Object) -> Tuple[Optional[str],str]: return None, obj.hexdigest() - def title_of(self, obj:Object) -> Optional[str]: + def title_of(self, obj:Object) -> str|None: """Return title (display name) of object.""" assert obj name = self.name.value_of(obj.name) @@ -271,7 +271,7 @@ def title_of(self, obj:Object) -> Optional[str]: return None - def references_of(self, obj:Object) -> Set[Tuple[str,str]]: + def references_of(self, obj:Object) -> set[tuple[str,str]]: """Return all references (referenceable fields) of object""" assert obj refs = [] @@ -287,16 +287,16 @@ def references_of(self, obj:Object) -> Set[Tuple[str,str]]: return set(refs) - def _context_without_object(self) -> Dict[str,Union[str,List[str]]]: + def _context_without_object(self) -> dict[str,str|list[str]]: return { self.TYPE_KEY: self.objtype, } - def _context_of(self, obj:Object) -> Dict[str,Union[str,List[str]]]: + def _context_of(self, obj:Object) -> dict[str,str|list[str]]: context = self._context_without_object() - def set_if_not_none(key:str, val:Union[str,List[str]]) -> None: + def set_if_not_none(key, val) -> None: if val is not None: context[key] = val set_if_not_none(self.NAME_KEY, self.name_of(obj)) @@ -308,7 +308,7 @@ def set_if_not_none(key:str, val:Union[str,List[str]]) -> None: return context - def render_description(self, obj:Object) -> List[str]: + def render_description(self, obj:Object) -> list[str]: assert obj tmpl = TemplateEnvironment().from_string(self.description_template) description = tmpl.render(self._context_of(obj)) diff --git a/src/sphinxnotes/any/template.py b/src/sphinxnotes/any/template.py index 6e0c03d..824b94a 100644 --- a/src/sphinxnotes/any/template.py +++ b/src/sphinxnotes/any/template.py @@ -9,7 +9,6 @@ """ from __future__ import annotations -from typing import Tuple import os from os import path import posixpath @@ -120,7 +119,7 @@ def _relative_uri(self, *args): return relative_uri(base, posixpath.join(*args)) - def _get_in_out_rel(self, fn:str) -> Tuple[str,str,str]: + def _get_in_out_rel(self, fn:str) -> tuple[str,str,str]: # The pass-in filenames must be relative assert not path.isabs(fn) diff --git a/tests/test_schema.py b/tests/test_schema.py index 659875a..7d4ed04 100644 --- a/tests/test_schema.py +++ b/tests/test_schema.py @@ -3,7 +3,7 @@ import unittest from textwrap import dedent -sys.path.insert(0, os.path.abspath('./sphinxnotes')) +sys.path.insert(0, os.path.abspath('./src/sphinxnotes')) from any import Schema, Field class TestSchema(unittest.TestCase):