Skip to content

Commit c0c0cdc

Browse files
authored
Init flow (#41)
* implements basic auth flow * refactor gha * fix dev group * ruff check and format * raise exit
1 parent e1c228f commit c0c0cdc

File tree

11 files changed

+1204
-108
lines changed

11 files changed

+1204
-108
lines changed

.github/workflows/black.yml

-16
This file was deleted.

.github/workflows/pytest.yml renamed to .github/workflows/ci.yml

+20-17
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,37 @@
1-
name: tests
1+
name: CI
22
on:
33
pull_request:
44
branches:
5-
- '*'
5+
- main
66
push:
77
branches:
88
- main
99

1010

1111
jobs:
12-
build:
12+
lint:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v4
16+
- uses: astral-sh/setup-uv@v3
17+
18+
- name: Ruff check
19+
run: uv run ruff check --output-format=github
1320

21+
- name: Ruff format
22+
run: uv run ruff format --check
23+
24+
test:
25+
needs: lint
1426
runs-on: ubuntu-latest
1527
strategy:
1628
matrix:
17-
python-version: ["3.8", "3.9", "3.10", "3.11"]
18-
29+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
30+
1931
steps:
20-
- uses: actions/checkout@v3
21-
- name: Set up Python ${{ matrix.python-version }}
22-
uses: actions/setup-python@v4
23-
with:
24-
python-version: ${{ matrix.python-version }}
25-
- name: Install dependencies
26-
run: |
27-
python -m pip install --upgrade pip
28-
pip install -e .[dev]
29-
- name: Build coverage file
30-
run: |
31-
pytest --junitxml=pytest.xml --cov-report "xml:coverage.xml" --cov=shbin tests/
32+
- uses: actions/checkout@v4
33+
- uses: astral-sh/setup-uv@v3
34+
- run: UV_PYTHON=${{ matrix.python-version }} uv run pytest --junitxml=pytest.xml --cov-report "xml:coverage.xml" --cov=shbin tests/
3235

3336
- name: Pytest coverage comment
3437
uses: MishaKav/pytest-coverage-comment@main

.github/workflows/release.yml

+7-9
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,22 @@
11
name: Publish Python 🐍 distributions 📦 to PyPI
22

33
on:
4-
push:
5-
tags:
6-
- "*"
4+
release:
5+
types: [created]
6+
7+
permissions:
8+
contents: read
79

810
jobs:
911
pypi-publish:
1012
name: upload release to PyPI
1113
runs-on: ubuntu-latest
12-
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
1314
permissions:
14-
# IMPORTANT: this permission is mandatory for trusted publishing
1515
id-token: write
1616
steps:
1717
- name: Checkout
1818
uses: actions/checkout@v3
19-
- name: install build
20-
run: python -m pip install --upgrade build
21-
- name: build
22-
run: python -m build
19+
- uses: astral-sh/setup-uv@v5
20+
- run: uv build
2321
- name: Publish package distributions to PyPI
2422
uses: pypa/gh-action-pypi-publish@release/v1

README.md

+33-34
Original file line numberDiff line numberDiff line change
@@ -93,22 +93,16 @@ have the target repository fully cloned locally.
9393

9494
# Install
9595

96-
The recommended way is to use [pipx](https://pypa.github.io/pipx/)
96+
The recommended way is to use [uv](https://docs.astral.sh/uv/)
9797

9898
```console
99-
pipx install shbin
100-
```
101-
102-
Alternatively, install directly with `pip`.
103-
104-
```console
105-
pip install --user shbin
99+
uv tool install shbin
106100
```
107101

108102
To install the latest development version from the repository:
109103

110104
```console
111-
pip install --user https://github.com/Shiphero/shbin/archive/refs/heads/main.zip
105+
uv tool install https://github.com/Shiphero/shbin/archive/refs/heads/main.zip
112106
```
113107

114108
## OSX
@@ -131,43 +125,48 @@ port install file
131125

132126
# Setup
133127

134-
Create a [new fine-grained personal token](https://github.com/settings/personal-access-tokens/new)
128+
To authenticate, simply run:
129+
```
130+
shbin init
131+
```
132+
133+
This command will guide you through creating a token and and selecting a repository,
134+
then store them locally so that `shbin` can use them right away.
135+
136+
Alternatively, you can **manually** create a [new fine-grained personal token](https://github.com/settings/personal-access-tokens/new)
135137
on Github restricted to your "pastebin" repository (under your user or
136-
your organization's ownership), with read and write permissions on
137-
"Contents".
138+
your organization's ownership), with **read and write** permission on **Contents**:
138139

139140
![image](https://user-images.githubusercontent.com/2355719/238758491-9d15e7e6-e4b7-43c8-a321-b65c968fc7e0.png)
140141

141-
- Then set the environment variables in your preferred place:
142+
Then set the environment variables:
142143

143144
```
144145
export SHBIN_GITHUB_TOKEN="<your personal token>"
145-
export SHBIN_REPO="<user_or_org>/<repo>" # example "Shiphero/pastebin"
146-
```
147-
148-
- By default `shbin` assigns a top-level folder to separate the content
149-
uploaded by each user. This can be changed using the `SHBIN_NAMESPACE`
150-
environment variable or the `--namespace` argument from the command
151-
line. For example:
146+
export SHBIN_REPO="<user_or_org>/<repo>" # example "myorg/pastebin"
147+
```
152148

153-
- `export SHBIN_NAMESPACE=""` # no namespace
154-
- `export SHBIN_NAMESPACE="pastebin_folder"` # the full pastebin is inside pastebin_folder/"
155-
- `export SHBIN_NAMESPACE="pastebin_folder/{user}"` # mix of both: each user has its own subfolder
156-
inside `pastebin_folder/`
157149

158-
- [optional] To interact with the clipboard, we use the library `pyclip`.
159-
This may require some additional system dependencies
160-
depending your operating system.
161-
See [these notes](https://github.com/spyoungtech/pyclip#platform-specific-notesissues).
150+
By default `shbin` assigns a top-level folder to separate the content
151+
uploaded by each user. This can be changed using the `SHBIN_NAMESPACE`
152+
environment variable or the `--namespace` argument from the command
153+
line. For example:
162154

163-
If you want to disable the automatic copying of the URL to the clipboard
164-
you can set the environment variable `SHBIN_COPY_URL=false` (or "0" or "no").
155+
- `export SHBIN_NAMESPACE=""` # no namespace
156+
- `export SHBIN_NAMESPACE="pastebin_folder"` # the full pastebin is inside pastebin_folder/"
157+
- `export SHBIN_NAMESPACE="pastebin_folder/{user}"` # mix of both: each user has its own subfolder
158+
inside `pastebin_folder/`
165159

166-
This is useful in some Linux distributions that use Wayland as the call via `wl-copy`
167-
that `pyclip` uses in such environment can be slow.
160+
> [!NOTE]
161+
> To interact with the clipboard, we use the library `pyclip`. This may require some additional system
162+
> dependencies depending your operating system. See [these notes](https://github.com/spyoungtech/pyclip#platform-specific-notesissues).
163+
> If you want to disable the automatic copying of the URL to the clipboard
164+
> you can set the environment variable `SHBIN_COPY_URL=false` (or "0" or "no").
165+
>
166+
> This is useful in some Linux distributions that use Wayland as the call via `wl-copy`
167+
> that `pyclip` uses in such environment can be slow.
168168
169-
Nice video courtesy of [tuterm](https://github.com/veracioux/tuterm), [asciinema](https://asciinema.org/)
170-
and [svg-term-cli](https://github.com/marionebl/svg-term-cli)
169+
Nice video courtesy of [tuterm](https://github.com/veracioux/tuterm), [asciinema](https://asciinema.org/) and [svg-term-cli](https://github.com/marionebl/svg-term-cli)
171170

172171
PRs are welcome!
173172

demo/demo.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
import this
1+
import this # noqa

demo/demo_2.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
print(f"Hello World")
1+
print("Hello World")

pyproject.toml

+7-12
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ dependencies = [
2525
"python-magic >= 0.4.27",
2626
"docopt-ng >= 0.8.1",
2727
"rich >= 12.5",
28+
"platformdirs>=4.3.6",
2829
]
2930
dynamic = ["version", "description"]
3031

@@ -35,20 +36,14 @@ Changelog = "https://github.com/Shiphero/shbin/blob/main/CHANGELOG.md"
3536
[project.scripts]
3637
shbin = "shbin:main"
3738

38-
[project.optional-dependencies]
39+
[tool.ruff]
40+
line-length = 120
41+
42+
[dependency-groups]
3943
dev = [
4044
"pytest",
41-
"black",
4245
"pytest-cov",
43-
"flake8",
46+
"pytest-mock>=3.14.0",
47+
"ruff",
4448
]
4549

46-
[tool.black]
47-
target-version = ["py38"]
48-
line-length = 120
49-
color = true
50-
51-
[tool.ruff]
52-
target-version = "py38"
53-
line-length = 120
54-

shbin.py renamed to shbin/__init__.py

+24-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""
22
Turns a Github repo into a pastebin.
33
"""
4+
45
import itertools
56
import os
67
import pathlib
@@ -13,11 +14,14 @@
1314
from docopt import DocoptExit, docopt
1415
from github import Github, GithubException
1516
from rich import print
17+
from .auth import do_auth, load_config
18+
1619

1720
usage = """
1821
1922
Usage:
2023
shbin dl <url_or_path>
24+
shbin auth
2125
shbin (<path>... | -x | -) [-f <file-name>] [-n] [-m <message>] [-d <target-dir>]
2226
[--namespace=<namespace>] [--url-link-to-pages]
2327
shbin (-h | --help)
@@ -35,7 +39,7 @@
3539
-p, --url-link-to-pages Reformat the url to link to Github pages.
3640
"""
3741

38-
__version__ = "0.3.0"
42+
__version__ = "0.4.0"
3943

4044

4145
class FakePath:
@@ -56,8 +60,17 @@ def __getattr__(self, attr):
5660

5761

5862
def get_repo_and_user():
59-
gh = Github(os.environ["SHBIN_GITHUB_TOKEN"])
60-
return gh.get_repo(os.environ["SHBIN_REPO"]), gh.get_user().login
63+
data = load_config()
64+
token = os.getenv("SHBIN_GITHUB_TOKEN", data.get("token"))
65+
repo = os.getenv("SHBIN_REPO", data.get("repo"))
66+
if not token or not repo:
67+
print(
68+
"[red]x[/red] Missing SHBIN_GITHUB_TOKEN or SHBIN_REPO environment variables. "
69+
"Run [bold]shbin auth[/bold] to authenticate."
70+
)
71+
raise SystemExit(1)
72+
gh = Github(token)
73+
return gh.get_repo(repo), gh.get_user().login
6174

6275

6376
def expand_paths(path_or_patterns):
@@ -122,12 +135,13 @@ def download(url_or_path, repo, user):
122135

123136
def main(argv=None) -> None:
124137
args = docopt(__doc__ + usage, argv, version=__version__)
125-
try:
126-
repo, user = get_repo_and_user()
127-
except Exception as e:
128-
raise DocoptExit(
129-
f"Ensure SHBIN_GITHUB_TOKEN and SHBIN_REPO environment variables are correctly set. (error {e})"
130-
)
138+
139+
if args["auth"]:
140+
do_auth()
141+
return
142+
143+
repo, user = get_repo_and_user()
144+
131145
# resolves namespace + target-dir (without ending slash)
132146
# it also interpolates {user}
133147
namespace = args.get("--namespace")
@@ -150,7 +164,7 @@ def main(argv=None) -> None:
150164
content = sys.stdin.buffer.read()
151165

152166
if args["--file-name"]:
153-
file_name = f'{args["--file-name"]}'
167+
file_name = f"{args['--file-name']}"
154168
else:
155169
extension = get_extension(content)
156170
# TODO try autodectect extension via pygment if .txt was guessed.

0 commit comments

Comments
 (0)