schenesort 2.1.1__tar.gz → 2.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {schenesort-2.1.1 → schenesort-2.2.0}/PKG-INFO +46 -14
- {schenesort-2.1.1 → schenesort-2.2.0}/README.md +45 -13
- schenesort-2.2.0/docs/browse-autumn.png +0 -0
- schenesort-2.2.0/docs/browse-greek.png +0 -0
- schenesort-2.2.0/docs/browse-stallman.png +0 -0
- {schenesort-2.1.1 → schenesort-2.2.0}/pyproject.toml +2 -2
- {schenesort-2.1.1 → schenesort-2.2.0}/src/schenesort/cli.py +53 -30
- {schenesort-2.1.1 → schenesort-2.2.0}/src/schenesort/config.py +9 -1
- {schenesort-2.1.1 → schenesort-2.2.0}/src/schenesort/tui/app.py +21 -8
- {schenesort-2.1.1 → schenesort-2.2.0}/src/schenesort/tui/widgets/image_preview.py +4 -2
- {schenesort-2.1.1 → schenesort-2.2.0}/.envrc +0 -0
- {schenesort-2.1.1 → schenesort-2.2.0}/.github/workflows/ci.yml +0 -0
- {schenesort-2.1.1 → schenesort-2.2.0}/.github/workflows/publish.yml +0 -0
- {schenesort-2.1.1 → schenesort-2.2.0}/.gitignore +0 -0
- {schenesort-2.1.1 → schenesort-2.2.0}/.pre-commit-config.yaml +0 -0
- {schenesort-2.1.1 → schenesort-2.2.0}/.python-version +0 -0
- {schenesort-2.1.1 → schenesort-2.2.0}/CLAUDE.md +0 -0
- {schenesort-2.1.1 → schenesort-2.2.0}/LICENSE +0 -0
- {schenesort-2.1.1 → schenesort-2.2.0}/justfile +0 -0
- {schenesort-2.1.1 → schenesort-2.2.0}/ollama-setup.md +0 -0
- {schenesort-2.1.1 → schenesort-2.2.0}/schenesort.yazi/README.md +0 -0
- {schenesort-2.1.1 → schenesort-2.2.0}/schenesort.yazi/main.lua +0 -0
- {schenesort-2.1.1 → schenesort-2.2.0}/schenesort.yazi/schenesort.config +0 -0
- {schenesort-2.1.1 → schenesort-2.2.0}/src/schenesort/__init__.py +0 -0
- {schenesort-2.1.1 → schenesort-2.2.0}/src/schenesort/db.py +0 -0
- {schenesort-2.1.1 → schenesort-2.2.0}/src/schenesort/tui/__init__.py +0 -0
- {schenesort-2.1.1 → schenesort-2.2.0}/src/schenesort/tui/widgets/__init__.py +0 -0
- {schenesort-2.1.1 → schenesort-2.2.0}/src/schenesort/tui/widgets/metadata_panel.py +0 -0
- {schenesort-2.1.1 → schenesort-2.2.0}/src/schenesort/xmp.py +0 -0
- {schenesort-2.1.1 → schenesort-2.2.0}/tests/__init__.py +0 -0
- {schenesort-2.1.1 → schenesort-2.2.0}/tests/test_cli.py +0 -0
- {schenesort-2.1.1 → schenesort-2.2.0}/tests/test_sanitise.py +0 -0
- {schenesort-2.1.1 → schenesort-2.2.0}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: schenesort
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Wallpaper collection management CLI tool
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Requires-Python: >=3.13
|
|
@@ -12,20 +12,40 @@ Requires-Dist: textual>=0.95.0
|
|
|
12
12
|
Requires-Dist: typer>=0.21.1
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
|
|
15
|
-
# Schenesort v2.
|
|
15
|
+
# Schenesort v2.2.0
|
|
16
16
|
|
|
17
|
-
A CLI tool for managing wallpaper collections with
|
|
17
|
+
A CLI tool for managing wallpaper collections with model generated metadata, terminal UI browsing, and SQLite-based
|
|
18
|
+
querying.
|
|
19
|
+
|
|
20
|
+
schenesort takes a directory of random wallpapers, with random filenames, and uses olama with a decent vision model to
|
|
21
|
+
- look at each wallpaper
|
|
22
|
+
- rename the wallpaper to something sensible
|
|
23
|
+
- drop a XMP sidecar with metadata about the file
|
|
24
|
+
|
|
25
|
+
Once you have a collection of wallpapers re-named with metadata sidecars, run the indexer over it to create a sqlitedb
|
|
26
|
+
that can be queried to retrieve suggestions based on tags, colours, names and the like. Then use `get` to get a
|
|
27
|
+
wallpaper path `feh $(schenesort get -1 -p)` or `hyprctl hyprpaper wallpaper "eDP-1,$(schenesort get -1 -p)"`
|
|
28
|
+
|
|
29
|
+
schenesort also provides a bunch of utility commands to satisfy a gooner collection.
|
|
18
30
|
|
|
19
31
|
## Installation
|
|
20
32
|
|
|
21
33
|
```bash
|
|
34
|
+
uv tool install schenesort
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
For development:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
git clone https://github.com/sthysel/schenesort.git
|
|
41
|
+
cd schenesort
|
|
22
42
|
uv sync
|
|
23
43
|
```
|
|
24
44
|
|
|
25
45
|
## Quick Start
|
|
26
46
|
|
|
27
47
|
```bash
|
|
28
|
-
# Generate
|
|
48
|
+
# Generate metadata for images
|
|
29
49
|
schenesort metadata generate ~/wallpapers -r
|
|
30
50
|
|
|
31
51
|
# Browse with TUI
|
|
@@ -67,8 +87,16 @@ Browse your wallpaper collection with image preview and metadata display:
|
|
|
67
87
|
```bash
|
|
68
88
|
schenesort browse ~/wallpapers
|
|
69
89
|
schenesort browse ~/wallpapers -r # recursive
|
|
90
|
+
schenesort browse # uses paths.wallpaper from config
|
|
91
|
+
schenesort get --mood peaceful -b # browse query results
|
|
70
92
|
```
|
|
71
93
|
|
|
94
|
+

|
|
95
|
+
|
|
96
|
+

|
|
97
|
+
|
|
98
|
+

|
|
99
|
+
|
|
72
100
|
**Keyboard shortcuts:**
|
|
73
101
|
| Key | Action |
|
|
74
102
|
|--------------|----------------|
|
|
@@ -104,6 +132,10 @@ schenesort get --random -n 10 # 10 random wallpapers
|
|
|
104
132
|
schenesort get -1 # single random wallpaper
|
|
105
133
|
schenesort get -1 --mood dramatic # random with filter
|
|
106
134
|
|
|
135
|
+
# Browse results in TUI
|
|
136
|
+
schenesort get --mood peaceful --browse # open matches in browser
|
|
137
|
+
schenesort get --style photography -b # short form
|
|
138
|
+
|
|
107
139
|
# For scripting (paths only)
|
|
108
140
|
schenesort get -1 -p # just the path
|
|
109
141
|
feh $(schenesort get -1 -p) # set random wallpaper
|
|
@@ -304,15 +336,15 @@ Metadata is stored in standard XMP format, compatible with digiKam, darktable, a
|
|
|
304
336
|
|
|
305
337
|
Images are tagged with recommended screen sizes based on resolution:
|
|
306
338
|
|
|
307
|
-
| Screen
|
|
308
|
-
|
|
309
|
-
| 8K
|
|
310
|
-
| 5K
|
|
311
|
-
| 4K
|
|
312
|
-
| Ultrawide 4K
|
|
313
|
-
| Ultrawide 1440p | 3440x1440
|
|
314
|
-
| 1440p
|
|
315
|
-
| 1080p
|
|
316
|
-
| 720p
|
|
339
|
+
| Screen | Resolution |
|
|
340
|
+
|-----------------|------------|
|
|
341
|
+
| 8K | 7680x4320 |
|
|
342
|
+
| 5K | 5120x2880 |
|
|
343
|
+
| 4K | 3840x2160 |
|
|
344
|
+
| Ultrawide 4K | 5120x2160 |
|
|
345
|
+
| Ultrawide 1440p | 3440x1440 |
|
|
346
|
+
| 1440p | 2560x1440 |
|
|
347
|
+
| 1080p | 1920x1080 |
|
|
348
|
+
| 720p | 1280x720 |
|
|
317
349
|
|
|
318
350
|
An image is recommended for a screen size if it can cover the screen without upscaling.
|
|
@@ -1,17 +1,37 @@
|
|
|
1
|
-
# Schenesort v2.
|
|
1
|
+
# Schenesort v2.2.0
|
|
2
2
|
|
|
3
|
-
A CLI tool for managing wallpaper collections with
|
|
3
|
+
A CLI tool for managing wallpaper collections with model generated metadata, terminal UI browsing, and SQLite-based
|
|
4
|
+
querying.
|
|
5
|
+
|
|
6
|
+
schenesort takes a directory of random wallpapers, with random filenames, and uses olama with a decent vision model to
|
|
7
|
+
- look at each wallpaper
|
|
8
|
+
- rename the wallpaper to something sensible
|
|
9
|
+
- drop a XMP sidecar with metadata about the file
|
|
10
|
+
|
|
11
|
+
Once you have a collection of wallpapers re-named with metadata sidecars, run the indexer over it to create a sqlitedb
|
|
12
|
+
that can be queried to retrieve suggestions based on tags, colours, names and the like. Then use `get` to get a
|
|
13
|
+
wallpaper path `feh $(schenesort get -1 -p)` or `hyprctl hyprpaper wallpaper "eDP-1,$(schenesort get -1 -p)"`
|
|
14
|
+
|
|
15
|
+
schenesort also provides a bunch of utility commands to satisfy a gooner collection.
|
|
4
16
|
|
|
5
17
|
## Installation
|
|
6
18
|
|
|
7
19
|
```bash
|
|
20
|
+
uv tool install schenesort
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
For development:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
git clone https://github.com/sthysel/schenesort.git
|
|
27
|
+
cd schenesort
|
|
8
28
|
uv sync
|
|
9
29
|
```
|
|
10
30
|
|
|
11
31
|
## Quick Start
|
|
12
32
|
|
|
13
33
|
```bash
|
|
14
|
-
# Generate
|
|
34
|
+
# Generate metadata for images
|
|
15
35
|
schenesort metadata generate ~/wallpapers -r
|
|
16
36
|
|
|
17
37
|
# Browse with TUI
|
|
@@ -53,8 +73,16 @@ Browse your wallpaper collection with image preview and metadata display:
|
|
|
53
73
|
```bash
|
|
54
74
|
schenesort browse ~/wallpapers
|
|
55
75
|
schenesort browse ~/wallpapers -r # recursive
|
|
76
|
+
schenesort browse # uses paths.wallpaper from config
|
|
77
|
+
schenesort get --mood peaceful -b # browse query results
|
|
56
78
|
```
|
|
57
79
|
|
|
80
|
+

