This commit is contained in:
Joscha 2019-06-21 11:49:32 +00:00
parent 68595dcb7a
commit 11bd7778cf
14 changed files with 58 additions and 68 deletions

View file

@ -2,8 +2,8 @@
## Next version ## Next version
Nothing yet. - Clean up code
## 0.1.0 (2019-04-12) ## 0.1.0 (2019-04-12)
- use setuptools - Use setuptools

View file

@ -15,7 +15,6 @@ from .utils import *
__all__: List[str] = [] __all__: List[str] = []
__all__ += attributed_lines.__all__ __all__ += attributed_lines.__all__
__all__ += attributed_lines_widget.__all__ __all__ += attributed_lines_widget.__all__
__all__ += attributed_text_widget.__all__ __all__ += attributed_text_widget.__all__

View file

@ -5,11 +5,11 @@
import collections import collections
from typing import Any, Deque, Iterator, List, Optional, Set, Tuple from typing import Any, Deque, Iterator, List, Optional, Set, Tuple
from .markup import AT, AttributedText, Attributes from .markup import AT, Attributes
__all__ = ["Line", "AttributedLines"] __all__ = ["Line", "AttributedLines"]
Line = Tuple[Attributes, AttributedText] Line = Tuple[Attributes, AT]
class AttributedLines: class AttributedLines:
""" """
@ -49,7 +49,8 @@ class AttributedLines:
def append_above(self, def append_above(self,
attributes: Attributes, attributes: Attributes,
text: AttributedText) -> None: text: AT,
) -> None:
""" """
Append a line above all already existing lines. The existing lines' Append a line above all already existing lines. The existing lines'
offsets do not change. offsets do not change.
@ -60,7 +61,8 @@ class AttributedLines:
def append_below(self, def append_below(self,
attributes: Attributes, attributes: Attributes,
text: AttributedText) -> None: text: AT,
) -> None:
""" """
Append a line below all already existing lines. The existing lines' Append a line below all already existing lines. The existing lines'
offsets do not change. offsets do not change.
@ -133,7 +135,7 @@ class AttributedLines:
horizontal_offset: int, horizontal_offset: int,
offset_char: str = " ", offset_char: str = " ",
overlap_char: str = "", overlap_char: str = "",
) -> AttributedText: ) -> AT:
""" """
Renders a single line to a specified width with a specified horizontal Renders a single line to a specified width with a specified horizontal
offset, applying all line-wide attributes to the result. The length of offset, applying all line-wide attributes to the result. The length of
@ -152,7 +154,7 @@ class AttributedLines:
start_offset = horizontal_offset start_offset = horizontal_offset
end_offset = start_offset + text_width end_offset = start_offset + text_width
result: AttributedText = AT() result: AT = AT()
if start_offset < 0: if start_offset < 0:
pad_length = min(text_width, -start_offset) pad_length = min(text_width, -start_offset)
@ -189,7 +191,7 @@ class AttributedLines:
width: int, width: int,
height: int, height: int,
horizontal_offset: int, horizontal_offset: int,
) -> List[AttributedText]: ) -> List[AT]:
""" """
Renders all lines individually. Renders all lines individually.
""" """
@ -205,7 +207,7 @@ class AttributedLines:
width: int, width: int,
height: int, height: int,
horizontal_offset: int, horizontal_offset: int,
) -> AttributedText: ) -> AT:
""" """
Renders all lines and combines them into a single AttributedText by Renders all lines and combines them into a single AttributedText by
joining them with a newline. joining them with a newline.

View file

@ -5,7 +5,7 @@ from typing import Optional, Tuple
import urwid import urwid
from .attributed_lines import AttributedLines from .attributed_lines import AttributedLines
from .attributed_text_widget import AttributedTextWidget from .attributed_text_widget import ATWidget
from .markup import AT from .markup import AT
__all__ = ["AttributedLinesWidget"] __all__ = ["AttributedLinesWidget"]
@ -17,7 +17,7 @@ class AttributedLinesWidget(urwid.WidgetWrap):
""" """
def __init__(self, lines: Optional[AttributedLines] = None) -> None: def __init__(self, lines: Optional[AttributedLines] = None) -> None:
self._text = AttributedTextWidget(AT()) self._text = ATWidget(AT())
self._filler = urwid.Filler(self._text, valign=urwid.TOP) self._filler = urwid.Filler(self._text, valign=urwid.TOP)
super().__init__(self._filler) super().__init__(self._filler)

View file

