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.
- {proteworks-0.1.1 → proteworks-0.1.2}/PKG-INFO +1 -1
- {proteworks-0.1.1 → proteworks-0.1.2}/pyproject.toml +1 -1
- {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks/auth.py +14 -2
- {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks.egg-info/PKG-INFO +1 -1
- {proteworks-0.1.1 → proteworks-0.1.2}/tests/test_cli.py +29 -1
- {proteworks-0.1.1 → proteworks-0.1.2}/README.md +0 -0
- {proteworks-0.1.1 → proteworks-0.1.2}/setup.cfg +0 -0
- {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks/__init__.py +0 -0
- {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks/api.py +0 -0
- {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks/cli.py +0 -0
- {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks/config.py +0 -0
- {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks/index.py +0 -0
- {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks/orgs.py +0 -0
- {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks/pull.py +0 -0
- {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks/push.py +0 -0
- {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks/redact.py +0 -0
- {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks.egg-info/SOURCES.txt +0 -0
- {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks.egg-info/dependency_links.txt +0 -0
- {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks.egg-info/entry_points.txt +0 -0
- {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks.egg-info/requires.txt +0 -0
- {proteworks-0.1.1 → proteworks-0.1.2}/src/proteworks.egg-info/top_level.txt +0 -0
|
@@ -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 =
|
|
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)
|
|
@@ -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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|