From e7ae59fadf6bc9a6924e7cf27585d6024409c333 Mon Sep 17 00:00:00 2001 From: relikd Date: Tue, 22 Nov 2022 10:51:28 +0100 Subject: [PATCH] chore: update types + minor fixes --- lektor_groupby/backref.py | 11 ++++++----- lektor_groupby/groupby.py | 6 +++--- lektor_groupby/pagination.py | 10 ++++++++-- lektor_groupby/plugin.py | 4 ++-- lektor_groupby/pruner.py | 2 +- lektor_groupby/query.py | 13 ++++++++----- lektor_groupby/resolver.py | 6 +++--- lektor_groupby/util.py | 14 ++++++++------ lektor_groupby/vobj.py | 6 +++--- lektor_groupby/watcher.py | 6 +++--- setup.py | 2 +- 11 files changed, 46 insertions(+), 34 deletions(-) diff --git a/lektor_groupby/backref.py b/lektor_groupby/backref.py index 7010103..eb194b0 100644 --- a/lektor_groupby/backref.py +++ b/lektor_groupby/backref.py @@ -1,5 +1,5 @@ from lektor.context import get_ctx -from typing import TYPE_CHECKING, Union, Iterable, Iterator, Optional +from typing import TYPE_CHECKING, Set, Union, Iterable, Iterator import weakref from .util import split_strip if TYPE_CHECKING: @@ -13,6 +13,7 @@ if TYPE_CHECKING: class WeakVGroupsList(list): def add(self, strong: 'FieldKeyPath', weak: 'GroupBySource') -> None: super().append((strong, weakref.ref(weak))) + # super().append((strong, weak)) # strong-ref class GroupByRef: @@ -71,11 +72,11 @@ class VGroups: flows = [flows] # find groups proc_list = [record] - done_list = set() + done_list = set() # type: Set[GroupBySource] while proc_list: page = proc_list.pop(0) if recursive and hasattr(page, 'children'): - proc_list.extend(page.children) # type: ignore[attr-defined] + proc_list.extend(page.children) for key, vobj in VGroups.of(page): if fields and key.fieldKey not in fields: continue @@ -87,11 +88,11 @@ class VGroups: if order_by: if isinstance(order_by, str): - order = split_strip(order_by, ',') + order = split_strip(order_by, ',') # type: Iterable[str] elif isinstance(order_by, (list, tuple)): order = order_by else: - raise TypeError('order_by must be either str or list type.') + raise AttributeError('order_by must be str or list type.') # using get_sort_key() of GroupBySource yield from sorted(done_list, key=lambda x: x.get_sort_key(order)) else: diff --git a/lektor_groupby/groupby.py b/lektor_groupby/groupby.py index 9c38d84..2cd01f2 100644 --- a/lektor_groupby/groupby.py +++ b/lektor_groupby/groupby.py @@ -4,9 +4,9 @@ from typing import TYPE_CHECKING, Set, List from .config import Config from .watcher import Watcher if TYPE_CHECKING: - from .config import AnyConfig from lektor.builder import Builder from lektor.sourceobj import SourceObject + from .config import AnyConfig from .resolver import Resolver from .vobj import GroupBySource @@ -55,9 +55,9 @@ class GroupBy: while queue: record = queue.pop() if hasattr(record, 'attachments'): - queue.extend(record.attachments) # type: ignore[attr-defined] + queue.extend(record.attachments) if hasattr(record, 'children'): - queue.extend(record.children) # type: ignore[attr-defined] + queue.extend(record.children) if isinstance(record, Record): for w in self._watcher: if w.should_process(record): diff --git a/lektor_groupby/pagination.py b/lektor_groupby/pagination.py index 96347ee..afa3cd4 100644 --- a/lektor_groupby/pagination.py +++ b/lektor_groupby/pagination.py @@ -1,14 +1,20 @@ from lektor import datamodel from typing import TYPE_CHECKING, Any if TYPE_CHECKING: - from lektor.db import Record + from lektor.pagination import Pagination + from lektor.sourceobj import SourceObject class PaginationConfig(datamodel.PaginationConfig): # because original method does not work for virtual sources. @staticmethod - def get_record_for_page(source: 'Record', page_num: int) -> Any: + def get_record_for_page(source: 'SourceObject', page_num: int) -> Any: for_page = getattr(source, '__for_page__', None) if callable(for_page): return for_page(page_num) return datamodel.PaginationConfig.get_record_for_page(source, page_num) + + if TYPE_CHECKING: + def get_pagination_controller(self, source: 'SourceObject') \ + -> 'Pagination': + ... diff --git a/lektor_groupby/plugin.py b/lektor_groupby/plugin.py index 9fd8c95..25af87e 100644 --- a/lektor_groupby/plugin.py +++ b/lektor_groupby/plugin.py @@ -1,4 +1,4 @@ -from lektor.assets import File, Directory # isinstance +from lektor.assets import Asset # isinstance from lektor.pluginsystem import Plugin # subclass from typing import TYPE_CHECKING, Iterator, Any from .backref import GroupByRef, VGroups @@ -27,7 +27,7 @@ class GroupByPlugin(Plugin): ) -> None: # before-build may be called before before-build-all (issue #1017) # make sure it is always evaluated first - if isinstance(source, (File, Directory)): + if isinstance(source, Asset): return groupby = self._init_once(builder) if groupby.isNew and isinstance(source, GroupBySource): diff --git a/lektor_groupby/pruner.py b/lektor_groupby/pruner.py index 43e9514..6eef54f 100644 --- a/lektor_groupby/pruner.py +++ b/lektor_groupby/pruner.py @@ -37,7 +37,7 @@ def prune(builder: 'Builder', vpath: str, url_cache: Iterable[str]) -> None: for artifact_name, _ in infos: if vpath not in artifact_name: continue # we only care about our Virtuals - reporter.report_pruned_artifact(url) + reporter.report_pruned_artifact(url) # type: ignore prune_file_and_folder(file.filename, dest_path) build_state.remove_artifact(url) break # there is only one VPATH-entry per source diff --git a/lektor_groupby/query.py b/lektor_groupby/query.py index eb7312c..f9baacb 100644 --- a/lektor_groupby/query.py +++ b/lektor_groupby/query.py @@ -1,8 +1,7 @@ # adapting https://github.com/dairiki/lektorlib/blob/master/lektorlib/query.py from lektor.constants import PRIMARY_ALT from lektor.db import Query # subclass - -from typing import TYPE_CHECKING, List, Optional, Iterator, Iterable +from typing import TYPE_CHECKING, List, Optional, Generator, Iterable if TYPE_CHECKING: from lektor.db import Record, Pad @@ -26,7 +25,7 @@ class FixedRecordsQuery(Query): return self.pad.get( # type: ignore[no-any-return] path, alt=self.alt, page_num=page_num, persist=persist) - def _iterate(self) -> Iterator['Record']: + def _iterate(self) -> Generator['Record', None, None]: ''' Iterate over internal set of Record elements. ''' # ignore self record dependency from super() for path in self.__child_paths: @@ -51,7 +50,7 @@ class FixedRecordsQuery(Query): def get_order_by(self) -> Optional[List[str]]: ''' Return list of attribute strings for sort order. ''' # ignore datamodel ordering from super() - return self._order_by + return self._order_by # type: ignore[no-any-return] def count(self) -> int: ''' Count matched objects. ''' @@ -69,4 +68,8 @@ class FixedRecordsQuery(Query): def __bool__(self) -> bool: if self._pristine: return len(self.__child_paths) > 0 - return super().__bool__() # type: ignore[no-any-return] + return super().__bool__() + + if TYPE_CHECKING: + def request_page(self, page_num: Optional[int]) -> 'FixedRecordsQuery': + ... diff --git a/lektor_groupby/resolver.py b/lektor_groupby/resolver.py index baed2d3..ca459d7 100644 --- a/lektor_groupby/resolver.py +++ b/lektor_groupby/resolver.py @@ -1,4 +1,4 @@ -from lektor.db import Record # isinstance +from lektor.db import Page # isinstance from typing import TYPE_CHECKING, Dict, List, NamedTuple, Optional, Iterable from .util import build_url from .vobj import VPATH, GroupBySource @@ -60,7 +60,7 @@ class Resolver: def resolve_server_path(self, node: 'SourceObject', pieces: List[str]) \ -> Optional[GroupBySource]: ''' Local server only: resolve /tag/rss/ -> /tag/rss/index.html ''' - if isinstance(node, Record): + if isinstance(node, Page): rv = self._data.get(build_url([node.url_path] + pieces)) if rv: return GroupBySource( @@ -70,7 +70,7 @@ class Resolver: def resolve_virtual_path(self, node: 'SourceObject', pieces: List[str]) \ -> Optional[GroupBySource]: ''' Admin UI only: Prevent server error and null-redirect. ''' - if isinstance(node, Record) and len(pieces) >= 2: + if isinstance(node, Page) and len(pieces) >= 2: path = node['_path'] # type: str attr, grp, *optional_page = pieces page = None diff --git a/lektor_groupby/util.py b/lektor_groupby/util.py index b46280a..3f90824 100644 --- a/lektor_groupby/util.py +++ b/lektor_groupby/util.py @@ -1,6 +1,8 @@ from lektor.reporter import reporter, style +from typing import List, Dict, Optional, TypeVar +from typing import Callable, Any, Union, Generic -from typing import List, Dict +T = TypeVar('T') def report_config_error(key: str, field: str, val: str, e: Exception) -> None: @@ -13,13 +15,13 @@ def report_config_error(key: str, field: str, val: str, e: Exception) -> None: print(msg) # fallback in case Lektor API changes -def most_used_key(keys: List[str]) -> str: +def most_used_key(keys: List[T]) -> Optional[T]: ''' Find string with most occurrences. ''' if len(keys) < 3: - return keys[0] if keys else '' # TODO: first vs last occurrence + return keys[0] if keys else None # TODO: first vs last occurrence best_count = 0 - best_key = '' - tmp = {} # type: Dict[str, int] + best_key = None + tmp = {} # type: Dict[T, int] for k in keys: num = (tmp[k] + 1) if k in tmp else 1 tmp[k] = num @@ -53,6 +55,6 @@ def build_url(parts: List[str]) -> str: txt = str(comp).strip('/') if txt: url += '/' + txt - if '.' not in url.split('/')[-1]: + if '.' not in url.rsplit('/', 1)[-1]: url += '/' return url or '/' diff --git a/lektor_groupby/vobj.py b/lektor_groupby/vobj.py index 4a7fb99..d455427 100644 --- a/lektor_groupby/vobj.py +++ b/lektor_groupby/vobj.py @@ -121,7 +121,7 @@ class GroupBySource(VirtualSourceObject): # --------------------- @property - def path(self) -> str: + def path(self) -> str: # type: ignore[override] # Used in VirtualSourceInfo, used to prune VirtualObjects vpath = f'{self.record.path}{VPATH}/{self.config.key}/{self.key}' if self.page_num: @@ -149,7 +149,7 @@ class GroupBySource(VirtualSourceObject): parts.append(self.slug) return build_url(parts) - def iter_source_filenames(self) -> Iterator[str]: + def iter_source_filenames(self) -> Generator[str, None, None]: ''' Enumerate all dependencies ''' if self.config.dependencies: yield from self.config.dependencies @@ -186,7 +186,7 @@ class GroupBySource(VirtualSourceObject): # Used for virtual path resolver if key in ('_path', '_alt'): return getattr(self, key[1:]) - return self.__missing__(key) # type: ignore[attr-defined] + return self.__missing__(key) def __lt__(self, other: 'GroupBySource') -> bool: # Used for |sort filter ("group" is the provided original string) diff --git a/lektor_groupby/watcher.py b/lektor_groupby/watcher.py index 8a9eb89..0e32d8f 100644 --- a/lektor_groupby/watcher.py +++ b/lektor_groupby/watcher.py @@ -56,7 +56,7 @@ class Watcher: def should_process(self, node: 'Record') -> bool: ''' Check if record path is being watched. ''' - return node['_path'].startswith(self._root) + return str(node['_path']).startswith(self._root) def process(self, record: 'Record') -> None: ''' @@ -106,5 +106,5 @@ class Watcher: del self._state def __repr__(self) -> str: - return ''.format( - self.config.key, self.config.enabled, self.callback) + return ''.format( + self.config.key, self.config.enabled) diff --git a/setup.py b/setup.py index ee6eb3b..ec02a53 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ from setuptools import setup -with open('README.md') as fp: +with open('README.md', encoding='utf8') as fp: longdesc = fp.read() setup(