@ -2,7 +2,7 @@ from typing import Any, List, Tuple, Union
import urwid import urwid
from .markup import AttributedText from .markup import AT
__all__ = ["AttributedTextWidget", "ATWidget"] __all__ = ["AttributedTextWidget", "ATWidget"]
@ -15,9 +15,9 @@ class AttributedTextWidget(urwid.Text):
""" """
def __init__(self, def __init__(self,
text: AttributedText, text: AT,
*args: Any, *args: Any,
**kwargs: Any **kwargs: Any,
) -> None: ) -> None:
""" """
text - an AttributedText object text - an AttributedText object
@ -30,9 +30,7 @@ class AttributedTextWidget(urwid.Text):
super().__init__(self._convert_to_markup(text), *args, **kwargs) super().__init__(self._convert_to_markup(text), *args, **kwargs)
@staticmethod @staticmethod
def _convert_to_markup(text: AttributedText def _convert_to_markup(text: AT) -> List[Union[str, Tuple[str, str]]]:
) -> List[Union[str, Tuple[str, str]]]:
# Wonder why mypy can't figure out the type signature of markup on its # Wonder why mypy can't figure out the type signature of markup on its
# own... :P # own... :P
markup: List[Union[str, Tuple[str, str]]] markup: List[Union[str, Tuple[str, str]]]
@ -43,7 +41,7 @@ class AttributedTextWidget(urwid.Text):
return markup or [""] return markup or [""]
def set_attributed_text(self, text: AttributedText) -> None: def set_attributed_text(self, text: AT) -> None:
""" """
Set the content of the AttributedTextWidget. Set the content of the AttributedTextWidget.
""" """
@ -51,7 +49,7 @@ class AttributedTextWidget(urwid.Text):
self._attributed_text = text self._attributed_text = text
super().set_text(self._convert_to_markup(text)) super().set_text(self._convert_to_markup(text))
def get_attributed_text(self) -> AttributedText: def get_attributed_text(self) -> AT:
""" """
Returns the currently used AttributedText. Returns the currently used AttributedText.
@ -63,7 +61,7 @@ class AttributedTextWidget(urwid.Text):
return self._attributed_text return self._attributed_text
@property @property
def attributed_text(self) -> AttributedText: def attributed_text(self) -> AT:
return self.get_attributed_text() return self.get_attributed_text()
ATWidget = AttributedTextWidget ATWidget = AttributedTextWidget

View file

@ -1,7 +1,6 @@
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum, auto from enum import Enum, auto
from typing import (Any, Callable, Dict, Iterable, List, Optional, Tuple, from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple
TypeVar)
__all__ = ["ConfigException", "ConfigValueException", "TransparentConfig", __all__ = ["ConfigException", "ConfigValueException", "TransparentConfig",
"Kind", "Condition", "Option", "TreeLoader"] "Kind", "Condition", "Option", "TreeLoader"]
@ -43,6 +42,7 @@ class TransparentConfig:
# Special config reading and writing classes # Special config reading and writing classes
class Kind(Enum): class Kind(Enum):
BOOL = auto() BOOL = auto()
DICT = auto() DICT = auto()
FLOAT = auto() FLOAT = auto()
@ -64,13 +64,15 @@ Condition = Callable[[Any], bool]
@dataclass @dataclass
class Option: class Option:
kind: Kind kind: Kind
default: Any default: Any
conditions: Iterable[Tuple[Condition, str]] = field(default_factory=list) conditions: Iterable[Tuple[Condition, str]] = field(default_factory=list)
def check_valid(self, value: Any) -> None: def check_valid(self, value: Any) -> None:
if not self.kind.matches(value): if not self.kind.matches(value):
raise ConfigValueException(f"value {value!r} does not match {self.kind}") raise ConfigValueException(
f"value {value!r} does not match {self.kind}")
self.apply_conditions(value) self.apply_conditions(value)

View file

