chore: update types + minor fixes
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
from lektor.context import get_ctx
|
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
|
import weakref
|
||||||
from .util import split_strip
|
from .util import split_strip
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@@ -13,6 +13,7 @@ if TYPE_CHECKING:
|
|||||||
class WeakVGroupsList(list):
|
class WeakVGroupsList(list):
|
||||||
def add(self, strong: 'FieldKeyPath', weak: 'GroupBySource') -> None:
|
def add(self, strong: 'FieldKeyPath', weak: 'GroupBySource') -> None:
|
||||||
super().append((strong, weakref.ref(weak)))
|
super().append((strong, weakref.ref(weak)))
|
||||||
|
# super().append((strong, weak)) # strong-ref
|
||||||
|
|
||||||
|
|
||||||
class GroupByRef:
|
class GroupByRef:
|
||||||
@@ -71,11 +72,11 @@ class VGroups:
|
|||||||
flows = [flows]
|
flows = [flows]
|
||||||
# find groups
|
# find groups
|
||||||
proc_list = [record]
|
proc_list = [record]
|
||||||
done_list = set()
|
done_list = set() # type: Set[GroupBySource]
|
||||||
while proc_list:
|
while proc_list:
|
||||||
page = proc_list.pop(0)
|
page = proc_list.pop(0)
|
||||||
if recursive and hasattr(page, 'children'):
|
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):
|
for key, vobj in VGroups.of(page):
|
||||||
if fields and key.fieldKey not in fields:
|
if fields and key.fieldKey not in fields:
|
||||||
continue
|
continue
|
||||||
@@ -87,11 +88,11 @@ class VGroups:
|
|||||||
|
|
||||||
if order_by:
|
if order_by:
|
||||||
if isinstance(order_by, str):
|
if isinstance(order_by, str):
|
||||||
order = split_strip(order_by, ',')
|
order = split_strip(order_by, ',') # type: Iterable[str]
|
||||||
elif isinstance(order_by, (list, tuple)):
|
elif isinstance(order_by, (list, tuple)):
|
||||||
order = order_by
|
order = order_by
|
||||||
else:
|
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
|
# using get_sort_key() of GroupBySource
|
||||||
yield from sorted(done_list, key=lambda x: x.get_sort_key(order))
|
yield from sorted(done_list, key=lambda x: x.get_sort_key(order))
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ from typing import TYPE_CHECKING, Set, List
|
|||||||
from .config import Config
|
from .config import Config
|
||||||
from .watcher import Watcher
|
from .watcher import Watcher
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .config import AnyConfig
|
|
||||||
from lektor.builder import Builder
|
from lektor.builder import Builder
|
||||||
from lektor.sourceobj import SourceObject
|
from lektor.sourceobj import SourceObject
|
||||||
|
from .config import AnyConfig
|
||||||
from .resolver import Resolver
|
from .resolver import Resolver
|
||||||
from .vobj import GroupBySource
|
from .vobj import GroupBySource
|
||||||
|
|
||||||
@@ -55,9 +55,9 @@ class GroupBy:
|
|||||||
while queue:
|
while queue:
|
||||||
record = queue.pop()
|
record = queue.pop()
|
||||||
if hasattr(record, 'attachments'):
|
if hasattr(record, 'attachments'):
|
||||||
queue.extend(record.attachments) # type: ignore[attr-defined]
|
queue.extend(record.attachments)
|
||||||
if hasattr(record, 'children'):
|
if hasattr(record, 'children'):
|
||||||
queue.extend(record.children) # type: ignore[attr-defined]
|
queue.extend(record.children)
|
||||||
if isinstance(record, Record):
|
if isinstance(record, Record):
|
||||||
for w in self._watcher:
|
for w in self._watcher:
|
||||||
if w.should_process(record):
|
if w.should_process(record):
|
||||||
|
|||||||
@@ -1,14 +1,20 @@
|
|||||||
from lektor import datamodel
|
from lektor import datamodel
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from lektor.db import Record
|
from lektor.pagination import Pagination
|
||||||
|
from lektor.sourceobj import SourceObject
|
||||||
|
|
||||||
|
|
||||||
class PaginationConfig(datamodel.PaginationConfig):
|
class PaginationConfig(datamodel.PaginationConfig):
|
||||||
# because original method does not work for virtual sources.
|
# because original method does not work for virtual sources.
|
||||||
@staticmethod
|
@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)
|
for_page = getattr(source, '__for_page__', None)
|
||||||
if callable(for_page):
|
if callable(for_page):
|
||||||
return for_page(page_num)
|
return for_page(page_num)
|
||||||
return datamodel.PaginationConfig.get_record_for_page(source, page_num)
|
return datamodel.PaginationConfig.get_record_for_page(source, page_num)
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
def get_pagination_controller(self, source: 'SourceObject') \
|
||||||
|
-> 'Pagination':
|
||||||
|
...
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from lektor.assets import File, Directory # isinstance
|
from lektor.assets import Asset # isinstance
|
||||||
from lektor.pluginsystem import Plugin # subclass
|
from lektor.pluginsystem import Plugin # subclass
|
||||||
from typing import TYPE_CHECKING, Iterator, Any
|
from typing import TYPE_CHECKING, Iterator, Any
|
||||||
from .backref import GroupByRef, VGroups
|
from .backref import GroupByRef, VGroups
|
||||||
@@ -27,7 +27,7 @@ class GroupByPlugin(Plugin):
|
|||||||
) -> None:
|
) -> None:
|
||||||
# before-build may be called before before-build-all (issue #1017)
|
# before-build may be called before before-build-all (issue #1017)
|
||||||
# make sure it is always evaluated first
|
# make sure it is always evaluated first
|
||||||
if isinstance(source, (File, Directory)):
|
if isinstance(source, Asset):
|
||||||
return
|
return
|
||||||
groupby = self._init_once(builder)
|
groupby = self._init_once(builder)
|
||||||
if groupby.isNew and isinstance(source, GroupBySource):
|
if groupby.isNew and isinstance(source, GroupBySource):
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ def prune(builder: 'Builder', vpath: str, url_cache: Iterable[str]) -> None:
|
|||||||
for artifact_name, _ in infos:
|
for artifact_name, _ in infos:
|
||||||
if vpath not in artifact_name:
|
if vpath not in artifact_name:
|
||||||
continue # we only care about our Virtuals
|
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)
|
prune_file_and_folder(file.filename, dest_path)
|
||||||
build_state.remove_artifact(url)
|
build_state.remove_artifact(url)
|
||||||
break # there is only one VPATH-entry per source
|
break # there is only one VPATH-entry per source
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
# adapting https://github.com/dairiki/lektorlib/blob/master/lektorlib/query.py
|
# adapting https://github.com/dairiki/lektorlib/blob/master/lektorlib/query.py
|
||||||
from lektor.constants import PRIMARY_ALT
|
from lektor.constants import PRIMARY_ALT
|
||||||
from lektor.db import Query # subclass
|
from lektor.db import Query # subclass
|
||||||
|
from typing import TYPE_CHECKING, List, Optional, Generator, Iterable
|
||||||
from typing import TYPE_CHECKING, List, Optional, Iterator, Iterable
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from lektor.db import Record, Pad
|
from lektor.db import Record, Pad
|
||||||
|
|
||||||
@@ -26,7 +25,7 @@ class FixedRecordsQuery(Query):
|
|||||||
return self.pad.get( # type: ignore[no-any-return]
|
return self.pad.get( # type: ignore[no-any-return]
|
||||||
path, alt=self.alt, page_num=page_num, persist=persist)
|
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. '''
|
''' Iterate over internal set of Record elements. '''
|
||||||
# ignore self record dependency from super()
|
# ignore self record dependency from super()
|
||||||
for path in self.__child_paths:
|
for path in self.__child_paths:
|
||||||
@@ -51,7 +50,7 @@ class FixedRecordsQuery(Query):
|
|||||||
def get_order_by(self) -> Optional[List[str]]:
|
def get_order_by(self) -> Optional[List[str]]:
|
||||||
''' Return list of attribute strings for sort order. '''
|
''' Return list of attribute strings for sort order. '''
|
||||||
# ignore datamodel ordering from super()
|
# ignore datamodel ordering from super()
|
||||||
return self._order_by
|
return self._order_by # type: ignore[no-any-return]
|
||||||
|
|
||||||
def count(self) -> int:
|
def count(self) -> int:
|
||||||
''' Count matched objects. '''
|
''' Count matched objects. '''
|
||||||
@@ -69,4 +68,8 @@ class FixedRecordsQuery(Query):
|
|||||||
def __bool__(self) -> bool:
|
def __bool__(self) -> bool:
|
||||||
if self._pristine:
|
if self._pristine:
|
||||||
return len(self.__child_paths) > 0
|
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':
|
||||||
|
...
|
||||||
|
|||||||
@@ -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 typing import TYPE_CHECKING, Dict, List, NamedTuple, Optional, Iterable
|
||||||
from .util import build_url
|
from .util import build_url
|
||||||
from .vobj import VPATH, GroupBySource
|
from .vobj import VPATH, GroupBySource
|
||||||
@@ -60,7 +60,7 @@ class Resolver:
|
|||||||
def resolve_server_path(self, node: 'SourceObject', pieces: List[str]) \
|
def resolve_server_path(self, node: 'SourceObject', pieces: List[str]) \
|
||||||
-> Optional[GroupBySource]:
|
-> Optional[GroupBySource]:
|
||||||
''' Local server only: resolve /tag/rss/ -> /tag/rss/index.html '''
|
''' 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))
|
rv = self._data.get(build_url([node.url_path] + pieces))
|
||||||
if rv:
|
if rv:
|
||||||
return GroupBySource(
|
return GroupBySource(
|
||||||
@@ -70,7 +70,7 @@ class Resolver:
|
|||||||
def resolve_virtual_path(self, node: 'SourceObject', pieces: List[str]) \
|
def resolve_virtual_path(self, node: 'SourceObject', pieces: List[str]) \
|
||||||
-> Optional[GroupBySource]:
|
-> Optional[GroupBySource]:
|
||||||
''' Admin UI only: Prevent server error and null-redirect. '''
|
''' 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
|
path = node['_path'] # type: str
|
||||||
attr, grp, *optional_page = pieces
|
attr, grp, *optional_page = pieces
|
||||||
page = None
|
page = None
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
from lektor.reporter import reporter, style
|
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:
|
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
|
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. '''
|
''' Find string with most occurrences. '''
|
||||||
if len(keys) < 3:
|
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_count = 0
|
||||||
best_key = ''
|
best_key = None
|
||||||
tmp = {} # type: Dict[str, int]
|
tmp = {} # type: Dict[T, int]
|
||||||
for k in keys:
|
for k in keys:
|
||||||
num = (tmp[k] + 1) if k in tmp else 1
|
num = (tmp[k] + 1) if k in tmp else 1
|
||||||
tmp[k] = num
|
tmp[k] = num
|
||||||
@@ -53,6 +55,6 @@ def build_url(parts: List[str]) -> str:
|
|||||||
txt = str(comp).strip('/')
|
txt = str(comp).strip('/')
|
||||||
if txt:
|
if txt:
|
||||||
url += '/' + txt
|
url += '/' + txt
|
||||||
if '.' not in url.split('/')[-1]:
|
if '.' not in url.rsplit('/', 1)[-1]:
|
||||||
url += '/'
|
url += '/'
|
||||||
return url or '/'
|
return url or '/'
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ class GroupBySource(VirtualSourceObject):
|
|||||||
# ---------------------
|
# ---------------------
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def path(self) -> str:
|
def path(self) -> str: # type: ignore[override]
|
||||||
# Used in VirtualSourceInfo, used to prune VirtualObjects
|
# Used in VirtualSourceInfo, used to prune VirtualObjects
|
||||||
vpath = f'{self.record.path}{VPATH}/{self.config.key}/{self.key}'
|
vpath = f'{self.record.path}{VPATH}/{self.config.key}/{self.key}'
|
||||||
if self.page_num:
|
if self.page_num:
|
||||||
@@ -149,7 +149,7 @@ class GroupBySource(VirtualSourceObject):
|
|||||||
parts.append(self.slug)
|
parts.append(self.slug)
|
||||||
return build_url(parts)
|
return build_url(parts)
|
||||||
|
|
||||||
def iter_source_filenames(self) -> Iterator[str]:
|
def iter_source_filenames(self) -> Generator[str, None, None]:
|
||||||
''' Enumerate all dependencies '''
|
''' Enumerate all dependencies '''
|
||||||
if self.config.dependencies:
|
if self.config.dependencies:
|
||||||
yield from self.config.dependencies
|
yield from self.config.dependencies
|
||||||
@@ -186,7 +186,7 @@ class GroupBySource(VirtualSourceObject):
|
|||||||
# Used for virtual path resolver
|
# Used for virtual path resolver
|
||||||
if key in ('_path', '_alt'):
|
if key in ('_path', '_alt'):
|
||||||
return getattr(self, key[1:])
|
return getattr(self, key[1:])
|
||||||
return self.__missing__(key) # type: ignore[attr-defined]
|
return self.__missing__(key)
|
||||||
|
|
||||||
def __lt__(self, other: 'GroupBySource') -> bool:
|
def __lt__(self, other: 'GroupBySource') -> bool:
|
||||||
# Used for |sort filter ("group" is the provided original string)
|
# Used for |sort filter ("group" is the provided original string)
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ class Watcher:
|
|||||||
|
|
||||||
def should_process(self, node: 'Record') -> bool:
|
def should_process(self, node: 'Record') -> bool:
|
||||||
''' Check if record path is being watched. '''
|
''' 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:
|
def process(self, record: 'Record') -> None:
|
||||||
'''
|
'''
|
||||||
@@ -106,5 +106,5 @@ class Watcher:
|
|||||||
del self._state
|
del self._state
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return '<GroupByWatcher key="{}" enabled={} callback={}>'.format(
|
return '<GroupByWatcher key="{}" enabled={}>'.format(
|
||||||
self.config.key, self.config.enabled, self.callback)
|
self.config.key, self.config.enabled)
|
||||||
|
|||||||
Reference in New Issue
Block a user