|
|
81
|
+
|
|
82
|
+

|
|
83
|
+
|
|
84
|
+

|
|
85
|
+
|
|
58
86
|
**Keyboard shortcuts:**
|
|
59
87
|
| Key | Action |
|
|
60
88
|
|--------------|----------------|
|
|
@@ -90,6 +118,10 @@ schenesort get --random -n 10 # 10 random wallpapers
|
|
|
90
118
|
schenesort get -1 # single random wallpaper
|
|
91
119
|
schenesort get -1 --mood dramatic # random with filter
|
|
92
120
|
|
|
121
|
+
# Browse results in TUI
|
|
122
|
+
schenesort get --mood peaceful --browse # open matches in browser
|
|
123
|
+
schenesort get --style photography -b # short form
|
|
124
|
+
|
|
93
125
|
# For scripting (paths only)
|
|
94
126
|
schenesort get -1 -p # just the path
|
|
95
127
|
feh $(schenesort get -1 -p) # set random wallpaper
|
|
@@ -290,15 +322,15 @@ Metadata is stored in standard XMP format, compatible with digiKam, darktable, a
|
|
|
290
322
|
|
|
291
323
|
Images are tagged with recommended screen sizes based on resolution:
|
|
292
324
|
|
|
293
|
-
| Screen
|
|
294
|
-
|
|
295
|
-
| 8K
|
|
296
|
-
| 5K
|
|
297
|
-
| 4K
|
|
298
|
-
| Ultrawide 4K
|
|
299
|
-
| Ultrawide 1440p | 3440x1440
|
|
300
|
-
| 1440p
|
|
301
|
-
| 1080p
|
|
302
|
-
| 720p
|
|
325
|
+
| Screen | Resolution |
|
|
326
|
+
|-----------------|------------|
|
|
327
|
+
| 8K | 7680x4320 |
|
|
328
|
+
| 5K | 5120x2880 |
|
|
329
|
+
| 4K | 3840x2160 |
|
|
330
|
+
| Ultrawide 4K | 5120x2160 |
|
|
331
|
+
| Ultrawide 1440p | 3440x1440 |
|
|
332
|
+
| 1440p | 2560x1440 |
|
|
333
|
+
| 1080p | 1920x1080 |
|
|
334
|
+
| 720p | 1280x720 |
|
|
303
335
|
|
|
304
336
|
An image is recommended for a screen size if it can cover the screen without upscaling.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "schenesort"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.2.0"
|
|
4
4
|
description = "Wallpaper collection management CLI tool"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.13"
|
|
@@ -56,7 +56,7 @@ testpaths = ["tests"]
|
|
|
56
56
|
pythonpath = ["src"]
|
|
57
57
|
|
|
58
58
|
[tool.bumpversion]
|
|
59
|
-
current_version = "2.
|
|
59
|
+
current_version = "2.2.0"
|
|
60
60
|
commit = true
|
|
61
61
|
tag = true
|
|
62
62
|
tag_name = "v{new_version}"
|
|
@@ -444,6 +444,9 @@ def get(
|
|
|
444
444
|
paths_only: Annotated[
|
|
445
445
|
bool, typer.Option("--paths-only", "-p", help="Output only file paths (for scripting)")
|
|
446
446
|
] = False,
|
|
447
|
+
browse: Annotated[
|
|
448
|
+
bool, typer.Option("--browse", "-b", help="Open results in TUI browser")
|
|
449
|
+
] = False,
|
|
447
450
|
) -> None:
|
|
448
451
|
"""Query wallpapers by metadata attributes."""
|
|
449
452
|
from schenesort.db import WallpaperDB
|
|
@@ -472,7 +475,13 @@ def get(
|
|
|
472
475
|
typer.echo("No wallpapers found matching criteria.", err=True)
|
|
473
476
|
raise typer.Exit(1)
|
|
474
477
|
|
|
475
|
-
if
|
|
478
|
+
if browse:
|
|
479
|
+
from schenesort.tui import WallpaperBrowser
|
|
480
|
+
|
|
481
|
+
files = [Path(r["path"]) for r in results]
|
|
482
|
+
app_instance = WallpaperBrowser(files=files)
|
|
483
|
+
app_instance.run()
|
|
484
|
+
elif paths_only:
|
|
476
485
|
for r in results:
|
|
477
486
|
typer.echo(r["path"])
|
|
478
487
|
else:
|
|
@@ -542,7 +551,10 @@ def stats() -> None:
|
|
|
542
551
|
|
|
543
552
|
@app.command()
|
|
544
553
|
def browse(
|
|
545
|
-
path: Annotated[
|
|
554
|
+
path: Annotated[
|
|
555
|
+
Path | None,
|
|
556
|
+
typer.Argument(help="Directory or file to browse (default: config wallpaper path)"),
|
|
557
|
+
] = None,
|
|
546
558
|
recursive: Annotated[
|
|
547
559
|
bool, typer.Option("--recursive", "-r", help="Browse directories recursively")
|
|
548
560
|
] = False,
|
|
@@ -550,6 +562,15 @@ def browse(
|
|
|
550
562
|
"""Browse wallpapers in a terminal UI with image preview and metadata display."""
|
|
551
563
|
from schenesort.tui import WallpaperBrowser
|
|
552
564
|
|
|
565
|
+
if path is None:
|
|
566
|
+
cfg = load_config()
|
|
567
|
+
if cfg.wallpaper_path:
|
|
568
|
+
path = Path(cfg.wallpaper_path).expanduser()
|
|
569
|
+
else:
|
|
570
|
+
typer.echo("Error: No path provided and no wallpaper path configured.", err=True)
|
|
571
|
+
typer.echo("Set paths.wallpaper in config or provide a path argument.", err=True)
|
|
572
|
+
raise typer.Exit(1)
|
|
573
|
+
|
|
553
574
|
path = path.resolve()
|
|
554
575
|
|
|
555
576
|
if not path.exists():
|
|
@@ -572,22 +593,17 @@ def config(
|
|
|
572
593
|
config_path = get_config_path()
|
|
573
594
|
|
|
574
595
|
if create:
|
|
596
|
+
already_existed = config_path.exists()
|
|
575
597
|
path = create_default_config()
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
598
|
+
typer.echo(f"Config file: {path}")
|
|
599
|
+
typer.echo("(already existed)" if already_existed else "(created)")
|
|
600
|
+
|
|
601
|
+
if config_path.exists():
|
|
602
|
+
typer.echo(f"Config file: {config_path}\n")
|
|
603
|
+
typer.echo(config_path.read_text())
|
|
604
|
+
elif not create:
|
|
581
605
|
typer.echo(f"Config file: {config_path}")
|
|
582
|
-
|
|
583
|
-
typer.echo("\nCurrent settings:")
|
|
584
|
-
cfg = load_config()
|
|
585
|
-
typer.echo(f" ollama.host: {cfg.ollama_host or '(default: localhost:11434)'}")
|
|
586
|
-
typer.echo(f" ollama.model: {cfg.ollama_model}")
|
|
587
|
-
if cfg.wallpaper_path:
|
|
588
|
-
typer.echo(f" paths.wallpaper: {cfg.wallpaper_path}")
|
|
589
|
-
else:
|
|
590
|
-
typer.echo("(file does not exist, use --create to create)")
|
|
606
|
+
typer.echo("(file does not exist, use --create to create)")
|
|
591
607
|
|
|
592
608
|
|
|
593
609
|
DEFAULT_MODEL = "llava"
|
|
@@ -1108,20 +1124,27 @@ def metadata_generate(
|
|
|
1108
1124
|
metadata = existing
|
|
1109
1125
|
metadata.description = str(description)
|
|
1110
1126
|
metadata.ai_model = effective_model
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
if isinstance(
|
|
1116
|
-
metadata.
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
if isinstance(
|
|
1122
|
-
metadata.
|
|
1123
|
-
|
|
1124
|
-
|
|
1127
|
+
scene = result.get("scene")
|
|
1128
|
+
if isinstance(scene, str):
|
|
1129
|
+
metadata.scene = scene
|
|
1130
|
+
tags = result.get("tags")
|
|
1131
|
+
if isinstance(tags, list):
|
|
1132
|
+
metadata.tags = tags
|
|
1133
|
+
mood = result.get("mood")
|
|
1134
|
+
if isinstance(mood, list):
|
|
1135
|
+
metadata.mood = mood
|
|
1136
|
+
style = result.get("style")
|
|
1137
|
+
if isinstance(style, str):
|
|
1138
|
+
metadata.style = style
|
|
1139
|
+
colors = result.get("colors")
|
|
1140
|
+
if isinstance(colors, list):
|
|
1141
|
+
metadata.colors = colors
|
|
1142
|
+
time_val = result.get("time")
|
|
1143
|
+
if isinstance(time_val, str):
|
|
1144
|
+
metadata.time_of_day = time_val
|
|
1145
|
+
subject = result.get("subject")
|
|
1146
|
+
if isinstance(subject, str):
|
|
1147
|
+
metadata.subject = subject
|
|
1125
1148
|
|
|
1126
1149
|
# Add image dimensions
|
|
1127
1150
|
width, height = get_image_dimensions(target_path)
|
|
@@ -73,7 +73,15 @@ def load_config() -> Config:
|
|
|
73
73
|
|
|
74
74
|
return config
|
|
75
75
|
|
|
76
|
-
except
|
|
76
|
+
except tomllib.TOMLDecodeError as e:
|
|
77
|
+
import sys
|
|
78
|
+
|
|
79
|
+
print(f"Warning: Failed to parse config file: {e}", file=sys.stderr)
|
|
80
|
+
return Config()
|
|
81
|
+
except Exception as e:
|
|
82
|
+
import sys
|
|
83
|
+
|
|
84
|
+
print(f"Warning: Failed to load config file: {e}", file=sys.stderr)
|
|
77
85
|
return Config()
|
|
78
86
|
|
|
79
87
|
|
|
@@ -73,10 +73,16 @@ class WallpaperBrowser(App):
|
|
|
73
73
|
Binding("end", "last_image", "Last", show=False),
|
|
74
74
|
]
|
|
75
75
|
|
|
76
|
-
def __init__(
|
|
76
|
+
def __init__(
|
|
77
|
+
self,
|
|
78
|
+
path: Path | None = None,
|
|
79
|
+
recursive: bool = False,
|
|
80
|
+
files: list[Path] | None = None,
|
|
81
|
+
) -> None:
|
|
77
82
|
super().__init__()
|
|
78
83
|
self._base_path = path
|
|
79
84
|
self._recursive = recursive
|
|
85
|
+
self._files = files # Pre-specified file list (from query results)
|
|
80
86
|
self._images: list[Path] = []
|
|
81
87
|
self._current_index: int = 0
|
|
82
88
|
|
|
@@ -99,7 +105,15 @@ class WallpaperBrowser(App):
|
|
|
99
105
|
self._update_status("No images found", "")
|
|
100
106
|
|
|
101
107
|
def _load_images(self) -> None:
|
|
102
|
-
"""Load list of images from the specified path."""
|
|
108
|
+
"""Load list of images from the specified path or file list."""
|
|
109
|
+
# If files were provided directly (e.g., from query results), use them
|
|
110
|
+
if self._files:
|
|
111
|
+
self._images = [f for f in self._files if f.exists()]
|
|
112
|
+
return
|
|
113
|
+
|
|
114
|
+
if self._base_path is None:
|
|
115
|
+
return
|
|
116
|
+
|
|
103
117
|
if self._base_path.is_file():
|
|
104
118
|
if self._base_path.suffix.lower() in VALID_IMAGE_EXTENSIONS:
|
|
105
119
|
self._images = [self._base_path]
|
|
@@ -128,12 +142,11 @@ class WallpaperBrowser(App):
|
|
|
128
142
|
panel.update_metadata(metadata, current_image.name)
|
|
129
143
|
|
|
130
144
|
# Update status
|
|
131
|
-
self.
|
|
132
|
-
str(current_image.relative_to(self._base_path))
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
)
|
|
145
|
+
if self._base_path and current_image.is_relative_to(self._base_path):
|
|
146
|
+
display_path = str(current_image.relative_to(self._base_path))
|
|
147
|
+
else:
|
|
148
|
+
display_path = current_image.name
|
|
149
|
+
self._update_status(display_path, f"{self._current_index + 1}/{len(self._images)}")
|
|
137
150
|
|
|
138
151
|
def _update_status(self, left: str, right: str) -> None:
|
|
139
152
|
"""Update the status bar."""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|