@ -7,7 +7,7 @@ from .attributed_lines import AttributedLines
from .element import Element, Id, Message, RenderedElement, RenderedMessage from .element import Element, Id, Message, RenderedElement, RenderedMessage
from .element_supply import ElementSupply from .element_supply import ElementSupply
from .exceptions import ShouldNeverHappen from .exceptions import ShouldNeverHappen
from .markup import AT, AttributedText, Attributes from .markup import AT, Attributes
from .rendered_element_cache import RenderedElementCache from .rendered_element_cache import RenderedElementCache
__all__ = ["CursorRenderer", "CursorTreeRenderer", "BasicCursorRenderer"] __all__ = ["CursorRenderer", "CursorTreeRenderer", "BasicCursorRenderer"]
@ -28,7 +28,7 @@ class CursorRenderer(ABC, Generic[E, R]):
pass pass
@abstractmethod @abstractmethod
def render_cursor(self, width: int) -> AttributedText: def render_cursor(self, width: int) -> AT:
pass pass
class CursorTreeRenderer(Generic[E]): class CursorTreeRenderer(Generic[E]):
@ -157,7 +157,7 @@ class CursorTreeRenderer(Generic[E]):
def _render_message(self, def _render_message(self,
message_id: Id, message_id: Id,
indent: AttributedText, indent: AT,
) -> AttributedLines: ) -> AttributedLines:
width = self._width - len(indent) - self._renderer.meta_width - 1 width = self._width - len(indent) - self._renderer.meta_width - 1
@ -175,9 +175,7 @@ class CursorTreeRenderer(Generic[E]):
return lines return lines
def _render_cursor(self, def _render_cursor(self, indent: AT = AT(),) -> AttributedLines:
indent: AttributedText = AT(),
) -> AttributedLines:
lines = AttributedLines() lines = AttributedLines()
width = self._width - len(indent) - self._renderer.meta_width - 1 width = self._width - len(indent) - self._renderer.meta_width - 1
meta_spaces = AT(" " * self._renderer.meta_width) meta_spaces = AT(" " * self._renderer.meta_width)
@ -189,7 +187,7 @@ class CursorTreeRenderer(Generic[E]):
def _render_indent(self, def _render_indent(self,
cursor: bool = False, cursor: bool = False,
cursor_line: bool = False, cursor_line: bool = False,
) -> AttributedText: ) -> AT:
if self._indent_width < 1: if self._indent_width < 1:
return AT() return AT()
@ -215,7 +213,7 @@ class CursorTreeRenderer(Generic[E]):
def _render_subtree(self, def _render_subtree(self,
lines: AttributedLines, lines: AttributedLines,
root_id: Id, root_id: Id,
indent: AttributedText = AT(), indent: AT = AT(),
) -> None: ) -> None:
if self._anchor_id == root_id: if self._anchor_id == root_id:
@ -635,5 +633,5 @@ class BasicCursorRenderer(CursorRenderer):
return RenderedMessage(message.id, lines, meta) return RenderedMessage(message.id, lines, meta)
def render_cursor(self, width: int) -> AttributedText: def render_cursor(self, width: int) -> AT:
return AT("<cursor>") return AT("<cursor>")

View file

@ -1,7 +1,7 @@
import datetime import datetime
from typing import Hashable, List, Optional from typing import Hashable, List, Optional
from .markup import AttributedText from .markup import AT
__all__ = ["Id", "Element", "RenderedElement", "Message", "RenderedMessage"] __all__ = ["Id", "Element", "RenderedElement", "Message", "RenderedMessage"]
@ -26,10 +26,8 @@ class Element:
return self._parent_id return self._parent_id
class RenderedElement: class RenderedElement:
def __init__(self,
id: Id, def __init__(self, id: Id, lines: List[AT]) -> None:
lines: List[AttributedText],
) -> None:
self._id = id self._id = id
self._lines = lines self._lines = lines
@ -39,7 +37,7 @@ class RenderedElement:
return self._id return self._id
@property @property
def lines(self) -> List[AttributedText]: def lines(self) -> List[AT]:
return self._lines return self._lines
class Message(Element): class Message(Element):
@ -71,15 +69,10 @@ class Message(Element):
class RenderedMessage(RenderedElement): class RenderedMessage(RenderedElement):
def __init__(self, def __init__(self, id: Id, lines: List[AT], meta: AT) -> None:
id: Id,
lines: List[AttributedText],
meta: AttributedText,
) -> None:
super().__init__(id, lines) super().__init__(id, lines)
self._meta = meta self._meta = meta
@property @property
def meta(self) -> AttributedText: def meta(self) -> AT:
return self._meta return self._meta

View file

@ -6,7 +6,6 @@ from .euph_renderer import *
from .launch_application import * from .launch_application import *
from .room_widget import * from .room_widget import *
from .single_room_application import * from .single_room_application import *
from .user_list_widget import *
__all__: List[str] = [] __all__: List[str] = []
@ -16,4 +15,3 @@ __all__ += euph_renderer.__all__
__all__ += launch_application.__all__ __all__ += launch_application.__all__
__all__ += room_widget.__all__ __all__ += room_widget.__all__
__all__ += single_room_application.__all__ __all__ += single_room_application.__all__
__all__ += user_list_widget.__all__

View file

@ -1,7 +1,6 @@
from typing import Any, Dict, List, Optional, Set, TypeVar from typing import Any, Dict, List, Optional, Set
from ..config import (ConfigValueException, Kind, Option, TransparentConfig, from ..config import ConfigValueException, Kind, TransparentConfig, TreeLoader
TreeLoader)
__all__ = ["EuphConfig", "EuphLoader"] __all__ = ["EuphConfig", "EuphLoader"]

View file

