diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml
index af60278..b32cd8c 100644
--- a/.github/workflows/tests.yaml
+++ b/.github/workflows/tests.yaml
@@ -24,6 +24,7 @@ jobs:
fail-fast: true
matrix:
include:
+ - { name: Python 3.12, python: "3.12" }
- { name: Python 3.11, python: "3.11" }
- { name: Python 3.10, python: "3.10" }
- { name: Python 3.9, python: "3.9" }
diff --git a/README.md b/README.md
index 6f36ed9..34aedaa 100644
--- a/README.md
+++ b/README.md
@@ -52,28 +52,29 @@ class UniversalDirectoryTreeApp(App):
def __init__(self, path: str, *args: Any, **kwargs: Any):
super().__init__(*args, **kwargs)
- self.universal_path = path
- self.file_content = Static()
+ self.file_path = path
+ self.file_content = Static(expand=True)
def compose(self) -> ComposeResult:
yield Header()
- directory_tree = UniversalDirectoryTree(path=self.universal_path)
+ directory_tree = UniversalDirectoryTree(path=self.file_path)
yield Horizontal(directory_tree, VerticalScroll(self.file_content))
yield Footer()
@on(DirectoryTree.FileSelected)
- def handle_file_selected(
- self, message: DirectoryTree.FileSelected
- ) -> None:
+ def handle_file_selected(self, message: DirectoryTree.FileSelected) -> None:
"""
Do something with the selected file.
Objects returned by the FileSelected event are upath.UPath objects and
they are compatible with the familiar pathlib.Path API built into Python.
"""
- selected_file_path = message.path
- file_content = selected_file_path.read_text(errors="replace")
- lexer = Syntax.guess_lexer(path=str(selected_file_path))
+ try:
+ file_content = message.path.read_text()
+ except UnicodeDecodeError:
+ self.file_content.update("")
+ return None
+ lexer = Syntax.guess_lexer(path=message.path.name)
code = Syntax(code=file_content, lexer=lexer)
self.file_content.update(code)
```
diff --git a/docs/screenshots/test_github_screenshot.svg b/docs/screenshots/test_github_screenshot.svg
index d55fa21..975eb49 100644
--- a/docs/screenshots/test_github_screenshot.svg
+++ b/docs/screenshots/test_github_screenshot.svg
@@ -19,191 +19,191 @@
font-weight: 700;
}
- .terminal-2773286720-matrix {
+ .terminal-3424560114-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
- .terminal-2773286720-title {
+ .terminal-3424560114-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
- .terminal-2773286720-r1 { fill: #c5c8c6 }
-.terminal-2773286720-r2 { fill: #e3e3e3 }
-.terminal-2773286720-r3 { fill: #e2e3e3 }
-.terminal-2773286720-r4 { fill: #e2e3e3;font-weight: bold }
-.terminal-2773286720-r5 { fill: #f92672 }
-.terminal-2773286720-r6 { fill: #f8f8f2 }
-.terminal-2773286720-r7 { fill: #e1e1e1 }
-.terminal-2773286720-r8 { fill: #008139 }
-.terminal-2773286720-r9 { fill: #919497;font-weight: bold }
-.terminal-2773286720-r10 { fill: #919497;font-style: italic; }
-.terminal-2773286720-r11 { fill: #211505;font-weight: bold;font-style: italic; }
-.terminal-2773286720-r12 { fill: #e6db74 }
-.terminal-2773286720-r13 { fill: #e2e3e3;font-style: italic; }
-.terminal-2773286720-r14 { fill: #14191f }
-.terminal-2773286720-r15 { fill: #66d9ef }
-.terminal-2773286720-r16 { fill: #dde8f3;font-weight: bold }
-.terminal-2773286720-r17 { fill: #ddedf9 }
+ .terminal-3424560114-r1 { fill: #c5c8c6 }
+.terminal-3424560114-r2 { fill: #e3e3e3 }
+.terminal-3424560114-r3 { fill: #e2e3e3 }
+.terminal-3424560114-r4 { fill: #e2e3e3;font-weight: bold }
+.terminal-3424560114-r5 { fill: #ff4689 }
+.terminal-3424560114-r6 { fill: #f8f8f2 }
+.terminal-3424560114-r7 { fill: #e1e1e1 }
+.terminal-3424560114-r8 { fill: #008139 }
+.terminal-3424560114-r9 { fill: #919497;font-weight: bold }
+.terminal-3424560114-r10 { fill: #919497;font-style: italic; }
+.terminal-3424560114-r11 { fill: #211505;font-weight: bold;font-style: italic; }
+.terminal-3424560114-r12 { fill: #e6db74 }
+.terminal-3424560114-r13 { fill: #e2e3e3;font-style: italic; }
+.terminal-3424560114-r14 { fill: #14191f }
+.terminal-3424560114-r15 { fill: #66d9ef }
+.terminal-3424560114-r16 { fill: #dde8f3;font-weight: bold }
+.terminal-3424560114-r17 { fill: #ddedf9 }
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
- UniversalDirectoryTreeApp
+ UniversalDirectoryTreeApp
-
-
-
- ⭘UniversalDirectoryTreeApp
-📂 github://juftin:textual-universal-directorytree@v1.0.0/default_stages:[commit]
-├── 📁 .githubfail_fast:false
-├── 📁 docs
-├── 📁 requirementsrepos:
-├── 📁 tests-repo:https://github.com/pre-commit/pre-commit-hooks
-├── 📁 textual_universal_directorytreerev:v4.4.0
-├── 📄 .gitignorehooks:
-├── 📄 .pre-commit-config.yaml-id:trailing-whitespace
-├── 📄 .releaserc.jsexclude:'\.svg$'
-├── 📄 LICENSE.txt-id:end-of-file-fixer
-├── 📄 mkdocs.yaml-id:check-yaml
-├── 📄 pyproject.toml-id:check-ast
-└── 📄 README.md-id:check-docstring-first
--id:check-merge-conflict
--id:mixed-line-ending
-
--repo:https://github.com/macisamuele/language-format
-rev:v2.8.0
-hooks:
--id:pretty-format-toml
-args:[--autofix]
-▁▁
--repo:https://github.com/pre-commit/mirrors-prettier
-rev:v3.0.0-alpha.6
-hooks:
--id:prettier
-args:[--print-width=88,--tab-width=4]
-exclude:|
-(?x)(
-.github/semantic_release/release_notes.h
-)
-additional_dependencies:
--prettier
- Q Quit
+
+
+
+ ⭘UniversalDirectoryTreeApp
+📂 github://juftin:textual-universal-directorytree@v1.0.0default_stages:[commit]
+├── 📁 .githubfail_fast:false
+├── 📁 docs
+├── 📁 requirementsrepos:
+├── 📁 tests-repo:https://github.com/pre-commit/pre-commit-hooks
+├── 📁 textual_universal_directorytreerev:v4.4.0
+├── 📄 .gitignorehooks:
+├── 📄 .pre-commit-config.yaml-id:trailing-whitespace
+├── 📄 .releaserc.jsexclude:'\.svg$'
+├── 📄 LICENSE.txt-id:end-of-file-fixer
+├── 📄 mkdocs.yaml-id:check-yaml
+├── 📄 pyproject.toml-id:check-ast
+└── 📄 README.md-id:check-docstring-first
+-id:check-merge-conflict
+-id:mixed-line-ending
+
+-repo:https://github.com/macisamuele/language-format
+rev:v2.8.0
+hooks:
+-id:pretty-format-toml
+args:[--autofix]
+▁▁
+-repo:https://github.com/pre-commit/mirrors-prettier
+rev:v3.0.0-alpha.6
+hooks:
+-id:prettier
+args:[--print-width=88,--tab-width=4]
+exclude:|
+(?x)(
+.github/semantic_release/release_notes.h
+)
+additional_dependencies:
+-prettier
+ Q Quit
diff --git a/pyproject.toml b/pyproject.toml
index 34d392a..92caca3 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -14,12 +14,13 @@ classifiers = [
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: 3.12",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy"
]
dependencies = [
"textual>=0.27.0",
- "universal-pathlib>=0.0.23,<=0.0.24"
+ "universal-pathlib>=0.2.2"
]
description = "A Textual Directory Tree for all File Systems"
dynamic = ["version"]
@@ -82,7 +83,7 @@ pip-compile-constraint = ""
template = "test"
[[tool.hatch.envs.all.matrix]]
-python = ["3.8", "3.9", "3.10", "3.11"]
+python = ["3.8", "3.9", "3.10", "3.11", "3.12"]
[tool.hatch.envs.default]
features = ["remote"]
diff --git a/requirements.txt b/requirements.txt
index 3a8ddf1..4bfa0da 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,7 +2,7 @@
# This file is autogenerated by hatch-pip-compile with Python 3.11
#
# - textual>=0.27.0
-# - universal-pathlib<=0.0.24,>=0.0.23
+# - universal-pathlib>=0.2.2
# - adlfs
# - aiohttp
# - gcsfs
@@ -11,11 +11,11 @@
# - s3fs
#
-adlfs==2023.8.0
+adlfs==2024.2.0
# via hatch.envs.default
-aiobotocore==2.5.4
+aiobotocore==2.11.2
# via s3fs
-aiohttp==3.8.4
+aiohttp==3.9.3
# via
# hatch.envs.default
# adlfs
@@ -26,11 +26,9 @@ aioitertools==0.11.0
# via aiobotocore
aiosignal==1.3.1
# via aiohttp
-async-timeout==4.0.2
+attrs==23.2.0
# via aiohttp
-attrs==23.1.0
- # via aiohttp
-azure-core==1.29.1
+azure-core==1.30.0
# via
# adlfs
# azure-identity
@@ -43,21 +41,19 @@ azure-storage-blob==12.19.0
# via adlfs
bcrypt==4.1.2
# via paramiko
-botocore==1.31.17
+botocore==1.34.34
# via aiobotocore
cachetools==5.3.2
# via google-auth
-certifi==2023.5.7
+certifi==2024.2.2
# via requests
cffi==1.16.0
# via
# azure-datalake-store
# cryptography
# pynacl
-charset-normalizer==3.1.0
- # via
- # aiohttp
- # requests
+charset-normalizer==3.3.2
+ # via requests
cryptography==42.0.3
# via
# azure-identity
@@ -67,17 +63,17 @@ cryptography==42.0.3
# pyjwt
decorator==5.1.1
# via gcsfs
-frozenlist==1.3.3
+frozenlist==1.4.1
# via
# aiohttp
# aiosignal
-fsspec==2023.5.0
+fsspec==2024.2.0
# via
# adlfs
# gcsfs
# s3fs
# universal-pathlib
-gcsfs==2023.5.0
+gcsfs==2024.2.0
# via hatch.envs.default
google-api-core==2.17.1
# via
@@ -104,24 +100,22 @@ google-resumable-media==2.7.0
# via google-cloud-storage
googleapis-common-protos==1.62.0
# via google-api-core
-idna==3.4
+idna==3.6
# via
# requests
# yarl
-importlib-metadata==6.6.0
- # via textual
isodate==0.6.1
# via azure-storage-blob
jmespath==1.0.1
# via botocore
-linkify-it-py==2.0.2
+linkify-it-py==2.0.3
# via markdown-it-py
-markdown-it-py==2.2.0
+markdown-it-py==3.0.0
# via
# mdit-py-plugins
# rich
# textual
-mdit-py-plugins==0.3.5
+mdit-py-plugins==0.4.0
# via markdown-it-py
mdurl==0.1.2
# via markdown-it-py
@@ -132,13 +126,13 @@ msal==1.26.0
# msal-extensions
msal-extensions==1.1.0
# via azure-identity
-multidict==6.0.4
+multidict==6.0.5
# via
# aiohttp
# yarl
oauthlib==3.2.2
# via requests-oauthlib
-packaging==23.1
+packaging==23.2
# via msal-extensions
paramiko==3.4.0
# via hatch.envs.default
@@ -156,7 +150,7 @@ pyasn1-modules==0.3.0
# via google-auth
pycparser==2.21
# via cffi
-pygments==2.15.1
+pygments==2.17.2
# via rich
pyjwt==2.8.0
# via
@@ -166,7 +160,7 @@ pynacl==1.5.0
# via paramiko
python-dateutil==2.8.2
# via botocore
-requests==2.30.0
+requests==2.31.0
# via
# hatch.envs.default
# azure-core
@@ -178,35 +172,33 @@ requests==2.30.0
# requests-oauthlib
requests-oauthlib==1.3.1
# via google-auth-oauthlib
-rich==13.3.5
+rich==13.7.0
# via textual
rsa==4.9
# via google-auth
-s3fs==2023.5.0
+s3fs==2024.2.0
# via hatch.envs.default
six==1.16.0
# via
# azure-core
# isodate
# python-dateutil
-textual==0.27.0
+textual==0.48.2
# via hatch.envs.default
-typing-extensions==4.5.0
+typing-extensions==4.9.0
# via
# azure-core
# azure-storage-blob
# textual
-uc-micro-py==1.0.2
+uc-micro-py==1.0.3
# via linkify-it-py
-universal-pathlib==0.0.24
+universal-pathlib==0.2.2
# via hatch.envs.default
-urllib3==1.26.16
+urllib3==2.0.7
# via
# botocore
# requests
-wrapt==1.15.0
+wrapt==1.16.0
# via aiobotocore
-yarl==1.9.2
+yarl==1.9.4
# via aiohttp
-zipp==3.15.0
- # via importlib-metadata
diff --git a/requirements/requirements-all.py3.10.txt b/requirements/requirements-all.py3.10.txt
index 598d653..76eb2f1 100644
--- a/requirements/requirements-all.py3.10.txt
+++ b/requirements/requirements-all.py3.10.txt
@@ -4,7 +4,7 @@
# - pytest
# - pytest-cov
# - textual>=0.27.0
-# - universal-pathlib<=0.0.24,>=0.0.23
+# - universal-pathlib>=0.2.2
# - adlfs
# - aiohttp
# - gcsfs
@@ -13,11 +13,11 @@
# - s3fs
#
-adlfs==2023.8.0
+adlfs==2024.2.0
# via hatch.envs.all.py3.10
-aiobotocore==2.5.4
+aiobotocore==2.11.2
# via s3fs
-aiohttp==3.8.4
+aiohttp==3.9.3
# via
# hatch.envs.all.py3.10
# adlfs
@@ -28,11 +28,11 @@ aioitertools==0.11.0
# via aiobotocore
aiosignal==1.3.1
# via aiohttp
-async-timeout==4.0.2
+async-timeout==4.0.3
# via aiohttp
-attrs==23.1.0
+attrs==23.2.0
# via aiohttp
-azure-core==1.29.1
+azure-core==1.30.0
# via
# adlfs
# azure-identity
@@ -45,22 +45,20 @@ azure-storage-blob==12.19.0
# via adlfs
bcrypt==4.1.2
# via paramiko
-botocore==1.31.17
+botocore==1.34.34
# via aiobotocore
cachetools==5.3.2
# via google-auth
-certifi==2023.5.7
+certifi==2024.2.2
# via requests
cffi==1.16.0
# via
# azure-datalake-store
# cryptography
# pynacl
-charset-normalizer==3.1.0
- # via
- # aiohttp
- # requests
-coverage==7.2.5
+charset-normalizer==3.3.2
+ # via requests
+coverage==7.4.1
# via pytest-cov
cryptography==42.0.3
# via
@@ -71,19 +69,19 @@ cryptography==42.0.3
# pyjwt
decorator==5.1.1
# via gcsfs
-exceptiongroup==1.1.1
+exceptiongroup==1.2.0
# via pytest
-frozenlist==1.3.3
+frozenlist==1.4.1
# via
# aiohttp
# aiosignal
-fsspec==2023.5.0
+fsspec==2024.2.0
# via
# adlfs
# gcsfs
# s3fs
# universal-pathlib
-gcsfs==2023.5.0
+gcsfs==2024.2.0
# via hatch.envs.all.py3.10
google-api-core==2.17.1
# via
@@ -110,26 +108,24 @@ google-resumable-media==2.7.0
# via google-cloud-storage
googleapis-common-protos==1.62.0
# via google-api-core
-idna==3.4
+idna==3.6
# via
# requests
# yarl
-importlib-metadata==6.6.0
- # via textual
iniconfig==2.0.0
# via pytest
isodate==0.6.1
# via azure-storage-blob
jmespath==1.0.1
# via botocore
-linkify-it-py==2.0.2
+linkify-it-py==2.0.3
# via markdown-it-py
-markdown-it-py==2.2.0
+markdown-it-py==3.0.0
# via
# mdit-py-plugins
# rich
# textual
-mdit-py-plugins==0.3.5
+mdit-py-plugins==0.4.0
# via markdown-it-py
mdurl==0.1.2
# via markdown-it-py
@@ -140,19 +136,19 @@ msal==1.26.0
# msal-extensions
msal-extensions==1.1.0
# via azure-identity
-multidict==6.0.4
+multidict==6.0.5
# via
# aiohttp
# yarl
oauthlib==3.2.2
# via requests-oauthlib
-packaging==23.1
+packaging==23.2
# via
# msal-extensions
# pytest
paramiko==3.4.0
# via hatch.envs.all.py3.10
-pluggy==1.0.0
+pluggy==1.4.0
# via pytest
portalocker==2.8.2
# via msal-extensions
@@ -168,7 +164,7 @@ pyasn1-modules==0.3.0
# via google-auth
pycparser==2.21
# via cffi
-pygments==2.15.1
+pygments==2.17.2
# via rich
pyjwt==2.8.0
# via
@@ -176,15 +172,15 @@ pyjwt==2.8.0
# pyjwt
pynacl==1.5.0
# via paramiko
-pytest==7.3.1
+pytest==8.0.1
# via
# hatch.envs.all.py3.10
# pytest-cov
-pytest-cov==4.0.0
+pytest-cov==4.1.0
# via hatch.envs.all.py3.10
python-dateutil==2.8.2
# via botocore
-requests==2.30.0
+requests==2.31.0
# via
# hatch.envs.all.py3.10
# azure-core
@@ -196,39 +192,37 @@ requests==2.30.0
# requests-oauthlib
requests-oauthlib==1.3.1
# via google-auth-oauthlib
-rich==13.3.5
+rich==13.7.0
# via textual
rsa==4.9
# via google-auth
-s3fs==2023.5.0
+s3fs==2024.2.0
# via hatch.envs.all.py3.10
six==1.16.0
# via
# azure-core
# isodate
# python-dateutil
-textual==0.27.0
+textual==0.48.2
# via hatch.envs.all.py3.10
tomli==2.0.1
# via
# coverage
# pytest
-typing-extensions==4.5.0
+typing-extensions==4.9.0
# via
# azure-core
# azure-storage-blob
# textual
-uc-micro-py==1.0.2
+uc-micro-py==1.0.3
# via linkify-it-py
-universal-pathlib==0.0.24
+universal-pathlib==0.2.2
# via hatch.envs.all.py3.10
-urllib3==1.26.16
+urllib3==2.0.7
# via
# botocore
# requests
-wrapt==1.15.0
+wrapt==1.16.0
# via aiobotocore
-yarl==1.9.2
+yarl==1.9.4
# via aiohttp
-zipp==3.15.0
- # via importlib-metadata
diff --git a/requirements/requirements-all.py3.11.txt b/requirements/requirements-all.py3.11.txt
index 1618ff2..07a53c2 100644
--- a/requirements/requirements-all.py3.11.txt
+++ b/requirements/requirements-all.py3.11.txt
@@ -4,7 +4,7 @@
# - pytest
# - pytest-cov
# - textual>=0.27.0
-# - universal-pathlib<=0.0.24,>=0.0.23
+# - universal-pathlib>=0.2.2
# - adlfs
# - aiohttp
# - gcsfs
@@ -13,11 +13,11 @@
# - s3fs
#
-adlfs==2023.8.0
+adlfs==2024.2.0
# via hatch.envs.all.py3.11
-aiobotocore==2.5.4
+aiobotocore==2.11.2
# via s3fs
-aiohttp==3.8.4
+aiohttp==3.9.3
# via
# hatch.envs.all.py3.11
# adlfs
@@ -28,11 +28,9 @@ aioitertools==0.11.0
# via aiobotocore
aiosignal==1.3.1
# via aiohttp
-async-timeout==4.0.2
+attrs==23.2.0
# via aiohttp
-attrs==23.1.0
- # via aiohttp
-azure-core==1.29.1
+azure-core==1.30.0
# via
# adlfs
# azure-identity
@@ -45,22 +43,20 @@ azure-storage-blob==12.19.0
# via adlfs
bcrypt==4.1.2
# via paramiko
-botocore==1.31.17
+botocore==1.34.34
# via aiobotocore
cachetools==5.3.2
# via google-auth
-certifi==2023.5.7
+certifi==2024.2.2
# via requests
cffi==1.16.0
# via
# azure-datalake-store
# cryptography
# pynacl
-charset-normalizer==3.1.0
- # via
- # aiohttp
- # requests
-coverage==7.2.5
+charset-normalizer==3.3.2
+ # via requests
+coverage==7.4.1
# via pytest-cov
cryptography==42.0.3
# via
@@ -71,17 +67,17 @@ cryptography==42.0.3
# pyjwt
decorator==5.1.1
# via gcsfs
-frozenlist==1.3.3
+frozenlist==1.4.1
# via
# aiohttp
# aiosignal
-fsspec==2023.5.0
+fsspec==2024.2.0
# via
# adlfs
# gcsfs
# s3fs
# universal-pathlib
-gcsfs==2023.5.0
+gcsfs==2024.2.0
# via hatch.envs.all.py3.11
google-api-core==2.17.1
# via
@@ -108,26 +104,24 @@ google-resumable-media==2.7.0
# via google-cloud-storage
googleapis-common-protos==1.62.0
# via google-api-core
-idna==3.4
+idna==3.6
# via
# requests
# yarl
-importlib-metadata==6.6.0
- # via textual
iniconfig==2.0.0
# via pytest
isodate==0.6.1
# via azure-storage-blob
jmespath==1.0.1
# via botocore
-linkify-it-py==2.0.2
+linkify-it-py==2.0.3
# via markdown-it-py
-markdown-it-py==2.2.0
+markdown-it-py==3.0.0
# via
# mdit-py-plugins
# rich
# textual
-mdit-py-plugins==0.3.5
+mdit-py-plugins==0.4.0
# via markdown-it-py
mdurl==0.1.2
# via markdown-it-py
@@ -138,19 +132,19 @@ msal==1.26.0
# msal-extensions
msal-extensions==1.1.0
# via azure-identity
-multidict==6.0.4
+multidict==6.0.5
# via
# aiohttp
# yarl
oauthlib==3.2.2
# via requests-oauthlib
-packaging==23.1
+packaging==23.2
# via
# msal-extensions
# pytest
paramiko==3.4.0
# via hatch.envs.all.py3.11
-pluggy==1.0.0
+pluggy==1.4.0
# via pytest
portalocker==2.8.2
# via msal-extensions
@@ -166,7 +160,7 @@ pyasn1-modules==0.3.0
# via google-auth
pycparser==2.21
# via cffi
-pygments==2.15.1
+pygments==2.17.2
# via rich
pyjwt==2.8.0
# via
@@ -174,15 +168,15 @@ pyjwt==2.8.0
# pyjwt
pynacl==1.5.0
# via paramiko
-pytest==7.3.1
+pytest==8.0.1
# via
# hatch.envs.all.py3.11
# pytest-cov
-pytest-cov==4.0.0
+pytest-cov==4.1.0
# via hatch.envs.all.py3.11
python-dateutil==2.8.2
# via botocore
-requests==2.30.0
+requests==2.31.0
# via
# hatch.envs.all.py3.11
# azure-core
@@ -194,35 +188,33 @@ requests==2.30.0
# requests-oauthlib
requests-oauthlib==1.3.1
# via google-auth-oauthlib
-rich==13.3.5
+rich==13.7.0
# via textual
rsa==4.9
# via google-auth
-s3fs==2023.5.0
+s3fs==2024.2.0
# via hatch.envs.all.py3.11
six==1.16.0
# via
# azure-core
# isodate
# python-dateutil
-textual==0.27.0
+textual==0.48.2
# via hatch.envs.all.py3.11
-typing-extensions==4.5.0
+typing-extensions==4.9.0
# via
# azure-core
# azure-storage-blob
# textual
-uc-micro-py==1.0.2
+uc-micro-py==1.0.3
# via linkify-it-py
-universal-pathlib==0.0.24
+universal-pathlib==0.2.2
# via hatch.envs.all.py3.11
-urllib3==1.26.16
+urllib3==2.0.7
# via
# botocore
# requests
-wrapt==1.15.0
+wrapt==1.16.0
# via aiobotocore
-yarl==1.9.2
+yarl==1.9.4
# via aiohttp
-zipp==3.15.0
- # via importlib-metadata
diff --git a/requirements/requirements-all.py3.12.txt b/requirements/requirements-all.py3.12.txt
new file mode 100644
index 0000000..7f5b3cc
--- /dev/null
+++ b/requirements/requirements-all.py3.12.txt
@@ -0,0 +1,220 @@
+#
+# This file is autogenerated by hatch-pip-compile with Python 3.12
+#
+# - pytest
+# - pytest-cov
+# - textual>=0.27.0
+# - universal-pathlib>=0.2.2
+# - adlfs
+# - aiohttp
+# - gcsfs
+# - paramiko
+# - requests>=2
+# - s3fs
+#
+
+adlfs==2024.2.0
+ # via hatch.envs.all.py3.12
+aiobotocore==2.12.1
+ # via s3fs
+aiohttp==3.9.3
+ # via
+ # hatch.envs.all.py3.12
+ # adlfs
+ # aiobotocore
+ # gcsfs
+ # s3fs
+aioitertools==0.11.0
+ # via aiobotocore
+aiosignal==1.3.1
+ # via aiohttp
+attrs==23.2.0
+ # via aiohttp
+azure-core==1.30.1
+ # via
+ # adlfs
+ # azure-identity
+ # azure-storage-blob
+azure-datalake-store==0.0.53
+ # via adlfs
+azure-identity==1.15.0
+ # via adlfs
+azure-storage-blob==12.19.0
+ # via adlfs
+bcrypt==4.1.2
+ # via paramiko
+botocore==1.34.51
+ # via aiobotocore
+cachetools==5.3.3
+ # via google-auth
+certifi==2024.2.2
+ # via requests
+cffi==1.16.0
+ # via
+ # azure-datalake-store
+ # cryptography
+ # pynacl
+charset-normalizer==3.3.2
+ # via requests
+coverage==7.4.3
+ # via pytest-cov
+cryptography==42.0.5
+ # via
+ # azure-identity
+ # azure-storage-blob
+ # msal
+ # paramiko
+ # pyjwt
+decorator==5.1.1
+ # via gcsfs
+frozenlist==1.4.1
+ # via
+ # aiohttp
+ # aiosignal
+fsspec==2024.2.0
+ # via
+ # adlfs
+ # gcsfs
+ # s3fs
+ # universal-pathlib
+gcsfs==2024.2.0
+ # via hatch.envs.all.py3.12
+google-api-core==2.17.1
+ # via
+ # google-cloud-core
+ # google-cloud-storage
+google-auth==2.28.1
+ # via
+ # gcsfs
+ # google-api-core
+ # google-auth-oauthlib
+ # google-cloud-core
+ # google-cloud-storage
+google-auth-oauthlib==1.2.0
+ # via gcsfs
+google-cloud-core==2.4.1
+ # via google-cloud-storage
+google-cloud-storage==2.15.0
+ # via gcsfs
+google-crc32c==1.5.0
+ # via
+ # google-cloud-storage
+ # google-resumable-media
+google-resumable-media==2.7.0
+ # via google-cloud-storage
+googleapis-common-protos==1.62.0
+ # via google-api-core
+idna==3.6
+ # via
+ # requests
+ # yarl
+iniconfig==2.0.0
+ # via pytest
+isodate==0.6.1
+ # via azure-storage-blob
+jmespath==1.0.1
+ # via botocore
+linkify-it-py==2.0.3
+ # via markdown-it-py
+markdown-it-py==3.0.0
+ # via
+ # mdit-py-plugins
+ # rich
+ # textual
+mdit-py-plugins==0.4.0
+ # via markdown-it-py
+mdurl==0.1.2
+ # via markdown-it-py
+msal==1.27.0
+ # via
+ # azure-datalake-store
+ # azure-identity
+ # msal-extensions
+msal-extensions==1.1.0
+ # via azure-identity
+multidict==6.0.5
+ # via
+ # aiohttp
+ # yarl
+oauthlib==3.2.2
+ # via requests-oauthlib
+packaging==23.2
+ # via
+ # msal-extensions
+ # pytest
+paramiko==3.4.0
+ # via hatch.envs.all.py3.12
+pluggy==1.4.0
+ # via pytest
+portalocker==2.8.2
+ # via msal-extensions
+protobuf==4.25.3
+ # via
+ # google-api-core
+ # googleapis-common-protos
+pyasn1==0.5.1
+ # via
+ # pyasn1-modules
+ # rsa
+pyasn1-modules==0.3.0
+ # via google-auth
+pycparser==2.21
+ # via cffi
+pygments==2.17.2
+ # via rich
+pyjwt==2.8.0
+ # via
+ # msal
+ # pyjwt
+pynacl==1.5.0
+ # via paramiko
+pytest==8.0.2
+ # via
+ # hatch.envs.all.py3.12
+ # pytest-cov
+pytest-cov==4.1.0
+ # via hatch.envs.all.py3.12
+python-dateutil==2.9.0.post0
+ # via botocore
+requests==2.31.0
+ # via
+ # hatch.envs.all.py3.12
+ # azure-core
+ # azure-datalake-store
+ # gcsfs
+ # google-api-core
+ # google-cloud-storage
+ # msal
+ # requests-oauthlib
+requests-oauthlib==1.3.1
+ # via google-auth-oauthlib
+rich==13.7.1
+ # via textual
+rsa==4.9
+ # via google-auth
+s3fs==2024.2.0
+ # via hatch.envs.all.py3.12
+six==1.16.0
+ # via
+ # azure-core
+ # isodate
+ # python-dateutil
+textual==0.48.2
+ # via hatch.envs.all.py3.12
+typing-extensions==4.10.0
+ # via
+ # azure-core
+ # azure-storage-blob
+ # textual
+uc-micro-py==1.0.3
+ # via linkify-it-py
+universal-pathlib==0.2.2
+ # via hatch.envs.all.py3.12
+urllib3==2.0.7
+ # via
+ # botocore
+ # requests
+wrapt==1.16.0
+ # via aiobotocore
+yarl==1.9.4
+ # via aiohttp
diff --git a/requirements/requirements-all.py3.8.txt b/requirements/requirements-all.py3.8.txt
index f4e8f94..c7e1e32 100644
--- a/requirements/requirements-all.py3.8.txt
+++ b/requirements/requirements-all.py3.8.txt
@@ -4,7 +4,7 @@
# - pytest
# - pytest-cov
# - textual>=0.27.0
-# - universal-pathlib<=0.0.24,>=0.0.23
+# - universal-pathlib>=0.2.2
# - adlfs
# - aiohttp
# - gcsfs
@@ -13,11 +13,11 @@
# - s3fs
#
-adlfs==2023.8.0
+adlfs==2024.2.0
# via hatch.envs.all.py3.8
-aiobotocore==2.5.4
+aiobotocore==2.11.2
# via s3fs
-aiohttp==3.8.4
+aiohttp==3.9.3
# via
# hatch.envs.all.py3.8
# adlfs
@@ -28,11 +28,11 @@ aioitertools==0.11.0
# via aiobotocore
aiosignal==1.3.1
# via aiohttp
-async-timeout==4.0.2
+async-timeout==4.0.3
# via aiohttp
-attrs==23.1.0
+attrs==23.2.0
# via aiohttp
-azure-core==1.29.1
+azure-core==1.30.0
# via
# adlfs
# azure-identity
@@ -45,22 +45,20 @@ azure-storage-blob==12.19.0
# via adlfs
bcrypt==4.1.2
# via paramiko
-botocore==1.31.17
+botocore==1.34.34
# via aiobotocore
cachetools==5.3.2
# via google-auth
-certifi==2023.5.7
+certifi==2024.2.2
# via requests
cffi==1.16.0
# via
# azure-datalake-store
# cryptography
# pynacl
-charset-normalizer==3.1.0
- # via
- # aiohttp
- # requests
-coverage==7.2.5
+charset-normalizer==3.3.2
+ # via requests
+coverage==7.4.1
# via pytest-cov
cryptography==42.0.3
# via
@@ -71,19 +69,19 @@ cryptography==42.0.3
# pyjwt
decorator==5.1.1
# via gcsfs
-exceptiongroup==1.1.1
+exceptiongroup==1.2.0
# via pytest
-frozenlist==1.3.3
+frozenlist==1.4.1
# via
# aiohttp
# aiosignal
-fsspec==2023.5.0
+fsspec==2024.2.0
# via
# adlfs
# gcsfs
# s3fs
# universal-pathlib
-gcsfs==2023.5.0
+gcsfs==2024.2.0
# via hatch.envs.all.py3.8
google-api-core==2.17.1
# via
@@ -110,26 +108,24 @@ google-resumable-media==2.7.0
# via google-cloud-storage
googleapis-common-protos==1.62.0
# via google-api-core
-idna==3.4
+idna==3.6
# via
# requests
# yarl
-importlib-metadata==6.6.0
- # via textual
iniconfig==2.0.0
# via pytest
isodate==0.6.1
# via azure-storage-blob
jmespath==1.0.1
# via botocore
-linkify-it-py==2.0.2
+linkify-it-py==2.0.3
# via markdown-it-py
-markdown-it-py==2.2.0
+markdown-it-py==3.0.0
# via
# mdit-py-plugins
# rich
# textual
-mdit-py-plugins==0.3.5
+mdit-py-plugins==0.4.0
# via markdown-it-py
mdurl==0.1.2
# via markdown-it-py
@@ -140,19 +136,19 @@ msal==1.26.0
# msal-extensions
msal-extensions==1.1.0
# via azure-identity
-multidict==6.0.4
+multidict==6.0.5
# via
# aiohttp
# yarl
oauthlib==3.2.2
# via requests-oauthlib
-packaging==23.1
+packaging==23.2
# via
# msal-extensions
# pytest
paramiko==3.4.0
# via hatch.envs.all.py3.8
-pluggy==1.0.0
+pluggy==1.4.0
# via pytest
portalocker==2.8.2
# via msal-extensions
@@ -168,7 +164,7 @@ pyasn1-modules==0.3.0
# via google-auth
pycparser==2.21
# via cffi
-pygments==2.15.1
+pygments==2.17.2
# via rich
pyjwt==2.8.0
# via
@@ -176,15 +172,15 @@ pyjwt==2.8.0
# pyjwt
pynacl==1.5.0
# via paramiko
-pytest==7.3.1
+pytest==8.0.1
# via
# hatch.envs.all.py3.8
# pytest-cov
-pytest-cov==4.0.0
+pytest-cov==4.1.0
# via hatch.envs.all.py3.8
python-dateutil==2.8.2
# via botocore
-requests==2.30.0
+requests==2.31.0
# via
# hatch.envs.all.py3.8
# azure-core
@@ -196,41 +192,39 @@ requests==2.30.0
# requests-oauthlib
requests-oauthlib==1.3.1
# via google-auth-oauthlib
-rich==13.3.5
+rich==13.7.0
# via textual
rsa==4.9
# via google-auth
-s3fs==2023.5.0
+s3fs==2024.2.0
# via hatch.envs.all.py3.8
six==1.16.0
# via
# azure-core
# isodate
# python-dateutil
-textual==0.27.0
+textual==0.48.2
# via hatch.envs.all.py3.8
tomli==2.0.1
# via
# coverage
# pytest
-typing-extensions==4.5.0
+typing-extensions==4.9.0
# via
# aioitertools
# azure-core
# azure-storage-blob
# rich
# textual
-uc-micro-py==1.0.2
+uc-micro-py==1.0.3
# via linkify-it-py
-universal-pathlib==0.0.24
+universal-pathlib==0.2.2
# via hatch.envs.all.py3.8
-urllib3==1.26.16
+urllib3==1.26.18
# via
# botocore
# requests
-wrapt==1.15.0
+wrapt==1.16.0
# via aiobotocore
-yarl==1.9.2
+yarl==1.9.4
# via aiohttp
-zipp==3.15.0
- # via importlib-metadata
diff --git a/requirements/requirements-all.py3.9.txt b/requirements/requirements-all.py3.9.txt
index 6b76946..f5e77ea 100644
--- a/requirements/requirements-all.py3.9.txt
+++ b/requirements/requirements-all.py3.9.txt
@@ -4,7 +4,7 @@
# - pytest
# - pytest-cov
# - textual>=0.27.0
-# - universal-pathlib<=0.0.24,>=0.0.23
+# - universal-pathlib>=0.2.2
# - adlfs
# - aiohttp
# - gcsfs
@@ -13,11 +13,11 @@
# - s3fs
#
-adlfs==2023.8.0
+adlfs==2024.2.0
# via hatch.envs.all.py3.9
-aiobotocore==2.5.4
+aiobotocore==2.11.2
# via s3fs
-aiohttp==3.8.4
+aiohttp==3.9.3
# via
# hatch.envs.all.py3.9
# adlfs
@@ -28,11 +28,11 @@ aioitertools==0.11.0
# via aiobotocore
aiosignal==1.3.1
# via aiohttp
-async-timeout==4.0.2
+async-timeout==4.0.3
# via aiohttp
-attrs==23.1.0
+attrs==23.2.0
# via aiohttp
-azure-core==1.29.1
+azure-core==1.30.0
# via
# adlfs
# azure-identity
@@ -45,22 +45,20 @@ azure-storage-blob==12.19.0
# via adlfs
bcrypt==4.1.2
# via paramiko
-botocore==1.31.17
+botocore==1.34.34
# via aiobotocore
cachetools==5.3.2
# via google-auth
-certifi==2023.5.7
+certifi==2024.2.2
# via requests
cffi==1.16.0
# via
# azure-datalake-store
# cryptography
# pynacl
-charset-normalizer==3.1.0
- # via
- # aiohttp
- # requests
-coverage==7.2.5
+charset-normalizer==3.3.2
+ # via requests
+coverage==7.4.1
# via pytest-cov
cryptography==42.0.3
# via
@@ -71,19 +69,19 @@ cryptography==42.0.3
# pyjwt
decorator==5.1.1
# via gcsfs
-exceptiongroup==1.1.1
+exceptiongroup==1.2.0
# via pytest
-frozenlist==1.3.3
+frozenlist==1.4.1
# via
# aiohttp
# aiosignal
-fsspec==2023.5.0
+fsspec==2024.2.0
# via
# adlfs
# gcsfs
# s3fs
# universal-pathlib
-gcsfs==2023.5.0
+gcsfs==2024.2.0
# via hatch.envs.all.py3.9
google-api-core==2.17.1
# via
@@ -110,26 +108,24 @@ google-resumable-media==2.7.0
# via google-cloud-storage
googleapis-common-protos==1.62.0
# via google-api-core
-idna==3.4
+idna==3.6
# via
# requests
# yarl
-importlib-metadata==6.6.0
- # via textual
iniconfig==2.0.0
# via pytest
isodate==0.6.1
# via azure-storage-blob
jmespath==1.0.1
# via botocore
-linkify-it-py==2.0.2
+linkify-it-py==2.0.3
# via markdown-it-py
-markdown-it-py==2.2.0
+markdown-it-py==3.0.0
# via
# mdit-py-plugins
# rich
# textual
-mdit-py-plugins==0.3.5
+mdit-py-plugins==0.4.0
# via markdown-it-py
mdurl==0.1.2
# via markdown-it-py
@@ -140,19 +136,19 @@ msal==1.26.0
# msal-extensions
msal-extensions==1.1.0
# via azure-identity
-multidict==6.0.4
+multidict==6.0.5
# via
# aiohttp
# yarl
oauthlib==3.2.2
# via requests-oauthlib
-packaging==23.1
+packaging==23.2
# via
# msal-extensions
# pytest
paramiko==3.4.0
# via hatch.envs.all.py3.9
-pluggy==1.0.0
+pluggy==1.4.0
# via pytest
portalocker==2.8.2
# via msal-extensions
@@ -168,7 +164,7 @@ pyasn1-modules==0.3.0
# via google-auth
pycparser==2.21
# via cffi
-pygments==2.15.1
+pygments==2.17.2
# via rich
pyjwt==2.8.0
# via
@@ -176,15 +172,15 @@ pyjwt==2.8.0
# pyjwt
pynacl==1.5.0
# via paramiko
-pytest==7.3.1
+pytest==8.0.1
# via
# hatch.envs.all.py3.9
# pytest-cov
-pytest-cov==4.0.0
+pytest-cov==4.1.0
# via hatch.envs.all.py3.9
python-dateutil==2.8.2
# via botocore
-requests==2.30.0
+requests==2.31.0
# via
# hatch.envs.all.py3.9
# azure-core
@@ -196,40 +192,38 @@ requests==2.30.0
# requests-oauthlib
requests-oauthlib==1.3.1
# via google-auth-oauthlib
-rich==13.3.5
+rich==13.7.0
# via textual
rsa==4.9
# via google-auth
-s3fs==2023.5.0
+s3fs==2024.2.0
# via hatch.envs.all.py3.9
six==1.16.0
# via
# azure-core
# isodate
# python-dateutil
-textual==0.27.0
+textual==0.48.2
# via hatch.envs.all.py3.9
tomli==2.0.1
# via
# coverage
# pytest
-typing-extensions==4.5.0
+typing-extensions==4.9.0
# via
# aioitertools
# azure-core
# azure-storage-blob
# textual
-uc-micro-py==1.0.2
+uc-micro-py==1.0.3
# via linkify-it-py
-universal-pathlib==0.0.24
+universal-pathlib==0.2.2
# via hatch.envs.all.py3.9
-urllib3==1.26.16
+urllib3==1.26.18
# via
# botocore
# requests
-wrapt==1.15.0
+wrapt==1.16.0
# via aiobotocore
-yarl==1.9.2
+yarl==1.9.4
# via aiohttp
-zipp==3.15.0
- # via importlib-metadata
diff --git a/requirements/requirements-docs.txt b/requirements/requirements-docs.txt
index b877c7f..aa928b2 100644
--- a/requirements/requirements-docs.txt
+++ b/requirements/requirements-docs.txt
@@ -1,7 +1,7 @@
#
# This file is autogenerated by hatch-pip-compile with Python 3.11
#
-# [constraints] requirements.txt (SHA256: ac0cd48906e0fabeea2bed80a2ebd5efd3c730ab841afa755168c420cb4c9b65)
+# [constraints] requirements.txt (SHA256: 9af71b46a759063aedcaa7dd5827200718b097dd959677acd642ee2dc7f49cd5)
#
# - markdown-callouts
# - markdown-exec
@@ -16,51 +16,50 @@
# - mkdocstrings-python
# - pymdown-extensions
# - textual>=0.27.0
-# - universal-pathlib<=0.0.24,>=0.0.23
+# - universal-pathlib>=0.2.2
#
-certifi==2023.5.7
+babel==2.14.0
+ # via mkdocs-material
+certifi==2024.2.2
# via
# -c requirements.txt
# requests
-charset-normalizer==3.1.0
+charset-normalizer==3.3.2
# via
# -c requirements.txt
# requests
-click==8.1.3
+click==8.1.7
# via
# mkdocs
# mkdocs-click
+ # mkdocstrings
colorama==0.4.6
# via
# griffe
# mkdocs-material
-fsspec==2023.5.0
+fsspec==2024.2.0
# via
# -c requirements.txt
# universal-pathlib
ghp-import==2.1.0
# via mkdocs
-griffe==0.28.0
+griffe==0.40.1
# via mkdocstrings-python
-idna==3.4
+idna==3.6
# via
# -c requirements.txt
# requests
-importlib-metadata==6.6.0
- # via
- # -c requirements.txt
- # textual
-jinja2==3.1.2
+jinja2==3.1.3
# via
# mkdocs
# mkdocs-material
# mkdocstrings
-linkify-it-py==2.0.2
+linkify-it-py==2.0.3
# via
# -c requirements.txt
# markdown-it-py
-markdown==3.3.7
+markdown==3.5.2
# via
# markdown-callouts
# mkdocs
@@ -73,17 +72,18 @@ markdown-callouts==0.4.0
# via hatch.envs.docs
markdown-exec==1.8.0
# via hatch.envs.docs
-markdown-it-py==2.2.0
+markdown-it-py==3.0.0
# via
# -c requirements.txt
# mdit-py-plugins
# rich
# textual
-markupsafe==2.1.2
+markupsafe==2.1.5
# via
# jinja2
+ # mkdocs
# mkdocstrings
-mdit-py-plugins==0.3.5
+mdit-py-plugins==0.4.0
# via
# -c requirements.txt
# markdown-it-py
@@ -93,7 +93,7 @@ mdurl==0.1.2
# markdown-it-py
mergedeep==1.3.4
# via mkdocs
-mkdocs==1.4.3
+mkdocs==1.5.3
# via
# hatch.envs.docs
# mkdocs-autorefs
@@ -102,38 +102,46 @@ mkdocs==1.4.3
# mkdocs-material
# mkdocs-section-index
# mkdocstrings
-mkdocs-autorefs==0.4.1
+mkdocs-autorefs==0.5.0
# via
# hatch.envs.docs
# mkdocstrings
-mkdocs-click==0.8.0
+mkdocs-click==0.8.1
# via hatch.envs.docs
-mkdocs-gen-files==0.4.0
+mkdocs-gen-files==0.5.0
# via hatch.envs.docs
-mkdocs-literate-nav==0.6.0
+mkdocs-literate-nav==0.6.1
# via hatch.envs.docs
-mkdocs-material==9.1.13
+mkdocs-material==9.5.10
# via hatch.envs.docs
-mkdocs-material-extensions==1.1.1
+mkdocs-material-extensions==1.3.1
# via mkdocs-material
-mkdocs-section-index==0.3.5
+mkdocs-section-index==0.3.8
# via hatch.envs.docs
-mkdocstrings==0.21.2
+mkdocstrings==0.24.0
# via
# hatch.envs.docs
# mkdocstrings-python
-mkdocstrings-python==1.0.0
+mkdocstrings-python==1.8.0
# via hatch.envs.docs
-packaging==23.1
+packaging==23.2
# via
# -c requirements.txt
# mkdocs
-pygments==2.15.1
+paginate==0.5.6
+ # via mkdocs-material
+pathspec==0.12.1
+ # via mkdocs
+platformdirs==4.2.0
+ # via
+ # mkdocs
+ # mkdocstrings
+pygments==2.17.2
# via
# -c requirements.txt
# mkdocs-material
# rich
-pymdown-extensions==10.0.1
+pymdown-extensions==10.7
# via
# hatch.envs.docs
# markdown-exec
@@ -143,20 +151,20 @@ python-dateutil==2.8.2
# via
# -c requirements.txt
# ghp-import
-pyyaml==6.0
+pyyaml==6.0.1
# via
# mkdocs
# pymdown-extensions
# pyyaml-env-tag
pyyaml-env-tag==0.1
# via mkdocs
-regex==2023.5.5
+regex==2023.12.25
# via mkdocs-material
-requests==2.30.0
+requests==2.31.0
# via
# -c requirements.txt
# mkdocs-material
-rich==13.3.5
+rich==13.7.0
# via
# -c requirements.txt
# textual
@@ -164,29 +172,25 @@ six==1.16.0
# via
# -c requirements.txt
# python-dateutil
-textual==0.27.0
+textual==0.48.2
# via
# -c requirements.txt
# hatch.envs.docs
-typing-extensions==4.5.0
+typing-extensions==4.9.0
# via
# -c requirements.txt
# textual
-uc-micro-py==1.0.2
+uc-micro-py==1.0.3
# via
# -c requirements.txt
# linkify-it-py
-universal-pathlib==0.0.24
+universal-pathlib==0.2.2
# via
# -c requirements.txt
# hatch.envs.docs
-urllib3==1.26.16
+urllib3==2.0.7
# via
# -c requirements.txt
# requests
-watchdog==3.0.0
+watchdog==4.0.0
# via mkdocs
-zipp==3.15.0
- # via
- # -c requirements.txt
- # importlib-metadata
diff --git a/requirements/requirements-test.txt b/requirements/requirements-test.txt
index 7a00121..f2e1867 100644
--- a/requirements/requirements-test.txt
+++ b/requirements/requirements-test.txt
@@ -1,12 +1,12 @@
#
# This file is autogenerated by hatch-pip-compile with Python 3.11
#
-# [constraints] requirements.txt (SHA256: ac0cd48906e0fabeea2bed80a2ebd5efd3c730ab841afa755168c420cb4c9b65)
+# [constraints] requirements.txt (SHA256: 9af71b46a759063aedcaa7dd5827200718b097dd959677acd642ee2dc7f49cd5)
#
# - pytest
# - pytest-cov
# - textual>=0.27.0
-# - universal-pathlib<=0.0.24,>=0.0.23
+# - universal-pathlib>=0.2.2
# - adlfs
# - aiohttp
# - gcsfs
@@ -15,15 +15,15 @@
# - s3fs
#
-adlfs==2023.8.0
+adlfs==2024.2.0
# via
# -c requirements.txt
# hatch.envs.test
-aiobotocore==2.5.4
+aiobotocore==2.11.2
# via
# -c requirements.txt
# s3fs
-aiohttp==3.8.4
+aiohttp==3.9.3
# via
# -c requirements.txt
# hatch.envs.test
@@ -39,15 +39,11 @@ aiosignal==1.3.1
# via
# -c requirements.txt
# aiohttp
-async-timeout==4.0.2
+attrs==23.2.0
# via
# -c requirements.txt
# aiohttp
-attrs==23.1.0
- # via
- # -c requirements.txt
- # aiohttp
-azure-core==1.29.1
+azure-core==1.30.0
# via
# -c requirements.txt
# adlfs
@@ -69,7 +65,7 @@ bcrypt==4.1.2
# via
# -c requirements.txt
# paramiko
-botocore==1.31.17
+botocore==1.34.34
# via
# -c requirements.txt
# aiobotocore
@@ -77,7 +73,7 @@ cachetools==5.3.2
# via
# -c requirements.txt
# google-auth
-certifi==2023.5.7
+certifi==2024.2.2
# via
# -c requirements.txt
# requests
@@ -87,12 +83,11 @@ cffi==1.16.0
# azure-datalake-store
# cryptography
# pynacl
-charset-normalizer==3.1.0
+charset-normalizer==3.3.2
# via
# -c requirements.txt
- # aiohttp
# requests
-coverage==7.2.5
+coverage==7.4.1
# via pytest-cov
cryptography==42.0.3
# via
@@ -106,19 +101,19 @@ decorator==5.1.1
# via
# -c requirements.txt
# gcsfs
-frozenlist==1.3.3
+frozenlist==1.4.1
# via
# -c requirements.txt
# aiohttp
# aiosignal
-fsspec==2023.5.0
+fsspec==2024.2.0
# via
# -c requirements.txt
# adlfs
# gcsfs
# s3fs
# universal-pathlib
-gcsfs==2023.5.0
+gcsfs==2024.2.0
# via
# -c requirements.txt
# hatch.envs.test
@@ -160,15 +155,11 @@ googleapis-common-protos==1.62.0
# via
# -c requirements.txt
# google-api-core
-idna==3.4
+idna==3.6
# via
# -c requirements.txt
# requests
# yarl
-importlib-metadata==6.6.0
- # via
- # -c requirements.txt
- # textual
iniconfig==2.0.0
# via pytest
isodate==0.6.1
@@ -179,17 +170,17 @@ jmespath==1.0.1
# via
# -c requirements.txt
# botocore
-linkify-it-py==2.0.2
+linkify-it-py==2.0.3
# via
# -c requirements.txt
# markdown-it-py
-markdown-it-py==2.2.0
+markdown-it-py==3.0.0
# via
# -c requirements.txt
# mdit-py-plugins
# rich
# textual
-mdit-py-plugins==0.3.5
+mdit-py-plugins==0.4.0
# via
# -c requirements.txt
# markdown-it-py
@@ -207,7 +198,7 @@ msal-extensions==1.1.0
# via
# -c requirements.txt
# azure-identity
-multidict==6.0.4
+multidict==6.0.5
# via
# -c requirements.txt
# aiohttp
@@ -216,7 +207,7 @@ oauthlib==3.2.2
# via
# -c requirements.txt
# requests-oauthlib
-packaging==23.1
+packaging==23.2
# via
# -c requirements.txt
# msal-extensions
@@ -225,7 +216,7 @@ paramiko==3.4.0
# via
# -c requirements.txt
# hatch.envs.test
-pluggy==1.0.0
+pluggy==1.4.0
# via pytest
portalocker==2.8.2
# via
@@ -249,7 +240,7 @@ pycparser==2.21
# via
# -c requirements.txt
# cffi
-pygments==2.15.1
+pygments==2.17.2
# via
# -c requirements.txt
# rich
@@ -262,17 +253,17 @@ pynacl==1.5.0
# via
# -c requirements.txt
# paramiko
-pytest==7.3.1
+pytest==8.0.1
# via
# hatch.envs.test
# pytest-cov
-pytest-cov==4.0.0
+pytest-cov==4.1.0
# via hatch.envs.test
python-dateutil==2.8.2
# via
# -c requirements.txt
# botocore
-requests==2.30.0
+requests==2.31.0
# via
# -c requirements.txt
# hatch.envs.test
@@ -287,7 +278,7 @@ requests-oauthlib==1.3.1
# via
# -c requirements.txt
# google-auth-oauthlib
-rich==13.3.5
+rich==13.7.0
# via
# -c requirements.txt
# textual
@@ -295,7 +286,7 @@ rsa==4.9
# via
# -c requirements.txt
# google-auth
-s3fs==2023.5.0
+s3fs==2024.2.0
# via
# -c requirements.txt
# hatch.envs.test
@@ -305,38 +296,34 @@ six==1.16.0
# azure-core
# isodate
# python-dateutil
-textual==0.27.0
+textual==0.48.2
# via
# -c requirements.txt
# hatch.envs.test
-typing-extensions==4.5.0
+typing-extensions==4.9.0
# via
# -c requirements.txt
# azure-core
# azure-storage-blob
# textual
-uc-micro-py==1.0.2
+uc-micro-py==1.0.3
# via
# -c requirements.txt
# linkify-it-py
-universal-pathlib==0.0.24
+universal-pathlib==0.2.2
# via
# -c requirements.txt
# hatch.envs.test
-urllib3==1.26.16
+urllib3==2.0.7
# via
# -c requirements.txt
# botocore
# requests
-wrapt==1.15.0
+wrapt==1.16.0
# via
# -c requirements.txt
# aiobotocore
-yarl==1.9.2
+yarl==1.9.4
# via
# -c requirements.txt
# aiohttp
-zipp==3.15.0
- # via
- # -c requirements.txt
- # importlib-metadata
diff --git a/textual_universal_directorytree/alternate_paths.py b/textual_universal_directorytree/alternate_paths.py
index c009437..da110fc 100644
--- a/textual_universal_directorytree/alternate_paths.py
+++ b/textual_universal_directorytree/alternate_paths.py
@@ -7,27 +7,11 @@
from os import getenv
from typing import Any
-from upath import UPath
-from upath.core import _FSSpecAccessor
from upath.implementations.cloud import S3Path
+from upath.implementations.github import GitHubPath as UGitHubPath
-class _GitHubAccessor(_FSSpecAccessor):
- """
- FSSpec Accessor for GitHub
- """
-
- def __init__(self, *args: Any, **kwargs: Any):
- """
- Initialize the GitHub Accessor
- """
- token = getenv("GITHUB_TOKEN")
- if token is not None:
- kwargs.update({"username": "Bearer", "token": token})
- super().__init__(*args, **kwargs)
-
-
-class GitHubPath(UPath):
+class GitHubPath(UGitHubPath):
"""
GitHubPath
@@ -35,35 +19,30 @@ class GitHubPath(UPath):
the Directory Tree
"""
- _default_accessor = _GitHubAccessor
-
- def __new__(cls, path: str | GitHubPath) -> GitHubPath:
+ def __init__(
+ self, *args: Any, protocol: str | None = None, **storage_options: Any
+ ) -> None:
"""
- New GitHub Path
+ Initialize the GitHubPath with GitHub Token Authentication
"""
- file_path = cls.handle_github_url(path)
- return super().__new__(cls, file_path)
-
- @property
- def path(self) -> str:
+ if "token" not in storage_options:
+ token = getenv("GITHUB_TOKEN")
+ if token is not None:
+ storage_options.update({"username": "Bearer", "token": token})
+ handled_args = args
+ if "sha" not in storage_options:
+ handled_url = self.handle_github_url(args[0])
+ handled_args = (handled_url, *args[1:])
+ super().__init__(*handled_args, protocol=protocol, **storage_options)
+
+ def __str__(self) -> str:
"""
- Paths get their leading slash stripped
+ String representation of the GitHubPath
"""
- return super().path.strip("/")
-
- @property
- def name(self) -> str:
- """
- Override the name for top level repo
- """
- if self.path == "":
- org = self._accessor._fs.org
- repo = self._accessor._fs.repo
- sha = self._accessor._fs.storage_options["sha"]
- github_name = f"{org}:{repo}@{sha}"
- return github_name
- else:
- return super().name
+ return (
+ f"{self.protocol}://{self.storage_options['org']}:"
+ f"{self.storage_options['repo']}@{self.storage_options['sha']}"
+ )
@classmethod
def handle_github_url(cls, url: str | GitHubPath) -> str:
@@ -80,7 +59,6 @@ def handle_github_url(cls, url: str | GitHubPath) -> str:
"Install `textual-universal-directorytree` with the `remote` "
"extra to install requests."
) from e
-
url = str(url)
gitub_prefix = "github://"
if gitub_prefix in url and "@" not in url:
diff --git a/textual_universal_directorytree/app.py b/textual_universal_directorytree/app.py
index 293a9ad..ae4e07d 100644
--- a/textual_universal_directorytree/app.py
+++ b/textual_universal_directorytree/app.py
@@ -1,13 +1,19 @@
+"""
+Example Universal Directory Tree App
+"""
+
+from __future__ import annotations
+
import argparse
-from typing import Any, ClassVar, List
+from typing import Any, ClassVar
-import upath
from rich.syntax import Syntax
from textual import on
from textual.app import App, ComposeResult
from textual.binding import BindingType
from textual.containers import Horizontal, VerticalScroll
from textual.widgets import DirectoryTree, Footer, Header, Static
+from upath import UPath
from textual_universal_directorytree import UniversalDirectoryTree
@@ -17,14 +23,14 @@ class UniversalDirectoryTreeApp(App):
The power of upath and fsspec in a Textual app
"""
- BINDINGS: ClassVar[List[BindingType]] = [
+ BINDINGS: ClassVar[list[BindingType]] = [
("q", "quit", "Quit"),
]
- def __init__(self, path: str, *args: Any, **kwargs: Any):
+ def __init__(self, path: str | UPath, *args: Any, **kwargs: Any):
super().__init__(*args, **kwargs)
- self.universal_path = path
- self.file_content = Static()
+ self.universal_path = UPath(path).resolve()
+ self.file_content = Static(expand=True)
def compose(self) -> ComposeResult:
yield Header()
@@ -40,9 +46,12 @@ def handle_file_selected(self, message: DirectoryTree.FileSelected) -> None:
Objects returned by the FileSelected event are upath.UPath objects and
they are compatible with the familiar pathlib.Path API built into Python.
"""
- selected_file_path = message.path
- file_content = selected_file_path.read_text(errors="replace")
- lexer = Syntax.guess_lexer(path=str(selected_file_path))
+ try:
+ file_content = message.path.read_text()
+ except UnicodeDecodeError:
+ self.file_content.update("")
+ return None
+ lexer = Syntax.guess_lexer(path=message.path.name)
code = Syntax(code=file_content, lexer=lexer)
self.file_content.update(code)
@@ -54,8 +63,7 @@ def cli() -> None:
parser = argparse.ArgumentParser(description="Universal Directory Tree")
parser.add_argument("path", type=str, help="Path to open", default=".")
args = parser.parse_args()
- file_path = str(upath.UPath(args.path).resolve()).rstrip("/")
- app = UniversalDirectoryTreeApp(path=file_path)
+ app = UniversalDirectoryTreeApp(path=args.path)
app.run()
diff --git a/textual_universal_directorytree/universal_directory_tree.py b/textual_universal_directorytree/universal_directory_tree.py
index b0588eb..23c6e80 100644
--- a/textual_universal_directorytree/universal_directory_tree.py
+++ b/textual_universal_directorytree/universal_directory_tree.py
@@ -5,15 +5,11 @@
from textual.widgets import DirectoryTree
from upath import UPath, registry
-registry._registry.known_implementations[
- "github"
-] = "textual_universal_directorytree.alternate_paths.GitHubPath"
-registry._registry.known_implementations[
- "s3"
-] = "textual_universal_directorytree.alternate_paths.S3TextualPath"
-registry._registry.known_implementations[
- "s3a"
-] = "textual_universal_directorytree.alternate_paths.S3TextualPath"
+from textual_universal_directorytree.alternate_paths import GitHubPath, S3TextualPath
+
+registry.register_implementation(protocol="github", cls=GitHubPath, clobber=True)
+registry.register_implementation(protocol="s3", cls=S3TextualPath, clobber=True)
+registry.register_implementation(protocol="s3a", cls=S3TextualPath, clobber=True)
class UniversalDirectoryTree(DirectoryTree):