desertislandutils 0.1.0__py3-none-any.whl → 0.4.3__py3-none-any.whl

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.
@@ -0,0 +1,179 @@
1
+ Metadata-Version: 2.4
2
+ Name: desertislandutils
3
+ Version: 0.4.3
4
+ Summary: A collection of personal convenience utilities
5
+ Project-URL: Homepage, https://github.com/mahiki/desertislandutils
6
+ Project-URL: Repository, https://github.com/mahiki/desertislandutils
7
+ Project-URL: Issues, https://github.com/mahiki/desertislandutils/issues
8
+ Author-email: mahiki <mahiki@users.noreply.github.com>
9
+ License: MIT
10
+ Requires-Python: >=3.11
11
+ Requires-Dist: argparse>=1.4.0
12
+ Requires-Dist: gitpython>=3.1.27
13
+ Requires-Dist: pendulum>=3.0.0
14
+ Requires-Dist: typer>=0.12.0
15
+ Provides-Extra: dev
16
+ Requires-Dist: ptpython>=3.0.23; extra == 'dev'
17
+ Provides-Extra: test
18
+ Requires-Dist: pytest>=7.2.2; extra == 'test'
19
+ Description-Content-Type: text/markdown
20
+
21
+ # desertislandutils
22
+
23
+ A collection of personal convenience utilities for managing parallel directory structures and ISO week numbers. Written in Python because it's far better than shell scripting!
24
+
25
+ ## Installation
26
+
27
+ Install globally using `uv`:
28
+
29
+ ```sh
30
+ uv tool install desertislandutils
31
+ ```
32
+
33
+ Update to the latest version:
34
+
35
+ ```sh
36
+ uv tool upgrade desertislandutils
37
+ ```
38
+
39
+ ## The Utils
40
+
41
+ ### toobigdatadoc (`too`)
42
+
43
+ Manage parallel directory structures for separating text files from large binary files and datasets. Creates symlinked folders under `HOME/{toobig|toodata|toodoc}`:
44
+
45
+ - `toobig` - Large files excluded from backups
46
+ - `toodata` - Small-ish data files
47
+ - `toodoc` - Binary files like PDFs and images
48
+
49
+ ```
50
+ $HOME
51
+ |-- toobig
52
+ |-- # replicated folder paths with large files here, assume not to be backed up
53
+ |-- toodata
54
+ |-- # small-ish data files in support of the parallel root
55
+ |-- toodoc
56
+ |-- # usually pdfs or image files
57
+ ```
58
+
59
+ **Usage:**
60
+
61
+ ```sh
62
+ too --help
63
+
64
+ usage: too [-h] {big,data,doc}
65
+
66
+ Create symlinked parallel folders under HOME/{toobig|toodata|toodoc}, to
67
+ contain data/binary files outside of git repo or away from source/text files.
68
+
69
+ positional arguments:
70
+ {big,data,doc} large files to exclude from backup, smallish datasets,
71
+ binary files like pdf
72
+
73
+ options:
74
+ -h, --help show this help message and exit
75
+ ```
76
+
77
+ ### weeknumber (`wn`)
78
+
79
+ Get ISO year week numbers in YYYY-WDD format. Default weekend day is Saturday.
80
+
81
+ **Usage:**
82
+
83
+ ```sh
84
+ wn --help
85
+
86
+ Usage: wn [OPTIONS] [DATE]
87
+
88
+ ISO year week number of a date as YYYY-"W"WW. Default weekend day is Saturday.
89
+
90
+ Example:
91
+
92
+ $> wn 'Jul 22 2020' --last
93
+
94
+ 2020-W29
95
+
96
+ ╭─ Arguments ────────────────────────────────────────────────────────────────╮
97
+ │ date [DATE] A text expression of date, ex: 'November 27', or │
98
+ │ 2112-07-29. Default is today's in current TZ. │
99
+ │ [default: (dynamic)] │
100
+ ╰────────────────────────────────────────────────────────────────────────────╯
101
+ ╭─ Options ──────────────────────────────────────────────────────────────────╮
102
+ │ --sunday Week end is Saturday by default, this flag sets │
103
+ │ Sunday weekend day (ISO standard). │
104
+ │ --last Give week number of most recently completed week │
105
+ │ (overrides DATE argument). │
106
+ │ --verbose -v Full parsed date details for verification. │
107
+ │ --install-completion Install completion for the current shell. │
108
+ │ --show-completion Show completion for the current shell, to copy it │
109
+ │ or customize the installation. │
110
+ │ --help Show this message and exit. │
111
+ ╰────────────────────────────────────────────────────────────────────────────╯
112
+ ```
113
+
114
+ **Examples:**
115
+
116
+ ```sh
117
+ # Get current week number
118
+ wn
119
+
120
+ # Get week number for a specific date
121
+ wn 'Jul 22'
122
+
123
+ # Get last completed week number
124
+ wn --last
125
+
126
+ # Parse a specific date with details
127
+ wn 'November 27 2024' --verbose
128
+ ```
129
+
130
+ ---
131
+
132
+ ## Development
133
+
134
+ Built with modern Python tooling:
135
+
136
+ - **Build system:** `uv`
137
+ - **Deploy:** PyPI via GitHub Actions CI/CD
138
+ - **Package manager:** `uv`
139
+
140
+ ### Setup
141
+
142
+ ```sh
143
+ # Clone the repository
144
+ git clone https://github.com/mahiki/desertislandutils.git
145
+ cd desertislandutils
146
+
147
+ # Install dependencies (including dev extras)
148
+ uv sync --all-extras
149
+ ```
150
+
151
+ ### Testing
152
+
153
+ ```sh
154
+ # Run tests
155
+ just test
156
+
157
+ # Or directly with uv
158
+ uv run --extra test pytest --disable-warnings --verbose
159
+ ```
160
+
161
+ ### Local Development
162
+
163
+ ```sh
164
+ # Run commands directly from source
165
+ uv run wn --help
166
+ uv run too --help
167
+ ```
168
+
169
+ ### Project Tasks
170
+
171
+ See the `justfile` for available commands:
172
+
173
+ ```sh
174
+ just --list
175
+ ```
176
+
177
+ ## License
178
+
179
+ MIT
@@ -0,0 +1,9 @@
1
+ src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ src/toobigdatadoc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ src/toobigdatadoc/too.py,sha256=PF8ycDOfrk6yzlQkajAEYQOB2G7FGsBWvHcDMobdwTg,2848
4
+ src/weeknumber/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ src/weeknumber/wn.py,sha256=uqKt-oXhLKkKeK35xyjx1vakjAIKVZniQksycbF1PE8,2908
6
+ desertislandutils-0.4.3.dist-info/METADATA,sha256=UAK_ixp1LWc102kF_RKhIOclkmIXs6OCmMjVkSmqKFE,5827
7
+ desertislandutils-0.4.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
8
+ desertislandutils-0.4.3.dist-info/entry_points.txt,sha256=5TRbM9NEaDJ_d-cfZprBLYMhblbwTp2Zn966FTkwVM8,78
9
+ desertislandutils-0.4.3.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry 1.0.8
2
+ Generator: hatchling 1.28.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ too = src.toobigdatadoc.too:main
3
+ wn = src.weeknumber.wn:app
src/__init__.py ADDED
File without changes
@@ -1 +0,0 @@
1
- __version__ = '0.1.0'
src/toobigdatadoc/too.py CHANGED
@@ -1,36 +1,42 @@
1
- """Create a symlinked folder in the current directory pointing to 'too' project root directory.
1
+ """A command line utility to create a symlinked folder in the current directory, pointing to the 'too' project root directory.
2
2
 
