Skip to content

Commit 05cae3e

Browse files
authored
✨ path kwargs (#25)
1 parent 78ac32f commit 05cae3e

File tree

3 files changed

+56
-5
lines changed

3 files changed

+56
-5
lines changed

browsr/_base.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66

77
import math
88
import pathlib
9+
from copy import copy
910
from dataclasses import dataclass
11+
from os import PathLike
1012
from textwrap import dedent
1113
from typing import Any, ClassVar, Dict, List, Optional, Union
1214

@@ -24,11 +26,26 @@
2426
from textual.reactive import reactive, var
2527
from textual.widget import Widget
2628
from textual.widgets import Button, DataTable, Static
29+
from upath import UPath
2730

2831
from browsr._config import favorite_themes
2932
from browsr._utils import FileInfo, handle_github_url
3033

3134

35+
class BrowsrPath(UPath):
36+
"""
37+
A UPath object that can be extended with persisted kwargs
38+
"""
39+
40+
__path_kwargs__: ClassVar[Dict[str, Any]] = {}
41+
42+
def __new__(cls, *args: str | PathLike[Any], **kwargs: Any) -> "BrowsrPath":
43+
"""
44+
Create a new BrowsrPath object
45+
"""
46+
return super().__new__(cls, *args, **kwargs, **cls.__path_kwargs__)
47+
48+
3249
@dataclass
3350
class TextualAppContext:
3451
"""
@@ -39,6 +56,7 @@ class TextualAppContext:
3956
config: Optional[Dict[str, Any]] = None
4057
debug: bool = False
4158
max_file_size: int = 20
59+
kwargs: Optional[Dict[str, Any]] = None
4260

4361
@property
4462
def path(self) -> pathlib.Path:
@@ -56,8 +74,11 @@ def path(self) -> pathlib.Path:
5674
self.file_path = file_path
5775
if str(self.file_path).endswith("/"):
5876
self.file_path = str(self.file_path)[:-1]
77+
kwargs = self.kwargs or {}
78+
PathClass = copy(BrowsrPath)
79+
PathClass.__path_kwargs__ = kwargs
5980
return (
60-
upath.UPath(self.file_path).resolve()
81+
PathClass(self.file_path).resolve()
6182
if self.file_path
6283
else pathlib.Path.cwd().resolve()
6384
)

browsr/_cli.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
browsr command line interface
33
"""
44

5-
from typing import Optional
5+
from typing import Optional, Tuple
66

77
import click
88
import rich_click
@@ -43,10 +43,14 @@
4343
help="Enable extra debugging output",
4444
type=click.BOOL,
4545
)
46+
@click.option(
47+
"-k", "--kwargs", multiple=True, help="Key=Value pairs to pass to the filesystem"
48+
)
4649
def browsr(
4750
path: Optional[str],
4851
debug: bool,
4952
max_file_size: int,
53+
kwargs: Tuple[str, ...],
5054
) -> None:
5155
"""
5256
browsr 🗂️ a pleasant file explorer in your terminal
@@ -107,6 +111,17 @@ def browsr(
107111
browsr az://bucket-name
108112
```
109113
114+
#### Pass Extra Arguments to Cloud Storage
115+
116+
Some cloud storage providers require extra arguments to be passed to the
117+
filesystem. For example, to browse an anonymous S3 bucket, you need to pass
118+
the `anon=True` argument to the filesystem. This can be done with the `-k/--kwargs`
119+
argument.
120+
121+
```shell
122+
browsr s3://anonymous-bucket -k anon=True
123+
```
124+
110125
### GitHub
111126
112127
#### Browse a GitHub repository
@@ -160,7 +175,20 @@ def browsr(
160175
- **`D`** - Toggle dark mode for the application
161176
- **`X`** - Download the file from cloud storage
162177
"""
163-
config = TextualAppContext(file_path=path, debug=debug, max_file_size=max_file_size)
178+
extra_kwargs = {}
179+
if kwargs:
180+
for kwarg in kwargs:
181+
try:
182+
key, value = kwarg.split("=")
183+
extra_kwargs[key] = value
184+
except ValueError as ve:
185+
raise click.BadParameter(
186+
message=f"Invalid Key/Value pair: `{kwarg}` - must be in the format Key=Value",
187+
param_hint="kwargs",
188+
) from ve
189+
config = TextualAppContext(
190+
file_path=path, debug=debug, max_file_size=max_file_size, kwargs=extra_kwargs
191+
)
164192
app = Browsr(config_object=config)
165193
app.run()
166194

browsr/universal_directory_tree.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,24 @@
44

55
from __future__ import annotations
66

7-
from typing import ClassVar, Iterable, List, Optional
7+
from typing import ClassVar, Iterable, List, Optional, Type
88

99
from textual.binding import BindingType
1010
from textual.widgets._directory_tree import DirEntry
1111
from textual.widgets._tree import TreeNode
1212
from textual_universal_directorytree import UniversalDirectoryTree
1313
from upath import UPath as Path
1414

15-
from browsr._base import vim_cursor_bindings
15+
from browsr._base import BrowsrPath, vim_cursor_bindings
1616

1717

1818
class BrowsrDirectoryTree(UniversalDirectoryTree):
1919
"""
2020
A DirectoryTree that can handle any filesystem.
2121
"""
2222

23+
PATH: Type[BrowsrPath] = BrowsrPath
24+
2325
BINDINGS: ClassVar[List[BindingType]] = [
2426
*UniversalDirectoryTree.BINDINGS,
2527
*vim_cursor_bindings,

0 commit comments

Comments
 (0)