@ -57,8 +57,8 @@ def load_config(args: Any) -> EuphConfig:
return config return config
def export_defaults(path: str) -> None: def export_defaults(path_str: str) -> None:
path = pathlib.Path(path).expanduser() path = pathlib.Path(path_str).expanduser()
print(f"Exporting default config to {path}") print(f"Exporting default config to {path}")
loader = EuphLoader() loader = EuphLoader()

View file

@ -1,16 +1,12 @@
import asyncio
import logging
from pathlib import Path
from typing import Any, Optional from typing import Any, Optional
import urwid import urwid
import yaml
from ..attributed_text_widget import ATWidget from ..attributed_text_widget import ATWidget
from ..markup import AT, Attributes from ..markup import AT
from .edit_widgets import EditWidget from .edit_widgets import EditWidget
from .euph_config import EuphConfig
from .launch_application import launch from .launch_application import launch
from .euph_config import EuphConfig, EuphLoader
from .room_widget import RoomWidget from .room_widget import RoomWidget
__all__ = ["SingleRoomApplication", "launch_single_room_application"] __all__ = ["SingleRoomApplication", "launch_single_room_application"]
@ -67,7 +63,7 @@ class ChooseRoomWidget(urwid.WidgetWrap):
self.set_error(ATWidget(text, align=urwid.CENTER)) self.set_error(ATWidget(text, align=urwid.CENTER))
class SingleRoomApplication(urwid.WidgetWrap): class SingleRoomApplication(urwid.WidgetWrap):
#
# The characters in the ALPHABET make up the characters that are allowed in # The characters in the ALPHABET make up the characters that are allowed in
# room names. # room names.
ALPHABET = "abcdefghijklmnopqrstuvwxyz0123456789" ALPHABET = "abcdefghijklmnopqrstuvwxyz0123456789"
@ -130,5 +126,5 @@ class SingleRoomApplication(urwid.WidgetWrap):
return key return key
def launch_single_room_application(): def launch_single_room_application() -> None:
launch(SingleRoomApplication) launch(SingleRoomApplication)

View file

@ -4,6 +4,7 @@ class MessageSupplyException(Exception):
pass pass
class ShouldNeverHappen(Exception): class ShouldNeverHappen(Exception):
def __init__(self, number: int) -> None: def __init__(self, number: int) -> None:
message = (f"SNV{number:05} - please contact @Garmy with the code on" message = (f"SNV{number:05} - please contact @Garmy with the code on"
" the left if you see this") " the left if you see this")

View file

@ -32,10 +32,7 @@ class Chunk:
# Common special methods # Common special methods
def __init__(self, def __init__(self, text: str, attributes: Attributes = {}) -> None:
text: str,
attributes: Attributes = {},
) -> None:
self._text = text self._text = text
self._attributes = dict(attributes) self._attributes = dict(attributes)
@ -51,7 +48,8 @@ class Chunk:
if not isinstance(other, Chunk): if not isinstance(other, Chunk):
return NotImplemented return NotImplemented
return self._text == other._text and self._attributes == other._attributes return (self._text == other._text and
self._attributes == other._attributes)
def __getitem__(self, key: Union[int, slice]) -> "Chunk": def __getitem__(self, key: Union[int, slice]) -> "Chunk":
return Chunk(self.text[key], self._attributes) return Chunk(self.text[key], self._attributes)
@ -247,9 +245,13 @@ class AttributedText:
name: str, name: str,
default: Any = None, default: Any = None,
) -> Any: ) -> Any:
return self._at(pos).get(name, default) return self._at(pos).get(name, default)
def split_by(self, attribute_name: str) -> List[Tuple["AttributedText", Any]]: def split_by(self,
attribute_name: str,
) -> List[Tuple["AttributedText", Any]]:
blocks = [] blocks = []
chunks: List[Chunk] = [] chunks: List[Chunk] = []
@ -297,6 +299,7 @@ class AttributedText:
start: Optional[int] = None, start: Optional[int] = None,
stop: Optional[int] = None, stop: Optional[int] = None,
) -> "AttributedText": ) -> "AttributedText":
if start is None and stop is None: if start is None and stop is None:
chunks = (chunk.set(name, value) for chunk in self._chunks) chunks = (chunk.set(name, value) for chunk in self._chunks)
return AttributedText.from_chunks(chunks) return AttributedText.from_chunks(chunks)
@ -319,6 +322,7 @@ class AttributedText:
start: Optional[int] = None, start: Optional[int] = None,
stop: Optional[int] = None, stop: Optional[int] = None,
) -> "AttributedText": ) -> "AttributedText":
if start is None and stop is None: if start is None and stop is None:
chunks = (chunk.remove(name) for chunk in self._chunks) chunks = (chunk.remove(name) for chunk in self._chunks)
return AttributedText.from_chunks(chunks) return AttributedText.from_chunks(chunks)