3
- I like to keep source code and notes as text files, with associated documents, data, and images stored separately on a parallel file structure. The main benefits are browsing through directories and scanning the notes contents visually, and looking through filenames without a lot of clutter.
3
+ For the purpose of keeping source code and notes as text files, with associated documents, data, and images stored separately on a parallel file structure. The main benefits are browsing through directories and scanning the notes contents visually, and looking through filenames without a lot of clutter.
4
+
5
+ NOTE: git repos can be moved anywhere, because their path is uniquely definied by root name.
4
6
 
5
7
  Usage:
6
-
8
+
7
9
  too big|data|doc
8
10
  """
9
11
  # TODO: [--verbose, -v] version print
10
- # folder created: ../../../../../toodoc/datasci/biq/biq-206/bigtest
11
- # symlink: doc -> ../../../../../toodoc/datasci/biq/biq-206/bigtest
12
+ # folder created: $HOME/toodoc/datasci/biq/biq-206/bigtest
13
+ # symlink: doc -> $HOME/toodoc/datasci/biq/biq-206/bigtest
12
14
 
13
15
  from argparse import ArgumentParser
14
16
  from git import Repo, exc
15
17
  from pathlib import Path
16
18
 
17
- def call_the_parser():
19
+ POSITIONAL_ARGS = {
20
+ 'big': 'toobig'
21
+ , 'data': 'toodata'
22
+ , 'doc': 'toodoc'
23
+ }
24
+
25
+ def cli_parser(args = None):
26
+ if args: args = [args] # must do for test calls
27
+ arg_choices = list(POSITIONAL_ARGS)
18
28
  parser = ArgumentParser(
19
- prog = "too"
20
- , description = "Create symlinked parallel folders to contain data/binary files outside of\n git repo or away from source/text files."
29
+ prog = "too"
30
+ , description = "Create symlinked parallel folders under HOME/{toobig|toodata|toodoc}, to contain data/binary files outside of\n git repo or away from source/text files."
21
31
  )
22
-
23
32
  parser.add_argument(
24
- 'arg1'
25
- , choices = ['big', 'data', 'doc']
33
+ 'too_dir'
34
+ , choices = arg_choices
26
35
  , help = "large files to exclude from backup, smallish datasets, binary files like pdf"
27
36
  )
37
+ args = parser.parse_args(args)
38
+ return args.too_dir
28
39
 
29
- args = parser.parse_args()
30
-
31
- return args.arg1
32
-
33
- # TODO: combine is_git_repo && repo_root
34
40
  def is_git_repo(path):
35
41
  try:
36
42
  _ = Repo(path, search_parent_directories=True)
@@ -45,18 +51,9 @@ def repo_root(repo_path):
45
51
  except exc.InvalidGitRepositoryError:
46
52
  return None
47
53
 
48
- def top_dir_rel_path(tbdd):
49
- switch = {
50
- 'big': 'toobig'
51
- , 'data': 'toodata'
52
- , 'doc': 'toodoc'
53
- }
54
- topname = switch.get(tbdd, "ERROR")
55
- relative_path_home = str(Path.cwd().relative_to(Path.home()))
56
- levels_home = len(relative_path_home.split('/'))
57
- dots_home = '../' * levels_home
58
-
59
- return Path(dots_home) / topname
54
+ def top_dir_path(tbdd):
55
+ topname = POSITIONAL_ARGS.get(tbdd, "ERROR")
56
+ return Path.home() / topname
60
57
 
61
58
  def make_topdir_and_link(new_path):
62
59
  try:
@@ -68,21 +65,23 @@ def make_topdir_and_link(new_path):
68
65
  except FileExistsError:
69
66
  print("Symlink already exists")
70
67
 
71
- def too_rel_path(any_path):
68
+ def too_path(any_path):
72
69
  if is_git_repo(any_path):
73
70
  repo_root_path = repo_root(any_path)
74
71
  path_from_root = any_path.relative_to(repo_root_path)
75
- return top_dir_rel_path(TOPDIR_NAME) / repo_root_path.name / path_from_root
72
+ return top_dir_path(TOPDIR_NAME) / repo_root_path.name / path_from_root
76
73
  else:
77
74
  path_from_home = any_path.relative_to(Path.home())
78
- return top_dir_rel_path(TOPDIR_NAME) / path_from_home
75
+ return top_dir_path(TOPDIR_NAME) / path_from_home
79
76
 
80
77
 
81
- def main():
78
+ def main(too_dir = None):
82
79
  global TOPDIR_NAME
83
- TOPDIR_NAME = call_the_parser()
84
80
 
85
- make_topdir_and_link(too_rel_path(Path.cwd()))
81
+ too_dir = cli_parser(too_dir)
82
+ TOPDIR_NAME = too_dir
83
+
84
+ make_topdir_and_link(too_path(Path.cwd()))
86
85
 
87
86
  if __name__ == "__main__":
88
87
  main()
File without changes
src/weeknumber/wn.py ADDED
@@ -0,0 +1,85 @@
1
+ """
2
+ CLI utility that gives the ISO reporting week for a given date.
3
+ Option allows week ending day of Saturday or Sunday.
4
+ Option for week number of most recently completed week.
5
+ Example: wn --last
6
+ 2023-W48
7
+ """
8
+
9
+ import pendulum
10
+ from pendulum.parsing.exceptions import ParserError
11
+ import typer
12
+ from typing_extensions import Annotated, Optional, List
13
+
14
+ app = typer.Typer()
15
+
16
+ def input_date_validate(value: str):
17
+ try:
18
+ pendulum.parse(value, strict=False)
19
+ except ParserError as ex:
20
+ raise typer.BadParameter(f"{ex}, try YYYY-MM-DD format.")
21
+ return value
22
+
23
+ def today_datestring():
24
+ return pendulum.now().to_date_string()
25
+
26
+ def week_number_string(date, sunday_weekend = False):
27
+ if sunday_weekend:
28
+ return date.strftime("%G-W%V")
29
+ else:
30
+ return date.add(days=1).strftime("%G-W%V")
31
+
32
+ def verbose_output(date, parsed_date, sunday_weekend, last_week):
33
+ weekend_day = "Sunday" if sunday_weekend else "Saturday"
34
+
35
+ if sunday_weekend:
36
+ weekend_date = parsed_date.add(days=-1).next(pendulum.SUNDAY)
37
+ else:
38
+ weekend_date = parsed_date.add(days=-1).next(pendulum.SATURDAY)
39
+
40
+ if last_week: weekend_date = weekend_date.subtract(weeks=1)
41
+
42
+ typer.echo(f"Input date string: {date}")
43
+ typer.echo(f"Timezone: {pendulum.now().timezone.name}")
44
+ typer.echo(f"Parsed date: {parsed_date.to_date_string()}")
45
+ typer.echo(f"Last week flag: {last_week}")
46
+ typer.echo(f"Week end day: {weekend_day}")
47
+ typer.echo(f"Week end date: {weekend_date.to_date_string()}")
48
+
49
+
50
+ @app.command()
51
+ def main(
52
+ date: Annotated[str
53
+ , typer.Argument(
54
+ callback=input_date_validate
55
+ , help="A text expression of date, ex: 'November 27', or 2112-07-29. Default is today's in current TZ."
56
+ , default_factory=today_datestring)]
57
+ , sunday_weekend: Annotated[bool
58
+ , typer.Option(
59
+ "--sunday"
60
+ , help="Week end is Saturday by default, this flag sets Sunday weekend day (ISO standard).")] = False
61
+ , last_week: Annotated[bool
62
+ , typer.Option(
63
+ "--last"
64
+ , help="Give week number of most recently completed week (overrides DATE argument).")] = False
65
+ , verbose: Annotated[bool
66
+ , typer.Option(
67
+ "--verbose", "-v"
68
+ , help="Full parsed date details for verification."
69
+ )] = False
70
+ ):
71
+ """
72
+ ISO year week number of a date as YYYY-"W"WW. Default weekend day is Saturday.\n
73
+ Example:\n
74
+ $> wn 'Jul 22 2020' --last\n
75
+ 2020-W29
76
+ """
77
+ parsed_date = pendulum.parse(date, strict=False)
78
+ if verbose: verbose_output(date, parsed_date, sunday_weekend, last_week)
79
+
80
+ if last_week:
81
+ result = week_number_string(parsed_date.subtract(weeks=1), sunday_weekend=sunday_weekend)
82
+ else:
83
+ result = week_number_string(parsed_date, sunday_weekend=sunday_weekend)
84
+
85
+ typer.echo(result)
@@ -1,14 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: desertislandutils
3
- Version: 0.1.0
4
- Summary: A collection of personal convenience utilities
5
- License: MIT
6
- Author: mahiki
7
- Author-email: mahiki@users.noreply.github.com
8
- Requires-Python: >=3.9,<4.0
9
- Classifier: License :: OSI Approved :: MIT License
10
- Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.10
12
- Classifier: Programming Language :: Python :: 3.9
13
- Requires-Dist: GitPython (>=3.1.27,<4.0.0)
14
- Requires-Dist: argparse (>=1.4.0,<2.0.0)
@@ -1,6 +0,0 @@
1
- src/toobigdatadoc/__init__.py,sha256=IMjkMO3twhQzluVTo8Z6rE7Eg-9U79_LGKMcsWLKBkY,22
2
- src/toobigdatadoc/too.py,sha256=0um45KMmed7mNq_PKpj5ZcbDi9pTBmd5tTdylf0xm8E,2794
3
- desertislandutils-0.1.0.dist-info/entry_points.txt,sha256=WQtlzk18d_KMRIIwBI-vb8gj2Vw0fQnxNsSQKur_S7k,50
4
- desertislandutils-0.1.0.dist-info/WHEEL,sha256=DA86_h4QwwzGeRoz62o1svYt5kGEXpoUTuTtwzoTb30,83
5
- desertislandutils-0.1.0.dist-info/METADATA,sha256=SkcYaP9TBU5gWJjeTtO4odFNn_JjfBVXAU6NZuO9JrE,503
6
- desertislandutils-0.1.0.dist-info/RECORD,,
@@ -1,3 +0,0 @@
1
- [console_scripts]
2
- too=src.toobigdatadoc.too:main
3
-