-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
245 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
name: Upload Python Package | ||
on: | ||
push: | ||
tags: | ||
- '[0-9]+\.[0-9]+\.[0-9]+' | ||
- '[0-9]+\.[0-9]+\.[0-9]+-?rc\.?[0-9]+' | ||
|
||
jobs: | ||
pypi: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v3 | ||
with: | ||
fetch-depth: 0 | ||
- name: Replace media paths in README.md | ||
run: sed -E 's#(\]\((asset/[a-zA-Z0-9._-]+))#](https://github.com/CZ-NIC/mininterface/blob/main/\2?raw=True#g' README.md | less > README.md.tmp && mv README.md.tmp README.md | ||
- name: Build the package | ||
run: python3 -m pip install --upgrade build && python3 -m build | ||
- name: Publish package | ||
uses: pypa/gh-action-pypi-publish@v1.8.10 | ||
with: | ||
password: ${{ secrets.PYPI_GITHUB_TOUCHTIMESTAMP }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export TAG := `grep version pyproject.toml | pz --search '"(\d+\.\d+\.\d+(?:rc\d+))?"'` | ||
|
||
release: | ||
git tag $(TAG) | ||
git push origin $(TAG) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,80 @@ | ||
XXX asi z toho můžu udělat package na pypi | ||
[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) | ||
|
||
Krusader user action command | ||
`python3 ...gui-touch/gui-touch.py %aList("Selected")%` | ||
Change file timestamps with a dialog window. | ||
|
||
![Gui window](asset/mininterface-gui.avif "Graphical interface") | ||
|
||
GUI automatically fallback to a text interface when display is not available. | ||
|
||
![Text interface](asset/textual.avif "Runs in the terminal") | ||
|
||
|
||
# Installation | ||
|
||
Install with a single command from [PyPi](https://pypi.org/project/touch-timestamp/). | ||
|
||
```bash | ||
pip install touch-timestamp | ||
``` | ||
|
||
Or eventually add [eel](https://github.com/python-eel/Eel) to provide browser-like GUI window. | ||
|
||
```bash | ||
pip install touch-timestamp[eel] | ||
``` | ||
|
||
![Browser interface](asset/eel-gui.avif "Eel interface") | ||
|
||
# Docs | ||
|
||
## Exact date | ||
|
||
When invoked with file paths, the program sets their modification times to the specified time. | ||
|
||
![Gui window](asset/mininterface-gui.avif "Graphical interface") | ||
|
||
## Fetch the time from the file name | ||
|
||
Should you end up with files that keep the date in the file name, use the `--from-name` parameter. | ||
|
||
```bash | ||
$ touch-timestamp 20240828_160619.heic --from-name True | ||
Changed 2001-01-01T12:00:00 → 2024-08-28T16:06:19: 20240828_160619.heic | ||
``` | ||
|
||
## Full help | ||
|
||
Use the `--help` to see full options. | ||
|
||
```bash | ||
$ touch-timestamp --help | ||
usage: Touch [-h] [--eel | --no-eel] [--from-name {True,False}|STR] | ||
[[PATH [PATH ...]]] | ||
|
||
╭─ positional arguments ─────────────────────────────────────────────────────╮ | ||
│ [[PATH [PATH ...]]] │ | ||
│ Files the modification date is to be changed. (default: ) │ | ||
╰────────────────────────────────────────────────────────────────────────────╯ | ||
╭─ options ──────────────────────────────────────────────────────────────────╮ | ||
│ -h, --help │ | ||
│ show this help message and exit │ | ||
│ --eel, --no-eel │ | ||
│ Prefer Eel GUI. (Set the date as in a chromium browser.) (default: │ | ||
│ True) │ | ||
│ --from-name {True,False}|STR │ | ||
│ Fetch the modification time from the file names stem. Set the format │ | ||
│ as for `datetime.strptime` like '%Y%m%d_%H%M%S'. │ | ||
│ If set to True, the format will be auto-detected. │ | ||
│ If a file name does not match the format or the format cannot be │ | ||
│ auto-detected, the file remains unchanged. │ | ||
│ │ | ||
│ │ | ||
│ Ex: `--from-name True 20240827_154252.heic` → modification time = │ | ||
│ 27.8.2024 15:42 (default: False) │ | ||
╰────────────────────────────────────────────────────────────────────────────╯ | ||
``` | ||
|
||
|
||
## Krusader user action | ||
|
||
To change the file timestamps easily from Krusader, import this [user action](extra/touch-timestamp-krusader-useraction.xml): `touch-timestamp %aList("Selected")%` |
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<?xml version="1.0" encoding="UTF-8" ?> | ||
<!DOCTYPE KrusaderUserActions> | ||
<KrusaderUserActions> | ||
<action name="touch-timestamp"> | ||
<title>&touch-timestamp</title> | ||
<tooltip>touch-timestamp</tooltip> | ||
<category>Files</category> | ||
<description>%aList("Selected")%</description> | ||
<command>touch-timestamp %aList("Selected")%</command> | ||
<defaultshortcut>Alt+Shift+T</defaultshortcut> | ||
</action> | ||
</KrusaderUserActions> |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
[build-system] | ||
requires = ["poetry-core>=1.0.0"] | ||
build-backend = "poetry.core.masonry.api" | ||
|
||
[tool.poetry] | ||
name = "touch-timestamp" | ||
version = "0.3.0" | ||
description = "Change file timestamps with a dialog window." | ||
authors = ["Edvard Rejthar <edvard.rejthar@nic.cz>"] | ||
license = "GPL-3.0-or-later" | ||
homepage = "https://github.com/CZ-NIC/touch-timestamp" | ||
readme = "README.md" | ||
|
||
[tool.poetry.dependencies] | ||
python = "^3.10" | ||
mininterface = "*" | ||
|
||
[tool.poetry.extras] | ||
eel = ["eel"] | ||
|
||
[tool.poetry.scripts] | ||
touch-timestamp = "touch_timestamp.touch_timestamp:main" |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
#!/usr/bin/env python3 | ||
from dataclasses import dataclass, field | ||
from datetime import datetime | ||
from os import utime | ||
from pathlib import Path | ||
|
||
import dateutil.parser | ||
from mininterface import run | ||
from tyro.conf import Positional | ||
|
||
try: | ||
from eel import expose, init, start | ||
eel = True | ||
except ImportError: | ||
eel = None | ||
|
||
|
||
DateFormat = str # Use type as of Python3.12 | ||
|
||
|
||
@dataclass | ||
class Env: | ||
files: Positional[list[Path]] = field(default_factory=list) | ||
""" Files the modification date is to be changed. """ | ||
|
||
eel: bool = True | ||
""" Prefer Eel GUI. (Set the date as in a chromium browser.) """ | ||
|
||
from_name: bool | DateFormat = False | ||
""" | ||
Fetch the modification time from the file names stem. Set the format as for `datetime.strptime` like '%Y%m%d_%H%M%S'. | ||
If set to True, the format will be auto-detected. | ||
If a file name does not match the format or the format cannot be auto-detected, the file remains unchanged. | ||
Ex: `--from-name True 20240827_154252.heic` → modification time = 27.8.2024 15:42 | ||
""" | ||
|
||
|
||
def set_files_timestamp(date, time, files: list[str]): | ||
print("Touching files", date, time) | ||
print(", ".join(str(f) for f in files)) | ||
if date and time: | ||
time = dateutil.parser.parse(date + " " + time).timestamp() | ||
[utime(f, (time, time)) for f in files] | ||
return True | ||
|
||
|
||
def run_eel(files): | ||
@expose | ||
def get_len_files(): | ||
return len(files) | ||
|
||
@expose | ||
def get_first_file_date(): | ||
return Path(files[0]).stat().st_mtime | ||
|
||
@expose | ||
def set_timestamp(date, time): | ||
return set_files_timestamp(date, time, files) | ||
|
||
init(Path(__file__).absolute().parent.joinpath('static')) | ||
start('index.html', size=(330, 30), port=0, block=True) | ||
|
||
|
||
def main(): | ||
m = run(Env, prog="Touch") | ||
|
||
if m.env.from_name: | ||
for p in m.env.files: | ||
if m.env.from_name is True: # auto detection | ||
try: | ||
# 20240828_160619.heic -> "20240828 160619" -> "28.8." | ||
dt = dateutil.parser.parse(p.stem.replace("_", "")) | ||
except ValueError: | ||
print(f"Cannot auto detect the date format: {p}") | ||
continue | ||
else: | ||
try: | ||
dt = datetime.strptime(p.stem, m.env.from_name) | ||
except ValueError: | ||
print(f"Does not match the format {m.env.from_name}: {p}") | ||
continue | ||
timestamp = int(dt.timestamp()) | ||
original = datetime.fromtimestamp(p.stat().st_mtime) | ||
utime(str(p), (timestamp, timestamp)) | ||
print(f"Changed {original.isoformat()} → {dt.isoformat()}: {p}") | ||
elif eel and m.env.eel: # set exact date with eel | ||
run_eel(m.env.files) | ||
else: # set exact date with Mininterface | ||
if len(m.env.files) > 1: | ||
title = f"Touch {len(m.env.files)} files" | ||
else: | ||
title = f"Touch {m.env.files[0].name}" | ||
|
||
with m: | ||
m.title = title # NOTE: Changing title does not work | ||
date = datetime.fromtimestamp(Path(m.env.files[0]).stat().st_mtime) | ||
output = {title: {"date": str(date.date()), "time": str(date.time())}} | ||
m.form(output) | ||
set_files_timestamp(output["date"], output["time"], m.env.files) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |