proteworks 0.1.1__tar.gz → 0.1.2__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 (21) hide show
  1. {proteworks-0.1.1 → proteworks-0.1.2}/PKG-INFO +1 -1
  2. {proteworks-0.1.1 → proteworks-0.1.2}/pyproject.toml +1 -1
  3. {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks/auth.py +14 -2
  4. {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks.egg-info/PKG-INFO +1 -1
  5. {proteworks-0.1.1 → proteworks-0.1.2}/tests/test_cli.py +29 -1
  6. {proteworks-0.1.1 → proteworks-0.1.2}/README.md +0 -0
  7. {proteworks-0.1.1 → proteworks-0.1.2}/setup.cfg +0 -0
  8. {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks/__init__.py +0 -0
  9. {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks/api.py +0 -0
  10. {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks/cli.py +0 -0
  11. {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks/config.py +0 -0
  12. {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks/index.py +0 -0
  13. {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks/orgs.py +0 -0
  14. {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks/pull.py +0 -0
  15. {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks/push.py +0 -0
  16. {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks/redact.py +0 -0
  17. {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks.egg-info/SOURCES.txt +0 -0
  18. {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks.egg-info/dependency_links.txt +0 -0
  19. {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks.egg-info/entry_points.txt +0 -0
  20. {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks.egg-info/requires.txt +0 -0
  21. {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: proteworks
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: Sync files with Proteworks using file-browser paths.
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "proteworks"
3
- version = "0.1.1"
3
+ version = "0.1.2"
4
4
  description = "Sync files with Proteworks using file-browser paths."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -4,6 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  import base64
6
6
  import hashlib
7
+ import os
7
8
  import secrets
8
9
  import webbrowser
9
10
  from http.server import BaseHTTPRequestHandler, HTTPServer
@@ -65,6 +66,18 @@ def loopback_redirect_uri(port: int = LOOPBACK_PORT) -> str:
65
66
  return f"http://127.0.0.1:{port}{LOOPBACK_REDIRECT_PATH}"
66
67
 
67
68
 
69
+ def open_browser(url: str) -> bool:
70
+ """Open the sign-in page. The browser's own startup errors stay hidden."""
71
+ saved_stderr = os.dup(2)
72
+ try:
73
+ with open(os.devnull, "wb") as discarded:
74
+ os.dup2(discarded.fileno(), 2)
75
+ return bool(webbrowser.open(url))
76
+ finally:
77
+ os.dup2(saved_stderr, 2)
78
+ os.close(saved_stderr)
79
+
80
+
68
81
  def login(settings: Settings, token_store: TokenStore, stderr) -> None:
69
82
  """Open a browser, receive the loopback redirect, and save the access token."""
70
83
  verifier, challenge = pkce_pair()
@@ -77,9 +90,8 @@ def login(settings: Settings, token_store: TokenStore, stderr) -> None:
77
90
  ) from exc
78
91
  redirect_uri = loopback_redirect_uri()
79
92
  url = authorize_url(settings, redirect_uri, state, challenge)
80
- print(f"Auth0 must allow this callback URL: {redirect_uri}", file=stderr)
81
93
  print("Opening a browser to sign in.", file=stderr)
82
- opened = webbrowser.open(url)
94
+ opened = open_browser(url)
83
95
  if not opened:
84
96
  print("Open this URL to sign in:", file=stderr)
85
97
  print(url, file=stderr)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: proteworks
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: Sync files with Proteworks using file-browser paths.
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -5,12 +5,15 @@ from __future__ import annotations
5
5
  import hashlib
6
6
  import json
7
7
  import mimetypes
8
+ import os
9
+ import subprocess
10
+ import sys
8
11
  import threading
9
12
  from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
10
13
  from pathlib import Path
11
14
  from urllib.parse import parse_qs, urlparse
12
15
 
13
- from proteworks.auth import loopback_redirect_uri
16
+ from proteworks.auth import loopback_redirect_uri, open_browser
14
17
  from proteworks.cli import main
15
18
  from proteworks.config import Settings
16
19
  from proteworks.push import _iter_local_files
@@ -220,6 +223,31 @@ def test_login_callback_url_is_fixed():
220
223
  assert loopback_redirect_uri() == "http://127.0.0.1:8765/callback"
221
224
 
222
225
 
226
+ def test_open_browser_hides_child_stderr(monkeypatch):
227
+ def noisy_open(_url: str) -> bool:
228
+ subprocess.run(
229
+ [sys.executable, "-c", "import os; os.write(2, b'zygote broken pipe\\n')"],
230
+ check=False,
231
+ )
232
+ return True
233
+
234
+ monkeypatch.setattr("proteworks.auth.webbrowser.open", noisy_open)
235
+ read_fd, write_fd = os.pipe()
236
+ saved = os.dup(2)
237
+ os.dup2(write_fd, 2)
238
+ os.close(write_fd)
239
+ try:
240
+ assert open_browser("https://example.test/authorize") is True
241
+ os.write(2, b"still open\n")
242
+ finally:
243
+ os.dup2(saved, 2)
244
+ os.close(saved)
245
+ captured = os.read(read_fd, 1024)
246
+ os.close(read_fd)
247
+ assert b"zygote" not in captured
248
+ assert b"still open" in captured
249
+
250
+
223
251
  def test_root_help_lists_commands(capsys):
224
252
  try:
225
253
  main(["--help"])
File without changes
File without changes