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.
Files changed (124) hide show
  1. rbrowser-0.1.6/MANIFEST.in +2 -0
  2. rbrowser-0.1.6/PKG-INFO +123 -0
  3. rbrowser-0.1.6/README.md +111 -0
  4. rbrowser-0.1.6/pyproject.toml +30 -0
  5. rbrowser-0.1.6/rbrowser.egg-info/PKG-INFO +123 -0
  6. rbrowser-0.1.6/rbrowser.egg-info/SOURCES.txt +122 -0
  7. rbrowser-0.1.6/rbrowser.egg-info/dependency_links.txt +1 -0
  8. rbrowser-0.1.6/rbrowser.egg-info/entry_points.txt +2 -0
  9. rbrowser-0.1.6/rbrowser.egg-info/requires.txt +3 -0
  10. rbrowser-0.1.6/rbrowser.egg-info/top_level.txt +1 -0
  11. rbrowser-0.1.6/rbrowser_cli/__init__.py +3 -0
  12. rbrowser-0.1.6/rbrowser_cli/cli.py +143 -0
  13. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/desyrel/desyrel.png +0 -0
  14. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/desyrel/desyrel.xml +1923 -0
  15. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-16.png +0 -0
  16. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-16.xml +1 -0
  17. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-72.png +0 -0
  18. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-72.xml +1 -0
  19. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-ExtraLightBETA.png +0 -0
  20. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-ExtraLightBETA.xml +1 -0
  21. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-Light-18.png +0 -0
  22. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-Light-18.xml +1 -0
  23. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-Light-64.png +0 -0
  24. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-Light-64.xml +1 -0
  25. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-LightBETA-64.png +0 -0
  26. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-LightBETA-64.xml +1 -0
  27. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-LightBETA.png +0 -0
  28. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-LightBETA.xml +1 -0
  29. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-Regular.json +2183 -0
  30. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-Regular.png +0 -0
  31. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-Regular.xml +101 -0
  32. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-SemiBold-64.png +0 -0
  33. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/Inter-SemiBold-64.xml +1 -0
  34. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/inter.xml +793 -0
  35. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter/inter_0.png +0 -0
  36. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter_regular/Inter-Regular.json +2183 -0
  37. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter_regular/Inter-Regular.ttf +0 -0
  38. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter_regular/font.0.png +0 -0
  39. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter_regular/font.1.png +0 -0
  40. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/inter_regular/font.png +0 -0
  41. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/opensans/OpenSans-Regular.json +1472 -0
  42. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/opensans/OpenSans-Regular.ttf +0 -0
  43. rbrowser-0.1.6/rbrowser_cli/frontend/assets/fonts/opensans/font.png +0 -0
  44. rbrowser-0.1.6/rbrowser_cli/frontend/assets/g3d/genome.g3d +0 -0
  45. rbrowser-0.1.6/rbrowser_cli/frontend/assets/icon/settings.svg +1 -0
  46. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/arrow_down.png +0 -0
  47. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/arrow_up.png +0 -0
  48. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ball_gray.png +0 -0
  49. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ball_gray3.png +0 -0
  50. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ball_gray_10x10.png +0 -0
  51. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ball_gray_5x5.png +0 -0
  52. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ball_white_100.png +0 -0
  53. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ball_white_20.png +0 -0
  54. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ball_white_40.png +0 -0
  55. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/base_A.png +0 -0
  56. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/base_C.png +0 -0
  57. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/base_G.png +0 -0
  58. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/base_T.png +0 -0
  59. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/base_U.png +0 -0
  60. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/circle_100.png +0 -0
  61. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/circle_black_100.png +0 -0
  62. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/circle_red.png +0 -0
  63. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/circle_white_100.png +0 -0
  64. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/diamond copy.png +0 -0
  65. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/diamond.png +0 -0
  66. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/diamond2.png +0 -0
  67. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/drop.png +0 -0
  68. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/drop_line.png +0 -0
  69. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ele_gray.png +0 -0
  70. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ele_grays.png +0 -0
  71. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ele_green.png +0 -0
  72. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ele_ocean.png +0 -0
  73. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ele_red.png +0 -0
  74. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ele_sky.png +0 -0
  75. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ele_soft_gray.png +0 -0
  76. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/ele_yellow.png +0 -0
  77. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/texture.psd +0 -0
  78. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/texture_ATCG.psd +0 -0
  79. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/texture_circle_org.png +0 -0
  80. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/texture_diamond.psd +0 -0
  81. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/texture_grey_border_main.png +0 -0
  82. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/texture_grey_main.png +0 -0
  83. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/texture_grey_main.psd +0 -0
  84. rbrowser-0.1.6/rbrowser_cli/frontend/assets/textures/triangle.png +0 -0
  85. rbrowser-0.1.6/rbrowser_cli/frontend/favicon.ico +0 -0
  86. rbrowser-0.1.6/rbrowser_cli/frontend/index.html +49 -0
  87. rbrowser-0.1.6/rbrowser_cli/frontend/logo192.png +0 -0
  88. rbrowser-0.1.6/rbrowser_cli/frontend/logo512.png +0 -0
  89. rbrowser-0.1.6/rbrowser_cli/frontend/manifest.json +25 -0
  90. rbrowser-0.1.6/rbrowser_cli/frontend/robots.txt +3 -0
  91. rbrowser-0.1.6/rbrowser_cli/frontend/static/css/index.ArNRqnY1.css +1 -0
  92. rbrowser-0.1.6/rbrowser_cli/frontend/static/css/index.CroWzXsC.css +1 -0
  93. rbrowser-0.1.6/rbrowser_cli/frontend/static/css/index.DPMyIVYU.css +1 -0
  94. rbrowser-0.1.6/rbrowser_cli/frontend/static/js/AppstoreAddOutlined.D5ilOMxt.chunk.js +3 -0
  95. rbrowser-0.1.6/rbrowser_cli/frontend/static/js/CheckCircleRounded.DVZy-MCf.chunk.js +1 -0
  96. rbrowser-0.1.6/rbrowser_cli/frontend/static/js/ClearAllRounded.CUJRdVDQ.chunk.js +1 -0
  97. rbrowser-0.1.6/rbrowser_cli/frontend/static/js/ExpandMore.C46BDO5j.chunk.js +1 -0
  98. rbrowser-0.1.6/rbrowser_cli/frontend/static/js/Refresh.C83YUbTk.chunk.js +1 -0
  99. rbrowser-0.1.6/rbrowser_cli/frontend/static/js/d3-vendor.D2vplkPo.chunk.js +1 -0
  100. rbrowser-0.1.6/rbrowser_cli/frontend/static/js/datahub-data.BkMvslYe.chunk.js +1 -0
  101. rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.B36BqAW0.chunk.js +1 -0
  102. rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.B79vQDf2.chunk.js +1 -0
  103. rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.D1QXMsT8.chunk.js +1 -0
  104. rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.DICxSQgm.chunk.js +1 -0
  105. rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.DezPsQiY.chunk.js +1 -0
  106. rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.DhVVPnZF.chunk.js +1 -0
  107. rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.DpkFDdug.js +145 -0
  108. rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.JBr0C4Rc.chunk.js +1 -0
  109. rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.Lr6WmsZR.chunk.js +40 -0
  110. rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.Pv0g6RaM.chunk.js +1 -0
  111. rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.WaMjEOTD.chunk.js +31 -0
  112. rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.oG4Fdp8e.chunk.js +1 -0
  113. rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.pFX21XGS.chunk.js +1 -0
  114. rbrowser-0.1.6/rbrowser_cli/frontend/static/js/index.qnCfw2-y.chunk.js +1 -0
  115. rbrowser-0.1.6/rbrowser_cli/frontend/static/js/mui-vendor.C2wT3-V2.chunk.js +140 -0
  116. rbrowser-0.1.6/rbrowser_cli/frontend/static/js/pixi-vendor.DwNHHdM-.chunk.js +1 -0
  117. rbrowser-0.1.6/rbrowser_cli/frontend/static/js/react-vendor.C018e_IG.chunk.js +56 -0
  118. rbrowser-0.1.6/rbrowser_cli/frontend/static/js/redux-vendor.BYT4ly2K.chunk.js +11 -0
  119. rbrowser-0.1.6/rbrowser_cli/frontend/static/media/logo.BdaLZdU8.png +0 -0
  120. rbrowser-0.1.6/rbrowser_cli/output.py +91 -0
  121. rbrowser-0.1.6/rbrowser_cli/path_parser.py +57 -0
  122. rbrowser-0.1.6/rbrowser_cli/server_local.py +236 -0
  123. rbrowser-0.1.6/rbrowser_cli/server_ssh.py +280 -0
  124. rbrowser-0.1.6/setup.cfg +4 -0
@@ -0,0 +1,2 @@
1
+ recursive-include rbrowser_cli/frontend *
2
+ include README.md
@@ -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,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,2 @@
1
+ [console_scripts]
2
+ rbrowser = rbrowser_cli.cli:main
@@ -0,0 +1,3 @@
1
+ click>=8.0
2
+ flask>=2.0
3
+ flask-cors>=4.0
@@ -0,0 +1 @@
1
+ rbrowser_cli
@@ -0,0 +1,3 @@
1
+ """RBrowser CLI — launch RBrowser with a local or remote directory."""
2
+
3
+ __version__ = "0.1.0"
@@ -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()