rbrowser 0.1.6__tar.gz
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.
- rbrowser-0.1.6/MANIFEST.in +2 -0
- rbrowser-0.1.6/PKG-INFO +123 -0
- rbrowser-0.1.6/README.md +111 -0
- rbrowser-0.1.6/pyproject.toml +30 -0
- rbrowser-0.1.6/rbrowser.egg-info/PKG-INFO +123 -0
- rbrowser-0.1.6/rbrowser.egg-info/SOURCES.txt +122 -0
- rbrowser-0.1.6/rbrowser.egg-info/dependency_links.txt +1 -0
- rbrowser-0.1.6/rbrowser.egg-info/entry_points.txt +2 -0
- rbrowser-0.1.6/rbrowser.egg-info/requires.txt +3 -0
- rbrowser-0.1.6/rbrowser.egg-info/top_level.txt +1 -0
- rbrowser-0.1.6/rbrowser_cli/__init__.py +3 -0
- rbrowser-0.1.6/rbrowser_cli/cli.py +143 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/desyrel/desyrel.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/desyrel/desyrel.xml +1923 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-16.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-16.xml +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-72.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-72.xml +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-ExtraLightBETA.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-ExtraLightBETA.xml +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-Light-18.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-Light-18.xml +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-Light-64.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-Light-64.xml +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-LightBETA-64.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-LightBETA-64.xml +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-LightBETA.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-LightBETA.xml +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-Regular.json +2183 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-Regular.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-Regular.xml +101 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-SemiBold-64.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-SemiBold-64.xml +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/inter.xml +793 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/inter_0.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter_regular/Inter-Regular.json +2183 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter_regular/Inter-Regular.ttf +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter_regular/font.0.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter_regular/font.1.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter_regular/font.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/opensans/OpenSans-Regular.json +1472 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/opensans/OpenSans-Regular.ttf +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/opensans/font.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/g3d/genome.g3d +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/icon/settings.svg +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/arrow_down.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/arrow_up.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ball_gray.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ball_gray3.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ball_gray_10x10.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ball_gray_5x5.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ball_white_100.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ball_white_20.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ball_white_40.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/base_A.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/base_C.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/base_G.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/base_T.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/base_U.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/circle_100.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/circle_black_100.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/circle_red.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/circle_white_100.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/diamond copy.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/diamond.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/diamond2.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/drop.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/drop_line.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ele_gray.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ele_grays.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ele_green.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ele_ocean.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ele_red.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ele_sky.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ele_soft_gray.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ele_yellow.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/texture.psd +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/texture_ATCG.psd +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/texture_circle_org.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/texture_diamond.psd +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/texture_grey_border_main.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/texture_grey_main.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/texture_grey_main.psd +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/triangle.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/favicon.ico +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/index.html +49 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/logo192.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/logo512.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/manifest.json +25 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/robots.txt +3 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/css/index.ArNRqnY1.css +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/css/index.CroWzXsC.css +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/css/index.DPMyIVYU.css +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/js/AppstoreAddOutlined.D5ilOMxt.chunk.js +3 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/js/CheckCircleRounded.DVZy-MCf.chunk.js +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/js/ClearAllRounded.CUJRdVDQ.chunk.js +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/js/ExpandMore.C46BDO5j.chunk.js +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/js/Refresh.C83YUbTk.chunk.js +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/js/d3-vendor.D2vplkPo.chunk.js +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/js/datahub-data.BkMvslYe.chunk.js +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.B36BqAW0.chunk.js +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.B79vQDf2.chunk.js +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.D1QXMsT8.chunk.js +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.DICxSQgm.chunk.js +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.DezPsQiY.chunk.js +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.DhVVPnZF.chunk.js +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.DpkFDdug.js +145 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.JBr0C4Rc.chunk.js +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.Lr6WmsZR.chunk.js +40 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.Pv0g6RaM.chunk.js +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.WaMjEOTD.chunk.js +31 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.oG4Fdp8e.chunk.js +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.pFX21XGS.chunk.js +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.qnCfw2-y.chunk.js +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/js/mui-vendor.C2wT3-V2.chunk.js +140 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/js/pixi-vendor.DwNHHdM-.chunk.js +1 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/js/react-vendor.C018e_IG.chunk.js +56 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/js/redux-vendor.BYT4ly2K.chunk.js +11 -0
- rbrowser-0.1.6/rbrowser_cli/frontend/static/media/logo.BdaLZdU8.png +0 -0
- rbrowser-0.1.6/rbrowser_cli/output.py +91 -0
- rbrowser-0.1.6/rbrowser_cli/path_parser.py +57 -0
- rbrowser-0.1.6/rbrowser_cli/server_local.py +236 -0
- rbrowser-0.1.6/rbrowser_cli/server_ssh.py +280 -0
- rbrowser-0.1.6/setup.cfg +4 -0
rbrowser-0.1.6/PKG-INFO
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rbrowser
|
|
3
|
+
Version: 0.1.6
|
|
4
|
+
Summary: Launch RBrowser with a local or remote (SSH) directory as a file server
|
|
5
|
+
Author: RBrowser Team
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.8
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: click>=8.0
|
|
10
|
+
Requires-Dist: flask>=2.0
|
|
11
|
+
Requires-Dist: flask-cors>=4.0
|
|
12
|
+
|
|
13
|
+
# RBrowser CLI
|
|
14
|
+
|
|
15
|
+
Launch [RBrowser](https://rbrowser.org) with a local or remote (SSH) directory
|
|
16
|
+
as a file server backend. **The frontend UI is bundled inside the wheel** —
|
|
17
|
+
one `pip install` and you're ready to go (no Node.js, no extra build step).
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install rbrowser-cli
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Open current directory (UI served from http://localhost:<port>)
|
|
29
|
+
rbrowser open .
|
|
30
|
+
|
|
31
|
+
# Open a specific directory
|
|
32
|
+
rbrowser open /data/myproject
|
|
33
|
+
|
|
34
|
+
# Open a remote SSH directory (requires ssh-agent or key auth)
|
|
35
|
+
rbrowser open user@host:/data/myproject
|
|
36
|
+
|
|
37
|
+
# Use a custom port
|
|
38
|
+
rbrowser open . --port 8888
|
|
39
|
+
|
|
40
|
+
# Override the bundled UI with a hosted RBrowser
|
|
41
|
+
rbrowser open . --frontend https://rbrowser.org
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The CLI prints (and auto-opens) a URL like
|
|
45
|
+
`http://localhost:<port>/#/main?fileServerUrl=...`, which jumps the user
|
|
46
|
+
directly to the Main view's File Explorer panel — no home-page detour.
|
|
47
|
+
|
|
48
|
+
When run on a remote SSH host, the URL is printed as a Ctrl+Click hyperlink so
|
|
49
|
+
you can open it from your local terminal.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Maintainer notes (release flow)
|
|
54
|
+
|
|
55
|
+
End users do **not** need to do this. To produce a wheel that ships the UI:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# One-shot: install JS deps, build frontend, build sdist + wheel
|
|
59
|
+
node rbrowser-cli/scripts/build_release.mjs
|
|
60
|
+
|
|
61
|
+
# Skip the npm install (faster local iterations)
|
|
62
|
+
node rbrowser-cli/scripts/build_release.mjs --skip-install
|
|
63
|
+
|
|
64
|
+
# Or via npm:
|
|
65
|
+
npm run release:cli # full pipeline
|
|
66
|
+
npm run build:cli-wheel # skip-install variant
|
|
67
|
+
|
|
68
|
+
# Output is in rbrowser-cli/dist/ (sdist + wheel)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Publishing to PyPI via GitHub Actions
|
|
72
|
+
|
|
73
|
+
The workflow [`.github/workflows/publish-rbrowser-cli.yml`](../.github/workflows/publish-rbrowser-cli.yml)
|
|
74
|
+
publishes a release to PyPI using **Trusted Publishing** (OIDC — no API
|
|
75
|
+
token in repo secrets). To set it up once:
|
|
76
|
+
|
|
77
|
+
1. On <https://pypi.org/manage/account/publishing/>, add a _pending publisher_:
|
|
78
|
+
- PyPI project name: `rbrowser-cli`
|
|
79
|
+
- Owner: `typekey` · Repository: `rna-browser`
|
|
80
|
+
- Workflow: `publish-rbrowser-cli.yml`
|
|
81
|
+
- Environment: `pypi`
|
|
82
|
+
2. In the GitHub repo Settings → Environments, create an environment named
|
|
83
|
+
`pypi` (optionally with a required reviewer).
|
|
84
|
+
|
|
85
|
+
Then to release:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# One-liner: bump patch version, build, commit, tag, push.
|
|
89
|
+
# (PyPI is published automatically by the GitHub Action.)
|
|
90
|
+
npm run release:cli:patch # 0.1.0 -> 0.1.1
|
|
91
|
+
npm run release:cli:minor # 0.1.0 -> 0.2.0
|
|
92
|
+
npm run release:cli:major # 0.1.0 -> 1.0.0
|
|
93
|
+
|
|
94
|
+
# Or pick an explicit version (and add --push when ready):
|
|
95
|
+
node rbrowser-cli/scripts/release.mjs 0.2.3 --push
|
|
96
|
+
|
|
97
|
+
# Dry-run / inspect first; create the tag locally without pushing:
|
|
98
|
+
node rbrowser-cli/scripts/release.mjs patch # local tag only
|
|
99
|
+
node rbrowser-cli/scripts/release.mjs patch --dry-run # print, don't mutate
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
What `release.mjs` does:
|
|
103
|
+
|
|
104
|
+
1. Resolves the new version (explicit or `patch` / `minor` / `major` bump).
|
|
105
|
+
2. Verifies the working tree is clean and on `main` (override with
|
|
106
|
+
`--allow-dirty` / `--branch=…`).
|
|
107
|
+
3. Rewrites `pyproject.toml`'s version.
|
|
108
|
+
4. Runs the full local build (skip with `--no-build`) so you can spot any
|
|
109
|
+
issue before the tag is pushed.
|
|
110
|
+
5. Commits, creates the annotated tag `rbrowser-cli-vX.Y.Z`, and (with
|
|
111
|
+
`--push`) pushes both to `origin` — which fires the publish workflow.
|
|
112
|
+
|
|
113
|
+
Manual fallback (no script):
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
# Update version in rbrowser-cli/pyproject.toml first.
|
|
117
|
+
git commit -am "chore(rbrowser-cli): release v0.1.1"
|
|
118
|
+
git tag rbrowser-cli-v0.1.1
|
|
119
|
+
git push origin main rbrowser-cli-v0.1.1
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
`pyproject.toml` already declares `frontend/**/*` as `package-data`, so the
|
|
123
|
+
built UI is included in the wheel automatically.
|
rbrowser-0.1.6/README.md
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# RBrowser CLI
|
|
2
|
+
|
|
3
|
+
Launch [RBrowser](https://rbrowser.org) with a local or remote (SSH) directory
|
|
4
|
+
as a file server backend. **The frontend UI is bundled inside the wheel** —
|
|
5
|
+
one `pip install` and you're ready to go (no Node.js, no extra build step).
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install rbrowser-cli
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Open current directory (UI served from http://localhost:<port>)
|
|
17
|
+
rbrowser open .
|
|
18
|
+
|
|
19
|
+
# Open a specific directory
|
|
20
|
+
rbrowser open /data/myproject
|
|
21
|
+
|
|
22
|
+
# Open a remote SSH directory (requires ssh-agent or key auth)
|
|
23
|
+
rbrowser open user@host:/data/myproject
|
|
24
|
+
|
|
25
|
+
# Use a custom port
|
|
26
|
+
rbrowser open . --port 8888
|
|
27
|
+
|
|
28
|
+
# Override the bundled UI with a hosted RBrowser
|
|
29
|
+
rbrowser open . --frontend https://rbrowser.org
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The CLI prints (and auto-opens) a URL like
|
|
33
|
+
`http://localhost:<port>/#/main?fileServerUrl=...`, which jumps the user
|
|
34
|
+
directly to the Main view's File Explorer panel — no home-page detour.
|
|
35
|
+
|
|
36
|
+
When run on a remote SSH host, the URL is printed as a Ctrl+Click hyperlink so
|
|
37
|
+
you can open it from your local terminal.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Maintainer notes (release flow)
|
|
42
|
+
|
|
43
|
+
End users do **not** need to do this. To produce a wheel that ships the UI:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# One-shot: install JS deps, build frontend, build sdist + wheel
|
|
47
|
+
node rbrowser-cli/scripts/build_release.mjs
|
|
48
|
+
|
|
49
|
+
# Skip the npm install (faster local iterations)
|
|
50
|
+
node rbrowser-cli/scripts/build_release.mjs --skip-install
|
|
51
|
+
|
|
52
|
+
# Or via npm:
|
|
53
|
+
npm run release:cli # full pipeline
|
|
54
|
+
npm run build:cli-wheel # skip-install variant
|
|
55
|
+
|
|
56
|
+
# Output is in rbrowser-cli/dist/ (sdist + wheel)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Publishing to PyPI via GitHub Actions
|
|
60
|
+
|
|
61
|
+
The workflow [`.github/workflows/publish-rbrowser-cli.yml`](../.github/workflows/publish-rbrowser-cli.yml)
|
|
62
|
+
publishes a release to PyPI using **Trusted Publishing** (OIDC — no API
|
|
63
|
+
token in repo secrets). To set it up once:
|
|
64
|
+
|
|
65
|
+
1. On <https://pypi.org/manage/account/publishing/>, add a _pending publisher_:
|
|
66
|
+
- PyPI project name: `rbrowser-cli`
|
|
67
|
+
- Owner: `typekey` · Repository: `rna-browser`
|
|
68
|
+
- Workflow: `publish-rbrowser-cli.yml`
|
|
69
|
+
- Environment: `pypi`
|
|
70
|
+
2. In the GitHub repo Settings → Environments, create an environment named
|
|
71
|
+
`pypi` (optionally with a required reviewer).
|
|
72
|
+
|
|
73
|
+
Then to release:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# One-liner: bump patch version, build, commit, tag, push.
|
|
77
|
+
# (PyPI is published automatically by the GitHub Action.)
|
|
78
|
+
npm run release:cli:patch # 0.1.0 -> 0.1.1
|
|
79
|
+
npm run release:cli:minor # 0.1.0 -> 0.2.0
|
|
80
|
+
npm run release:cli:major # 0.1.0 -> 1.0.0
|
|
81
|
+
|
|
82
|
+
# Or pick an explicit version (and add --push when ready):
|
|
83
|
+
node rbrowser-cli/scripts/release.mjs 0.2.3 --push
|
|
84
|
+
|
|
85
|
+
# Dry-run / inspect first; create the tag locally without pushing:
|
|
86
|
+
node rbrowser-cli/scripts/release.mjs patch # local tag only
|
|
87
|
+
node rbrowser-cli/scripts/release.mjs patch --dry-run # print, don't mutate
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
What `release.mjs` does:
|
|
91
|
+
|
|
92
|
+
1. Resolves the new version (explicit or `patch` / `minor` / `major` bump).
|
|
93
|
+
2. Verifies the working tree is clean and on `main` (override with
|
|
94
|
+
`--allow-dirty` / `--branch=…`).
|
|
95
|
+
3. Rewrites `pyproject.toml`'s version.
|
|
96
|
+
4. Runs the full local build (skip with `--no-build`) so you can spot any
|
|
97
|
+
issue before the tag is pushed.
|
|
98
|
+
5. Commits, creates the annotated tag `rbrowser-cli-vX.Y.Z`, and (with
|
|
99
|
+
`--push`) pushes both to `origin` — which fires the publish workflow.
|
|
100
|
+
|
|
101
|
+
Manual fallback (no script):
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# Update version in rbrowser-cli/pyproject.toml first.
|
|
105
|
+
git commit -am "chore(rbrowser-cli): release v0.1.1"
|
|
106
|
+
git tag rbrowser-cli-v0.1.1
|
|
107
|
+
git push origin main rbrowser-cli-v0.1.1
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
`pyproject.toml` already declares `frontend/**/*` as `package-data`, so the
|
|
111
|
+
built UI is included in the wheel automatically.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "rbrowser"
|
|
7
|
+
version = "0.1.6"
|
|
8
|
+
description = "Launch RBrowser with a local or remote (SSH) directory as a file server"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
authors = [{ name = "RBrowser Team" }]
|
|
12
|
+
license = { text = "MIT" }
|
|
13
|
+
dependencies = [
|
|
14
|
+
"click>=8.0",
|
|
15
|
+
"flask>=2.0",
|
|
16
|
+
"flask-cors>=4.0",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
[project.scripts]
|
|
20
|
+
rbrowser = "rbrowser_cli.cli:main"
|
|
21
|
+
|
|
22
|
+
[tool.setuptools.packages.find]
|
|
23
|
+
where = ["."]
|
|
24
|
+
include = ["rbrowser_cli*"]
|
|
25
|
+
|
|
26
|
+
[tool.setuptools.package-data]
|
|
27
|
+
rbrowser_cli = [
|
|
28
|
+
"frontend/**/*",
|
|
29
|
+
"frontend/index.html",
|
|
30
|
+
]
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rbrowser
|
|
3
|
+
Version: 0.1.6
|
|
4
|
+
Summary: Launch RBrowser with a local or remote (SSH) directory as a file server
|
|
5
|
+
Author: RBrowser Team
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.8
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: click>=8.0
|
|
10
|
+
Requires-Dist: flask>=2.0
|
|
11
|
+
Requires-Dist: flask-cors>=4.0
|
|
12
|
+
|
|
13
|
+
# RBrowser CLI
|
|
14
|
+
|
|
15
|
+
Launch [RBrowser](https://rbrowser.org) with a local or remote (SSH) directory
|
|
16
|
+
as a file server backend. **The frontend UI is bundled inside the wheel** —
|
|
17
|
+
one `pip install` and you're ready to go (no Node.js, no extra build step).
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install rbrowser-cli
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Open current directory (UI served from http://localhost:<port>)
|
|
29
|
+
rbrowser open .
|
|
30
|
+
|
|
31
|
+
# Open a specific directory
|
|
32
|
+
rbrowser open /data/myproject
|
|
33
|
+
|
|
34
|
+
# Open a remote SSH directory (requires ssh-agent or key auth)
|
|
35
|
+
rbrowser open user@host:/data/myproject
|
|
36
|
+
|
|
37
|
+
# Use a custom port
|
|
38
|
+
rbrowser open . --port 8888
|
|
39
|
+
|
|
40
|
+
# Override the bundled UI with a hosted RBrowser
|
|
41
|
+
rbrowser open . --frontend https://rbrowser.org
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The CLI prints (and auto-opens) a URL like
|
|
45
|
+
`http://localhost:<port>/#/main?fileServerUrl=...`, which jumps the user
|
|
46
|
+
directly to the Main view's File Explorer panel — no home-page detour.
|
|
47
|
+
|
|
48
|
+
When run on a remote SSH host, the URL is printed as a Ctrl+Click hyperlink so
|
|
49
|
+
you can open it from your local terminal.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Maintainer notes (release flow)
|
|
54
|
+
|
|
55
|
+
End users do **not** need to do this. To produce a wheel that ships the UI:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# One-shot: install JS deps, build frontend, build sdist + wheel
|
|
59
|
+
node rbrowser-cli/scripts/build_release.mjs
|
|
60
|
+
|
|
61
|
+
# Skip the npm install (faster local iterations)
|
|
62
|
+
node rbrowser-cli/scripts/build_release.mjs --skip-install
|
|
63
|
+
|
|
64
|
+
# Or via npm:
|
|
65
|
+
npm run release:cli # full pipeline
|
|
66
|
+
npm run build:cli-wheel # skip-install variant
|
|
67
|
+
|
|
68
|
+
# Output is in rbrowser-cli/dist/ (sdist + wheel)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Publishing to PyPI via GitHub Actions
|
|
72
|
+
|
|
73
|
+
The workflow [`.github/workflows/publish-rbrowser-cli.yml`](../.github/workflows/publish-rbrowser-cli.yml)
|
|
74
|
+
publishes a release to PyPI using **Trusted Publishing** (OIDC — no API
|
|
75
|
+
token in repo secrets). To set it up once:
|
|
76
|
+
|
|
77
|
+
1. On <https://pypi.org/manage/account/publishing/>, add a _pending publisher_:
|
|
78
|
+
- PyPI project name: `rbrowser-cli`
|
|
79
|
+
- Owner: `typekey` · Repository: `rna-browser`
|
|
80
|
+
- Workflow: `publish-rbrowser-cli.yml`
|
|
81
|
+
- Environment: `pypi`
|
|
82
|
+
2. In the GitHub repo Settings → Environments, create an environment named
|
|
83
|
+
`pypi` (optionally with a required reviewer).
|
|
84
|
+
|
|
85
|
+
Then to release:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# One-liner: bump patch version, build, commit, tag, push.
|
|
89
|
+
# (PyPI is published automatically by the GitHub Action.)
|
|
90
|
+
npm run release:cli:patch # 0.1.0 -> 0.1.1
|
|
91
|
+
npm run release:cli:minor # 0.1.0 -> 0.2.0
|
|
92
|
+
npm run release:cli:major # 0.1.0 -> 1.0.0
|
|
93
|
+
|
|
94
|
+
# Or pick an explicit version (and add --push when ready):
|
|
95
|
+
node rbrowser-cli/scripts/release.mjs 0.2.3 --push
|
|
96
|
+
|
|
97
|
+
# Dry-run / inspect first; create the tag locally without pushing:
|
|
98
|
+
node rbrowser-cli/scripts/release.mjs patch # local tag only
|
|
99
|
+
node rbrowser-cli/scripts/release.mjs patch --dry-run # print, don't mutate
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
What `release.mjs` does:
|
|
103
|
+
|
|
104
|
+
1. Resolves the new version (explicit or `patch` / `minor` / `major` bump).
|
|
105
|
+
2. Verifies the working tree is clean and on `main` (override with
|
|
106
|
+
`--allow-dirty` / `--branch=…`).
|
|
107
|
+
3. Rewrites `pyproject.toml`'s version.
|
|
108
|
+
4. Runs the full local build (skip with `--no-build`) so you can spot any
|
|
109
|
+
issue before the tag is pushed.
|
|
110
|
+
5. Commits, creates the annotated tag `rbrowser-cli-vX.Y.Z`, and (with
|
|
111
|
+
`--push`) pushes both to `origin` — which fires the publish workflow.
|
|
112
|
+
|
|
113
|
+
Manual fallback (no script):
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
# Update version in rbrowser-cli/pyproject.toml first.
|
|
117
|
+
git commit -am "chore(rbrowser-cli): release v0.1.1"
|
|
118
|
+
git tag rbrowser-cli-v0.1.1
|
|
119
|
+
git push origin main rbrowser-cli-v0.1.1
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
`pyproject.toml` already declares `frontend/**/*` as `package-data`, so the
|
|
123
|
+
built UI is included in the wheel automatically.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
MANIFEST.in
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
rbrowser.egg-info/PKG-INFO
|
|
5
|
+
rbrowser.egg-info/SOURCES.txt
|
|
6
|
+
rbrowser.egg-info/dependency_links.txt
|
|
7
|
+
rbrowser.egg-info/entry_points.txt
|
|
8
|
+
rbrowser.egg-info/requires.txt
|
|
9
|
+
rbrowser.egg-info/top_level.txt
|
|
10
|
+
rbrowser_cli/__init__.py
|
|
11
|
+
rbrowser_cli/cli.py
|
|
12
|
+
rbrowser_cli/output.py
|
|
13
|
+
rbrowser_cli/path_parser.py
|
|
14
|
+
rbrowser_cli/server_local.py
|
|
15
|
+
rbrowser_cli/server_ssh.py
|
|
16
|
+
rbrowser_cli/frontend/favicon.ico
|
|
17
|
+
rbrowser_cli/frontend/index.html
|
|
18
|
+
rbrowser_cli/frontend/logo192.png
|
|
19
|
+
rbrowser_cli/frontend/logo512.png
|
|
20
|
+
rbrowser_cli/frontend/manifest.json
|
|
21
|
+
rbrowser_cli/frontend/robots.txt
|
|
22
|
+
rbrowser_cli/frontend/assets/fonts/desyrel/desyrel.png
|
|
23
|
+
rbrowser_cli/frontend/assets/fonts/desyrel/desyrel.xml
|
|
24
|
+
rbrowser_cli/frontend/assets/fonts/inter/Inter-16.png
|
|
25
|
+
rbrowser_cli/frontend/assets/fonts/inter/Inter-16.xml
|
|
26
|
+
rbrowser_cli/frontend/assets/fonts/inter/Inter-72.png
|
|
27
|
+
rbrowser_cli/frontend/assets/fonts/inter/Inter-72.xml
|
|
28
|
+
rbrowser_cli/frontend/assets/fonts/inter/Inter-ExtraLightBETA.png
|
|
29
|
+
rbrowser_cli/frontend/assets/fonts/inter/Inter-ExtraLightBETA.xml
|
|
30
|
+
rbrowser_cli/frontend/assets/fonts/inter/Inter-Light-18.png
|
|
31
|
+
rbrowser_cli/frontend/assets/fonts/inter/Inter-Light-18.xml
|
|
32
|
+
rbrowser_cli/frontend/assets/fonts/inter/Inter-Light-64.png
|
|
33
|
+
rbrowser_cli/frontend/assets/fonts/inter/Inter-Light-64.xml
|
|
34
|
+
rbrowser_cli/frontend/assets/fonts/inter/Inter-LightBETA-64.png
|
|
35
|
+
rbrowser_cli/frontend/assets/fonts/inter/Inter-LightBETA-64.xml
|
|
36
|
+
rbrowser_cli/frontend/assets/fonts/inter/Inter-LightBETA.png
|
|
37
|
+
rbrowser_cli/frontend/assets/fonts/inter/Inter-LightBETA.xml
|
|
38
|
+
rbrowser_cli/frontend/assets/fonts/inter/Inter-Regular.json
|
|
39
|
+
rbrowser_cli/frontend/assets/fonts/inter/Inter-Regular.png
|
|
40
|
+
rbrowser_cli/frontend/assets/fonts/inter/Inter-Regular.xml
|
|
41
|
+
rbrowser_cli/frontend/assets/fonts/inter/Inter-SemiBold-64.png
|
|
42
|
+
rbrowser_cli/frontend/assets/fonts/inter/Inter-SemiBold-64.xml
|
|
43
|
+
rbrowser_cli/frontend/assets/fonts/inter/inter.xml
|
|
44
|
+
rbrowser_cli/frontend/assets/fonts/inter/inter_0.png
|
|
45
|
+
rbrowser_cli/frontend/assets/fonts/inter_regular/Inter-Regular.json
|
|
46
|
+
rbrowser_cli/frontend/assets/fonts/inter_regular/Inter-Regular.ttf
|
|
47
|
+
rbrowser_cli/frontend/assets/fonts/inter_regular/font.0.png
|
|
48
|
+
rbrowser_cli/frontend/assets/fonts/inter_regular/font.1.png
|
|
49
|
+
rbrowser_cli/frontend/assets/fonts/inter_regular/font.png
|
|
50
|
+
rbrowser_cli/frontend/assets/fonts/opensans/OpenSans-Regular.json
|
|
51
|
+
rbrowser_cli/frontend/assets/fonts/opensans/OpenSans-Regular.ttf
|
|
52
|
+
rbrowser_cli/frontend/assets/fonts/opensans/font.png
|
|
53
|
+
rbrowser_cli/frontend/assets/g3d/genome.g3d
|
|
54
|
+
rbrowser_cli/frontend/assets/icon/settings.svg
|
|
55
|
+
rbrowser_cli/frontend/assets/textures/arrow_down.png
|
|
56
|
+
rbrowser_cli/frontend/assets/textures/arrow_up.png
|
|
57
|
+
rbrowser_cli/frontend/assets/textures/ball_gray.png
|
|
58
|
+
rbrowser_cli/frontend/assets/textures/ball_gray3.png
|
|
59
|
+
rbrowser_cli/frontend/assets/textures/ball_gray_10x10.png
|
|
60
|
+
rbrowser_cli/frontend/assets/textures/ball_gray_5x5.png
|
|
61
|
+
rbrowser_cli/frontend/assets/textures/ball_white_100.png
|
|
62
|
+
rbrowser_cli/frontend/assets/textures/ball_white_20.png
|
|
63
|
+
rbrowser_cli/frontend/assets/textures/ball_white_40.png
|
|
64
|
+
rbrowser_cli/frontend/assets/textures/base_A.png
|
|
65
|
+
rbrowser_cli/frontend/assets/textures/base_C.png
|
|
66
|
+
rbrowser_cli/frontend/assets/textures/base_G.png
|
|
67
|
+
rbrowser_cli/frontend/assets/textures/base_T.png
|
|
68
|
+
rbrowser_cli/frontend/assets/textures/base_U.png
|
|
69
|
+
rbrowser_cli/frontend/assets/textures/circle_100.png
|
|
70
|
+
rbrowser_cli/frontend/assets/textures/circle_black_100.png
|
|
71
|
+
rbrowser_cli/frontend/assets/textures/circle_red.png
|
|
72
|
+
rbrowser_cli/frontend/assets/textures/circle_white_100.png
|
|
73
|
+
rbrowser_cli/frontend/assets/textures/diamond copy.png
|
|
74
|
+
rbrowser_cli/frontend/assets/textures/diamond.png
|
|
75
|
+
rbrowser_cli/frontend/assets/textures/diamond2.png
|
|
76
|
+
rbrowser_cli/frontend/assets/textures/drop.png
|
|
77
|
+
rbrowser_cli/frontend/assets/textures/drop_line.png
|
|
78
|
+
rbrowser_cli/frontend/assets/textures/ele_gray.png
|
|
79
|
+
rbrowser_cli/frontend/assets/textures/ele_grays.png
|
|
80
|
+
rbrowser_cli/frontend/assets/textures/ele_green.png
|
|
81
|
+
rbrowser_cli/frontend/assets/textures/ele_ocean.png
|
|
82
|
+
rbrowser_cli/frontend/assets/textures/ele_red.png
|
|
83
|
+
rbrowser_cli/frontend/assets/textures/ele_sky.png
|
|
84
|
+
rbrowser_cli/frontend/assets/textures/ele_soft_gray.png
|
|
85
|
+
rbrowser_cli/frontend/assets/textures/ele_yellow.png
|
|
86
|
+
rbrowser_cli/frontend/assets/textures/texture.psd
|
|
87
|
+
rbrowser_cli/frontend/assets/textures/texture_ATCG.psd
|
|
88
|
+
rbrowser_cli/frontend/assets/textures/texture_circle_org.png
|
|
89
|
+
rbrowser_cli/frontend/assets/textures/texture_diamond.psd
|
|
90
|
+
rbrowser_cli/frontend/assets/textures/texture_grey_border_main.png
|
|
91
|
+
rbrowser_cli/frontend/assets/textures/texture_grey_main.png
|
|
92
|
+
rbrowser_cli/frontend/assets/textures/texture_grey_main.psd
|
|
93
|
+
rbrowser_cli/frontend/assets/textures/triangle.png
|
|
94
|
+
rbrowser_cli/frontend/static/css/index.ArNRqnY1.css
|
|
95
|
+
rbrowser_cli/frontend/static/css/index.CroWzXsC.css
|
|
96
|
+
rbrowser_cli/frontend/static/css/index.DPMyIVYU.css
|
|
97
|
+
rbrowser_cli/frontend/static/js/AppstoreAddOutlined.D5ilOMxt.chunk.js
|
|
98
|
+
rbrowser_cli/frontend/static/js/CheckCircleRounded.DVZy-MCf.chunk.js
|
|
99
|
+
rbrowser_cli/frontend/static/js/ClearAllRounded.CUJRdVDQ.chunk.js
|
|
100
|
+
rbrowser_cli/frontend/static/js/ExpandMore.C46BDO5j.chunk.js
|
|
101
|
+
rbrowser_cli/frontend/static/js/Refresh.C83YUbTk.chunk.js
|
|
102
|
+
rbrowser_cli/frontend/static/js/d3-vendor.D2vplkPo.chunk.js
|
|
103
|
+
rbrowser_cli/frontend/static/js/datahub-data.BkMvslYe.chunk.js
|
|
104
|
+
rbrowser_cli/frontend/static/js/index.B36BqAW0.chunk.js
|
|
105
|
+
rbrowser_cli/frontend/static/js/index.B79vQDf2.chunk.js
|
|
106
|
+
rbrowser_cli/frontend/static/js/index.D1QXMsT8.chunk.js
|
|
107
|
+
rbrowser_cli/frontend/static/js/index.DICxSQgm.chunk.js
|
|
108
|
+
rbrowser_cli/frontend/static/js/index.DezPsQiY.chunk.js
|
|
109
|
+
rbrowser_cli/frontend/static/js/index.DhVVPnZF.chunk.js
|
|
110
|
+
rbrowser_cli/frontend/static/js/index.DpkFDdug.js
|
|
111
|
+
rbrowser_cli/frontend/static/js/index.JBr0C4Rc.chunk.js
|
|
112
|
+
rbrowser_cli/frontend/static/js/index.Lr6WmsZR.chunk.js
|
|
113
|
+
rbrowser_cli/frontend/static/js/index.Pv0g6RaM.chunk.js
|
|
114
|
+
rbrowser_cli/frontend/static/js/index.WaMjEOTD.chunk.js
|
|
115
|
+
rbrowser_cli/frontend/static/js/index.oG4Fdp8e.chunk.js
|
|
116
|
+
rbrowser_cli/frontend/static/js/index.pFX21XGS.chunk.js
|
|
117
|
+
rbrowser_cli/frontend/static/js/index.qnCfw2-y.chunk.js
|
|
118
|
+
rbrowser_cli/frontend/static/js/mui-vendor.C2wT3-V2.chunk.js
|
|
119
|
+
rbrowser_cli/frontend/static/js/pixi-vendor.DwNHHdM-.chunk.js
|
|
120
|
+
rbrowser_cli/frontend/static/js/react-vendor.C018e_IG.chunk.js
|
|
121
|
+
rbrowser_cli/frontend/static/js/redux-vendor.BYT4ly2K.chunk.js
|
|
122
|
+
rbrowser_cli/frontend/static/media/logo.BdaLZdU8.png
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
rbrowser_cli
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"""Click CLI entry-point for ``rbrowser``."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import socket
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from urllib.parse import quote, urlencode
|
|
9
|
+
|
|
10
|
+
import click
|
|
11
|
+
from werkzeug.serving import make_server
|
|
12
|
+
|
|
13
|
+
from .output import is_remote_session, print_banner
|
|
14
|
+
from .path_parser import parse_path
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
FRONTEND_FALLBACK = "https://rbrowser.org"
|
|
18
|
+
_BUNDLED_FRONTEND_DIR = Path(__file__).parent / "frontend"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _has_bundled_frontend() -> bool:
|
|
22
|
+
return (_BUNDLED_FRONTEND_DIR / "index.html").is_file()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _pick_port(preferred: int) -> int:
|
|
26
|
+
"""Return an available port. If ``preferred`` is 0, OS picks one."""
|
|
27
|
+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
28
|
+
try:
|
|
29
|
+
s.bind(("0.0.0.0", preferred))
|
|
30
|
+
except OSError as e:
|
|
31
|
+
raise click.ClickException(f"Port {preferred} is not available: {e}") from e
|
|
32
|
+
return s.getsockname()[1]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _detect_host_for_url(is_remote_cli: bool) -> str:
|
|
36
|
+
"""Pick the host the user's browser should connect to.
|
|
37
|
+
|
|
38
|
+
- When the CLI runs locally, ``localhost`` is the safest default.
|
|
39
|
+
- When the CLI runs on a remote SSH server, fall back to the externally
|
|
40
|
+
visible hostname / first non-loopback IPv4 so the user's local browser
|
|
41
|
+
can reach it (or, if SSH port-forwarding is set up, ``localhost``).
|
|
42
|
+
"""
|
|
43
|
+
if not is_remote_cli:
|
|
44
|
+
return "localhost"
|
|
45
|
+
try:
|
|
46
|
+
host = socket.gethostname()
|
|
47
|
+
ip = socket.gethostbyname(host)
|
|
48
|
+
if ip and not ip.startswith("127."):
|
|
49
|
+
return host
|
|
50
|
+
except OSError:
|
|
51
|
+
pass
|
|
52
|
+
return "localhost"
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@click.group()
|
|
56
|
+
@click.version_option()
|
|
57
|
+
def cli() -> None:
|
|
58
|
+
"""RBrowser CLI."""
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@cli.command("open")
|
|
62
|
+
@click.argument("path")
|
|
63
|
+
@click.option("--port", "-p", type=int, default=0, show_default=False,
|
|
64
|
+
help="Port to bind (default: random free port).")
|
|
65
|
+
@click.option("--frontend", default=None,
|
|
66
|
+
help=("RBrowser frontend. Default: bundled (if installed), else "
|
|
67
|
+
f"{FRONTEND_FALLBACK}. Pass an http(s):// URL to override."))
|
|
68
|
+
@click.option("--host", default="0.0.0.0", show_default=True,
|
|
69
|
+
help="Bind address for the file server.")
|
|
70
|
+
def open_cmd(path: str, port: int, frontend: str | None, host: str) -> None:
|
|
71
|
+
"""Start the file server for PATH and open RBrowser.
|
|
72
|
+
|
|
73
|
+
PATH may be a local directory or ``user@host:/remote/path``.
|
|
74
|
+
"""
|
|
75
|
+
parsed = parse_path(path)
|
|
76
|
+
|
|
77
|
+
# Decide frontend mode: bundled (served from this same server) vs external URL.
|
|
78
|
+
use_bundled = False
|
|
79
|
+
if frontend is None:
|
|
80
|
+
if _has_bundled_frontend():
|
|
81
|
+
use_bundled = True
|
|
82
|
+
else:
|
|
83
|
+
frontend = FRONTEND_FALLBACK
|
|
84
|
+
elif frontend.lower() in ("bundled", "local"):
|
|
85
|
+
if not _has_bundled_frontend():
|
|
86
|
+
raise click.ClickException(
|
|
87
|
+
"Bundled frontend not found. Reinstall rbrowser-cli or pass --frontend URL."
|
|
88
|
+
)
|
|
89
|
+
use_bundled = True
|
|
90
|
+
|
|
91
|
+
static_dir = str(_BUNDLED_FRONTEND_DIR) if use_bundled else None
|
|
92
|
+
|
|
93
|
+
if parsed.is_remote:
|
|
94
|
+
from .server_ssh import create_app
|
|
95
|
+
app = create_app(parsed.ssh_target, parsed.path, static_dir=static_dir)
|
|
96
|
+
else:
|
|
97
|
+
from .server_local import create_app
|
|
98
|
+
app = create_app(parsed.path, static_dir=static_dir)
|
|
99
|
+
|
|
100
|
+
bound_port = _pick_port(port) if port else _pick_port(0)
|
|
101
|
+
remote_session = is_remote_session()
|
|
102
|
+
url_host = _detect_host_for_url(remote_session)
|
|
103
|
+
|
|
104
|
+
server_url = f"http://{url_host}:{bound_port}"
|
|
105
|
+
if use_bundled:
|
|
106
|
+
# Bundled frontend: served from the same origin → only need ?root=.
|
|
107
|
+
# The frontend infers fileServerUrl from window.location.
|
|
108
|
+
qs = urlencode({"root": parsed.display()}, quote_via=quote)
|
|
109
|
+
frontend_url = f"{server_url}/#/main?{qs}"
|
|
110
|
+
else:
|
|
111
|
+
# External UI: must include fileServerUrl (different origin).
|
|
112
|
+
qs = urlencode({
|
|
113
|
+
"fileServerUrl": server_url,
|
|
114
|
+
"root": parsed.display(),
|
|
115
|
+
}, quote_via=quote)
|
|
116
|
+
frontend_url = f"{frontend.rstrip('/')}/#/main?{qs}"
|
|
117
|
+
|
|
118
|
+
print_banner(
|
|
119
|
+
server_url=server_url,
|
|
120
|
+
frontend_url=frontend_url,
|
|
121
|
+
root_display=parsed.display(),
|
|
122
|
+
is_remote=remote_session,
|
|
123
|
+
bundled=use_bundled,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
server = make_server(host, bound_port, app, threaded=True)
|
|
127
|
+
try:
|
|
128
|
+
server.serve_forever()
|
|
129
|
+
except KeyboardInterrupt:
|
|
130
|
+
click.echo("\nShutting down…")
|
|
131
|
+
server.shutdown()
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def main() -> None:
|
|
135
|
+
try:
|
|
136
|
+
cli()
|
|
137
|
+
except click.ClickException as e:
|
|
138
|
+
e.show()
|
|
139
|
+
sys.exit(e.exit_code)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
if __name__ == "__main__":
|
|
143
|
+
main()
|
|
Binary file
|