Skip to content

Commit

Permalink
Merge pull request #208 from dooit-org/develop
Browse files Browse the repository at this point in the history
v3.0.4
  • Loading branch information
kraanzu authored Nov 18, 2024
2 parents 20afad2 + b986dfb commit 9c598bf
Show file tree
Hide file tree
Showing 15 changed files with 87 additions and 81 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 3.0.4

This is a minor release with no new changes but fixing some stuff that was caused by recent textual update
- Fix tint on focused lists
- Startup crash because of variable override (#207)

## 3.0.3

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion dooit/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from platformdirs import user_data_dir, user_config_dir

OLD_CONFIG = Path(user_data_dir("dooit")) / "todo.yaml"
VERSION = "3.0.3"
VERSION = "3.0.4"


def run_dooit():
Expand Down
16 changes: 8 additions & 8 deletions dooit/ui/api/api_components/vars.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@


if TYPE_CHECKING: # pragma: no cover
from dooit.ui.tui import Dooit
from dooit.ui.api.dooit_api import DooitAPI


class VarManager(ApiComponent):
def __init__(self, app: "Dooit") -> None:
def __init__(self, api: "DooitAPI") -> None:
super().__init__()
self.app = app
self.api = api
self._show_confirm = True

@property
Expand All @@ -29,27 +29,27 @@ def show_confirm(self, value: bool):

@property
def mode(self) -> str:
return self.app.current_mode
return self.api.app.dooit_mode

@property
def theme(self) -> DooitThemeBase:
return self.app.current_theme
return self.api.css.theme

@property
def workspaces_tree(self) -> WorkspacesTree:
return self.app.query_one(WorkspacesTree)
return self.api.app.query_one(WorkspacesTree)

@property
def current_workspace(self) -> Optional[Workspace]:
tree = self.app.workspace_tree
tree = self.api.vars.workspaces_tree
if tree.highlighted is None:
return None

return tree.current_model

@property
def todos_tree(self) -> Optional[TodosTree]:
todo_switcher = self.app.query_one(
todo_switcher = self.api.app.query_one(
"#todo_switcher", expect_type=ContentSwitcher
)
if todo_switcher.visible_content and isinstance(
Expand Down
4 changes: 2 additions & 2 deletions dooit/ui/api/dooit_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ def __init__(self, app: "Dooit") -> None:
self.app = app
self.plugin_manager = PluginManager(self)
self.css = CssManager()
self.keys = KeyManager(self.app.get_mode)
self.keys = KeyManager(self.app.get_dooit_mode)
self.layouts = LayoutManager(self.app)
self.formatter = Formatter(self)
self.bar = BarManager(self)
self.vars = VarManager(self.app)
self.vars = VarManager(self)
self.dashboard = DashboardManager(self.app)

self.css.refresh_css()
Expand Down
49 changes: 28 additions & 21 deletions dooit/ui/api/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,49 @@
import sys
from typing import TYPE_CHECKING
from pathlib import Path
from contextlib import contextmanager

if TYPE_CHECKING: # pragma: no cover
from .plug import PluginManager


def register(api: "PluginManager", path: Path) -> None:
spec = importlib.util.spec_from_file_location("", path)
@contextmanager
def temporary_sys_path(path: Path):
"""Context manager to temporarily add a directory to sys.path."""

if spec and spec.loader:
foo = importlib.util.module_from_spec(spec)
spec.loader.exec_module(foo)
for obj in vars(foo).values():
api.register(obj)
# Temporarily add the parent directory to the path
# to allow imports from other files in the same directory

parent_path = str(path.parent.absolute())
if parent_path not in sys.path:
sys.path.insert(0, parent_path)
try:
yield
finally:
if parent_path in sys.path:
sys.path.remove(parent_path)

def load_file(api: "PluginManager", path: Path) -> bool:
if not path.exists():
return False

if path.suffix == ".py":
register(api, path)
def register(api: "PluginManager", path: Path) -> None:
module_name = f"dynamic_{path.stem}"
spec = importlib.util.spec_from_file_location(module_name, path)

return True
if spec and spec.loader:
parent_path = str(path.parent.absolute())
sys.path.append(parent_path)

with temporary_sys_path(path):
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
for obj in vars(module).values():
api.register(obj)

def load_dir(api: "PluginManager", path: Path) -> bool:
# allows users to import from the directory
sys.path.append(str(path.resolve()))

def load_file(api: "PluginManager", path: Path) -> bool:
if not path.exists():
return False

for file in path.iterdir():
if file.is_dir():
return load_dir(api, file)

load_file(api, file)
if path.suffix == ".py":
register(api, path)

return True
14 changes: 11 additions & 3 deletions dooit/ui/api/plug.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from functools import partial
import os
import sys
from functools import partial
from collections import defaultdict
from pathlib import Path
from typing import TYPE_CHECKING, Callable, List, Type
Expand All @@ -8,7 +9,7 @@

from dooit.ui.api.event_handlers import DOOIT_EVENT_ATTR, DOOIT_TIMER_ATTR
from dooit.ui.api.events import DooitEvent
from .loader import load_dir, load_file
from .loader import load_file

if TYPE_CHECKING: # pragma: no cover
from dooit.ui.api.dooit_api import DooitAPI
Expand All @@ -24,6 +25,10 @@
DEFAULT_CONFIG = BASE_PATH / "utils" / "default_config.py"


def is_running_under_pytest() -> bool:
return "PYTEST_CURRENT_TEST" in os.environ


class PluginManager:
def __init__(self, api: "DooitAPI") -> None:
self.events: defaultdict[Type[DooitEvent], List[Callable]] = defaultdict(list)
Expand All @@ -33,7 +38,10 @@ def __init__(self, api: "DooitAPI") -> None:

def scan(self):
load_file(self, DEFAULT_CONFIG)
load_dir(self, CONFIG_FOLDER)
if is_running_under_pytest():
return

load_file(self, CONFIG_FOLDER / "config.py")

def _update_dooit_value(self, obj, *params):
res = obj(self.api, *params)
Expand Down
1 change: 1 addition & 0 deletions dooit/ui/styles.tcss
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Dashboard {

ModelTree {
background: $background1;
background-tint: white 0%;
color: $foreground3;
border: $border_type $background3;
padding: 1;
Expand Down
23 changes: 8 additions & 15 deletions dooit/ui/tui.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import webbrowser
from typing import Optional
from textual import on
from textual.app import App
from textual.binding import Binding

from dooit.api.theme import DooitThemeBase
from dooit.ui.api.events import ModeChanged, DooitEvent, ModeType, Startup, _QuitApp
from dooit.ui.api.events.events import ShutDown
from dooit.ui.widgets import BarSwitcher
Expand Down Expand Up @@ -37,7 +34,7 @@ class Dooit(App):

def __init__(self, connection_string: Optional[str] = None):
super().__init__(watch_css=True)
self._mode: ModeType = "NORMAL"
self.dooit_mode: ModeType = "NORMAL"
manager.connect(connection_string)

async def base_setup(self):
Expand All @@ -48,7 +45,7 @@ async def base_setup(self):
self.push_screen("main")

async def setup_poller(self):
self.set_interval(1, self.poll)
self.set_interval(1, self.poll_dooit_db)

async def on_mount(self):
await self.base_setup()
Expand All @@ -70,14 +67,10 @@ def bar(self) -> StatusBar:
def bar_switcher(self) -> BarSwitcher:
return self.query_one(BarSwitcher)

def get_mode(self) -> ModeType:
return self._mode

@property
def current_theme(self) -> DooitThemeBase:
return self.api.css.theme
def get_dooit_mode(self) -> ModeType:
return self.dooit_mode

async def poll(self): # pragma: no cover
async def poll_dooit_db(self): # pragma: no cover
def refresh_all_trees():
trees = self.query(ModelTree)
for tree in trees:
Expand All @@ -93,12 +86,12 @@ def global_message(self, event: DooitEvent):
self.bar.refresh()

@on(ShutDown)
def shutdown(self, event: ShutDown):
def shutdown(self, _: ShutDown):
self.api.css.cleanup()

@on(ModeChanged)
def change_status(self, event: ModeChanged):
self._mode = event.mode
self.dooit_mode = event.mode
if event.mode == "NORMAL":
self.workspace_tree.refresh_options()
todos_tree = self.api.vars.todos_tree
Expand All @@ -110,7 +103,7 @@ async def quit_app(self):
await self.action_quit()

async def action_open_url(self, url: str) -> None: # pragma: no cover
webbrowser.open(url, new=2)
self.open_url(url)


if __name__ == "__main__": # pragma: no cover
Expand Down
6 changes: 3 additions & 3 deletions dooit/utils/css_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def __init__(
theme: DooitThemeBase = DooitThemeBase(),
cache_path: Path = dooit_cache_path,
):
self.theme = theme
self.theme: DooitThemeBase = theme
self.cache_path = cache_path
self.stylesheets: Path = cache_path / "stylesheets"
self.css_file: Path = cache_path / "dooit.tcss"
Expand Down Expand Up @@ -59,14 +59,14 @@ def refresh_css(self):
self.write(css)

def add_theme(self, theme: Type[DooitThemeBase]):
self.themes[theme._name] = theme
self.themes[theme._name] = theme()
self.refresh_css()

def set_theme(self, theme: Union[str, Type[DooitThemeBase]]):
if isinstance(theme, str):
self.theme = self.themes.get(theme, DooitThemeBase)
else:
self.theme = theme
self.theme = theme()

self.refresh_css()

Expand Down
18 changes: 10 additions & 8 deletions dooit/utils/default_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

@subscribe(ModeChanged)
def get_mode(api: DooitAPI, event: ModeChanged):
theme = api.app.current_theme
theme = api.vars.theme
mode = event.mode

MODES = {
Expand All @@ -32,7 +32,7 @@ def get_mode(api: DooitAPI, event: ModeChanged):

@timer(1)
def get_clock(api: DooitAPI):
theme = api.app.current_theme
theme = api.vars.theme
time = datetime.now().strftime("%H:%M:%S")
return Text(
f" {time} ",
Expand All @@ -45,7 +45,7 @@ def get_clock(api: DooitAPI):

@subscribe(Startup)
def get_user(api: DooitAPI, _: Startup):
theme = api.app.current_theme
theme = api.vars.theme
try:
username = os.getlogin()
except OSError:
Expand All @@ -65,17 +65,19 @@ def get_user(api: DooitAPI, _: Startup):
# Todo formatters


def todo_status_formatter(status: str, todo: Todo, api: DooitAPI):
def todo_status_formatter(status: str, _: Todo, api: DooitAPI):
text = "o"
color = api.app.current_theme.yellow
theme = api.vars.theme

color = theme.yellow

if status == "completed":
text = "x"
color = api.app.current_theme.green
color = theme.green

if status == "overdue":
text = "!"
color = api.app.current_theme.red
color = theme.red

return Text(text, style=Style(color=color, bold=True))

Expand All @@ -96,7 +98,7 @@ def todo_urgency_formatter(urgency, _, api: DooitAPI):
if urgency == 0:
return ""

theme = api.app.current_theme
theme = api.vars.theme
colors = {
1: theme.green,
2: theme.yellow,
Expand Down
8 changes: 4 additions & 4 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 9c598bf

Please sign in to comment.