Skip to content

Commit a7a1ebe

Browse files
committed
chore: update the documentation
1 parent ea71583 commit a7a1ebe

5 files changed

Lines changed: 110 additions & 28 deletions

File tree

‎docs/features/logging.md‎

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,27 @@
11
# Logging != print()
22

3-
Logging is not the same as printing to the console. Logging is a more sophisticated way of recording events in a program.
4-
It is a way to track the flow of the program and to record errors and exceptions.
3+
Logging records the flow of a program, including its errors and exceptions, to the console and to a file at once. It is more than printing.
4+
5+
## Usage
6+
7+
Call `setup_logger` once at startup, then use the shared `logger` everywhere. The `time_it` decorator logs how long a function takes:
8+
9+
```python
10+
from pathlib import Path
11+
12+
from py_app_dev.core.logging import logger, setup_logger, time_it
13+
14+
15+
@time_it()
16+
def build() -> None:
17+
logger.info("building ...")
18+
19+
20+
setup_logger(Path("build.log")) # console + file
21+
build()
22+
```
23+
24+
## Requirements
525

626
```{item} REQ-LOGGING_FILE-0.0.1 Print to file
727
@@ -41,7 +61,7 @@ It is a way to track the flow of the program and to record errors and exceptions
4161
```
4262

4363
:::{note}
44-
This module is based on the [loguru](https://github.com/Delgan/loguru) library, which is a Python logging library that provides powerful logging system.
64+
This module is built on the [loguru](https://github.com/Delgan/loguru) logging library.
4565
:::
4666

4767
## Current Status

‎docs/features/runnable.md‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,45 @@ To optimize an application, you want to avoid executing tasks with high computat
44
A simple way to avoid unnecessary executions is to check whether the inputs and outputs of a task have changed since the last execution.
55
If there are no changes, the task is skipped, saving time and resources.
66

7+
## Usage
8+
9+
Subclass `Runnable`, declare the task's inputs and outputs, then hand it to an `Executor`. The executor skips the task when nothing changed since the last run:
10+
11+
```python
12+
from pathlib import Path
13+
14+
from py_app_dev.core.runnable import Executor, Runnable
15+
16+
17+
class GenerateReport(Runnable):
18+
def __init__(self, source: Path, report: Path) -> None:
19+
super().__init__()
20+
self.source = source
21+
self.report = report
22+
23+
def get_name(self) -> str:
24+
return "generate_report"
25+
26+
def run(self) -> int:
27+
self.report.write_text(self.source.read_text().upper())
28+
return 0
29+
30+
def get_inputs(self) -> list[Path]:
31+
return [self.source]
32+
33+
def get_outputs(self) -> list[Path]:
34+
return [self.report]
35+
36+
37+
executor = Executor(cache_dir=Path(".cache"))
38+
executor.execute(GenerateReport(Path("in.txt"), Path("out.txt"))) # runs
39+
executor.execute(GenerateReport(Path("in.txt"), Path("out.txt"))) # skipped, nothing changed
40+
```
41+
42+
Pass `force_run=True` to `Executor` to run even when nothing changed, or `dry_run=True` to report what would run without touching the system.
43+
44+
## Requirements
45+
746
```{item} REQ-RUNNABLE-0.0.1 Executing a New Task
847
948
Execute a new task to ensure it runs even in the absence of previous execution data.

‎docs/features/scoop_wrapper.md‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,25 @@
33
The [Scoop](https://scoop.sh/) package manager for Windows has certain limitations, particularly in handling of tool versions and path prioritization via shims.
44
This module allows users to specify which versions of apps they want installed and actively manage the accessibility of these apps within their environment.
55

6+
## Usage
7+
8+
Point `ScoopWrapper` at a scoop file (the JSON listing the apps and versions you want). `install` installs anything missing and returns every required app, located on disk:
9+
10+
```python
11+
from pathlib import Path
12+
13+
from py_app_dev.core.scoop_wrapper import ScoopWrapper
14+
15+
apps = ScoopWrapper().install(Path("scoopfile.json"))
16+
for app in apps:
17+
print(app.name, app.version)
18+
print(app.get_all_required_paths()) # bin and env directories to put on PATH
19+
```
20+
21+
Each returned `InstalledScoopApp` carries its `name`, `version`, install `path`, and the bin/env directories from its manifest.
22+
23+
## Requirements
24+
625
```{item} REQ-SCOOP-WRAPPER-0.0.1 Customized App Installation
726
827
Allow users to specify which apps and versions to install via Scoop.

‎docs/getting_started/index.md‎

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,29 @@
11
# 🚀 Getting Started
22

3-
To be documented ...
3+
Add the package as a dependency of your project in `pyproject.toml`:
4+
5+
```toml
6+
[project]
7+
dependencies = [
8+
"py-app-dev",
9+
]
10+
```
11+
12+
Every module shares one logging setup. This is the smallest useful program:
13+
14+
```python
15+
from pathlib import Path
16+
17+
from py_app_dev.core.logging import logger, setup_logger, time_it
18+
19+
20+
@time_it()
21+
def build() -> None:
22+
logger.info("building ...")
23+
24+
25+
setup_logger(Path("build.log")) # logs to console and to the file
26+
build()
27+
```
28+
29+
From here, browse the [Features](../features/index.md) for the modules you need.

‎docs/internals/mvp/index.md‎

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -43,33 +43,11 @@ The Presenter subscribes to the Event Manager to handle these events and updates
4343
Presenter "1" *-- EventManager
4444
```
4545

46-
The implementation above uses the Model-View-Presenter (MVP) design pattern along with the Event Manager to handle events and communication between the components.
47-
Here are some advantages of this implementation:
48-
49-
- **Separation of Concerns:**
50-
: This pattern pattern separates the responsibilities of the View and Presenter into distinct components, which makes the code easier to read, test, and maintain.
51-
The Event Manager also helps to decouple the components, making it easier to modify and extend the code without affecting other parts.
52-
- **Testability:**
53-
: The Presenter acts as a mediator between the View and the underlying functionality, which allows for easy unit testing of the Presenter without needing to test the user interface.
54-
- **Flexibility:**
55-
: It allows for different user interfaces to be used with the same underlying functionality.
56-
For example, if we wanted to switch from a graphical user interface to a command-line interface, we could do so without affecting the underlying functionality of the application.
46+
Keeping the View and Presenter apart, with the Event Manager between them, makes the Presenter unit-testable without a user interface and lets the same logic drive a different View (for example, swapping a GUI for a command line).
5747

5848
## Event Manager
5949

60-
The EventManager class is a utility class that can be used in conjunction with the Model-View-Presenter design pattern to facilitate communication between the View and the Presenter.
61-
Its primary purpose is to handle events that are raised by the View and forward them to the appropriate Presenter methods.
62-
63-
By using the EventManager class, the View can raise events using the create_event_trigger method, and the Presenter can subscribe to those events using the subscribe method.
64-
When the event is triggered, the EventManager calls all of the registered callbacks for that event, allowing the Presenter to handle the event appropriately.
65-
The unsubscribe method can be used to remove callbacks from the list of subscribers if needed.
66-
67-
It's worth noting that the EventManager class, as described above, is actually an implementation of the Observer design pattern.
68-
In this pattern, the EventManager acts as the Subject or Observable, while the callbacks registered through the subscribe method serve as the Observers.
69-
70-
When an event is triggered, the EventManager notifies all registered Observers by calling their respective callback functions. This decouples the components of the system and allows for easier maintenance and modifications in the future.
71-
72-
By using the Observer pattern with the EventManager class, the View can raise events without knowing anything about the Presenter, and the Presenter can handle events without knowing anything about the View. This promotes a more modular and flexible architecture, making it easier to develop and maintain complex systems.
50+
The `EventManager` decouples the View from the Presenter: the View raises events with `create_event_trigger`, and the Presenter reacts to them with `subscribe`. When an event fires, the manager calls every registered callback; `unsubscribe` removes one. This is the Observer pattern, with the manager as the subject and the callbacks as the observers, so neither side needs to know about the other.
7351

7452
```{eval-rst}
7553
.. autoclass:: py_app_dev.mvp.event_manager::EventManager

0 commit comments

Comments
 (0)