ghps 0.2__tar.gz → 0.3__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.
@@ -5,6 +5,15 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
6
 
7
7
  ## [Unreleased]
8
+ ## [0.3] - 2026-04-05
9
+ ### Added
10
+ - `auto_open` parameter
11
+ - `--auto-open` CLI argument
12
+ - Random port support
13
+ ### Changed
14
+ - Test system modified
15
+ - CLI error messages updated
16
+ - `README.md` updated
8
17
  ## [0.2] - 2026-03-19
9
18
  ### Added
10
19
  - Logo
@@ -18,7 +27,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
18
27
  - Command line interface
19
28
  - Test system
20
29
 
21
- [Unreleased]: https://github.com/sepandhaghighi/ghps/compare/v0.2...dev
30
+ [Unreleased]: https://github.com/sepandhaghighi/ghps/compare/v0.3...dev
31
+ [0.3]: https://github.com/sepandhaghighi/ghps/compare/v0.2...v0.3
22
32
  [0.2]: https://github.com/sepandhaghighi/ghps/compare/v0.1...v0.2
23
33
  [0.1]: https://github.com/sepandhaghighi/ghps/compare/bc0a425...v0.1
24
34
 
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ghps
3
- Version: 0.2
3
+ Version: 0.3
4
4
  Summary: Ghps: A Minimal GitHub Pages Simulator for Local Development
5
5
  Home-page: https://github.com/sepandhaghighi/ghps
6
- Download-URL: https://github.com/sepandhaghighi/ghps/tarball/v0.2
6
+ Download-URL: https://github.com/sepandhaghighi/ghps/tarball/v0.3
7
7
  Author: Sepand Haghighi
8
8
  Author-email: me@sepand.tech
9
9
  License: MIT
@@ -101,13 +101,13 @@ Dynamic: summary
101
101
  ## Installation
102
102
 
103
103
  ### Source Code
104
- - Download [Version 0.2](https://github.com/sepandhaghighi/ghps/archive/v0.2.zip) or [Latest Source](https://github.com/sepandhaghighi/ghps/archive/dev.zip)
104
+ - Download [Version 0.3](https://github.com/sepandhaghighi/ghps/archive/v0.3.zip) or [Latest Source](https://github.com/sepandhaghighi/ghps/archive/dev.zip)
105
105
  - `pip install .`
106
106
 
107
107
  ### PyPI
108
108
 
109
109
  - Check [Python Packaging User Guide](https://packaging.python.org/installing/)
110
- - `pip install ghps==0.2`
110
+ - `pip install ghps==0.3`
111
111
 
112
112
 
113
113
  ## Usage
@@ -130,6 +130,9 @@ ghps --port=8080 --no-cache --no-threaded
130
130
  | `--no-strict` | Enable `.html` fallback| Strict mode enabled |
131
131
  | `--no-cache` | Disable HTTP caching headers | Cache enabled |
132
132
  | `--no-threaded` | Disable threaded server | Threaded enabled |
133
+ | `--auto-open` | Automatically open the server URL | Disable |
134
+
135
+ ℹ️ You can set `--port=0` to let the OS automatically select an available port
133
136
 
134
137
 
135
138
  ### Library
@@ -144,6 +147,7 @@ server = GHPageServer(
144
147
  strict=True,
145
148
  no_cache=False,
146
149
  threaded=True,
150
+ auto_open=True,
147
151
  )
148
152
 
149
153
  server.start()
@@ -159,6 +163,9 @@ server.start()
159
163
  | `strict` | `bool` | Enforce GitHub-like routing behavior | `True` |
160
164
  | `no_cache` | `bool` | Disable cache headers | `False` |
161
165
  | `threaded` | `bool` | Enable threaded request handling | `True` |
166
+ | `auto_open` | `bool` | Automatically open the server URL | `False` |
167
+
168
+ ℹ️ You can set `port=0` to let the OS automatically select an available port
162
169
 
163
170
  ## Issues & Bug Reports
164
171
 
@@ -209,6 +216,15 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
209
216
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
210
217
 
211
218
  ## [Unreleased]
219
+ ## [0.3] - 2026-04-05
220
+ ### Added
221
+ - `auto_open` parameter
222
+ - `--auto-open` CLI argument
223
+ - Random port support
224
+ ### Changed
225
+ - Test system modified
226
+ - CLI error messages updated
227
+ - `README.md` updated
212
228
  ## [0.2] - 2026-03-19
213
229
  ### Added
214
230
  - Logo
@@ -222,7 +238,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
222
238
  - Command line interface
223
239
  - Test system
224
240
 
225
- [Unreleased]: https://github.com/sepandhaghighi/ghps/compare/v0.2...dev
241
+ [Unreleased]: https://github.com/sepandhaghighi/ghps/compare/v0.3...dev
242
+ [0.3]: https://github.com/sepandhaghighi/ghps/compare/v0.2...v0.3
226
243
  [0.2]: https://github.com/sepandhaghighi/ghps/compare/v0.1...v0.2
227
244
  [0.1]: https://github.com/sepandhaghighi/ghps/compare/bc0a425...v0.1
228
245
 
@@ -50,13 +50,13 @@
50
50
  ## Installation
51
51
 
52
52
  ### Source Code
53
- - Download [Version 0.2](https://github.com/sepandhaghighi/ghps/archive/v0.2.zip) or [Latest Source](https://github.com/sepandhaghighi/ghps/archive/dev.zip)
53
+ - Download [Version 0.3](https://github.com/sepandhaghighi/ghps/archive/v0.3.zip) or [Latest Source](https://github.com/sepandhaghighi/ghps/archive/dev.zip)
54
54
  - `pip install .`
55
55
 
56
56
  ### PyPI
57
57
 
58
58
  - Check [Python Packaging User Guide](https://packaging.python.org/installing/)
59
- - `pip install ghps==0.2`
59
+ - `pip install ghps==0.3`
60
60
 
61
61
 
62
62
  ## Usage
@@ -79,6 +79,9 @@ ghps --port=8080 --no-cache --no-threaded
79
79
  | `--no-strict` | Enable `.html` fallback| Strict mode enabled |
80
80
  | `--no-cache` | Disable HTTP caching headers | Cache enabled |
81
81
  | `--no-threaded` | Disable threaded server | Threaded enabled |
82
+ | `--auto-open` | Automatically open the server URL | Disable |
83
+
84
+ ℹ️ You can set `--port=0` to let the OS automatically select an available port
82
85
 
83
86
 
84
87
  ### Library
@@ -93,6 +96,7 @@ server = GHPageServer(
93
96
  strict=True,
94
97
  no_cache=False,
95
98
  threaded=True,
99
+ auto_open=True,
96
100
  )
97
101
 
98
102
  server.start()
@@ -108,6 +112,9 @@ server.start()
108
112
  | `strict` | `bool` | Enforce GitHub-like routing behavior | `True` |
109
113
  | `no_cache` | `bool` | Disable cache headers | `False` |
110
114
  | `threaded` | `bool` | Enable threaded request handling | `True` |
115
+ | `auto_open` | `bool` | Automatically open the server URL | `False` |
116
+
117
+ ℹ️ You can set `port=0` to let the OS automatically select an available port
111
118
 
112
119
  ## Issues & Bug Reports
113
120
 
@@ -4,8 +4,8 @@
4
4
 
5
5
  | Version | Supported |
6
6
  | ------------- | ------------------ |
7
- | 0.2 | :white_check_mark: |
8
- | < 0.2 | :x: |
7
+ | 0.3 | :white_check_mark: |
8
+ | < 0.3 | :x: |
9
9
 
10
10
  ## Reporting a Vulnerability
11
11
 
@@ -7,6 +7,16 @@ from pathlib import Path
7
7
  from .params import GHPS_VERSION
8
8
  from .server import GHPageServer
9
9
 
10
+ def _print_cli_error(message: str, exit_code: int = 1) -> None:
11
+ """
12
+ Print a formatted CLI error message and exit.
13
+
14
+ :param message: Error message to display.
15
+ :param exit_code: Exit status code (default: 1).
16
+ """
17
+ print(f"[GHPS ERROR] {message}", file=sys.stderr)
18
+ sys.exit(exit_code)
19
+
10
20
 
11
21
  def _parse_args() -> argparse.Namespace:
12
22
  """Parse arguments."""
@@ -57,29 +67,34 @@ def _parse_args() -> argparse.Namespace:
57
67
  help="Disable threaded server"
58
68
  )
59
69
 
70
+ parser.add_argument(
71
+ "--auto-open",
72
+ action="store_true",
73
+ help="Automatically open the server URL"
74
+ )
75
+
60
76
  args = parser.parse_args()
61
77
  return args
62
78
 
63
79
 
64
80
  def main() -> None:
65
81
  """CLI main function."""
66
- args = _parse_args()
67
-
68
- if args.version:
69
- print(GHPS_VERSION)
70
- else:
71
- directory = Path(args.directory).resolve()
72
-
73
- if not directory.exists():
74
- print("Error: Directory does not exist.")
75
- sys.exit(1)
76
-
77
- server = GHPageServer(
78
- directory=str(directory),
79
- port=args.port,
80
- base_path=args.base_path,
81
- strict=not args.no_strict,
82
- no_cache=args.no_cache,
83
- threaded=not args.no_threaded,
84
- )
85
- server.start()
82
+ try:
83
+ args = _parse_args()
84
+ if args.version:
85
+ print(GHPS_VERSION)
86
+ else:
87
+ server = GHPageServer(
88
+ directory=args.directory,
89
+ port=args.port,
90
+ base_path=args.base_path,
91
+ strict=not args.no_strict,
92
+ no_cache=args.no_cache,
93
+ threaded=not args.no_threaded,
94
+ auto_open=args.auto_open,
95
+ )
96
+ server.start()
97
+ except ValueError as e:
98
+ _print_cli_error(str(e))
99
+ except Exception as e:
100
+ _print_cli_error(f"Unexpected error: {e}")
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """ghps params."""
3
3
 
4
- GHPS_VERSION = "0.2"
4
+ GHPS_VERSION = "0.3"
5
5
 
6
6
  INVALID_DIRECTORY_TYPE_ERROR = "`directory` must be str or pathlib.Path."
7
7
  DIRECTORY_NOT_FOUND_ERROR = "`directory` does not exist."
@@ -16,3 +16,4 @@ INVALID_BASE_PATH_FORMAT_ERROR = "`base_path` must start with '/' or be empty."
16
16
  INVALID_STRICT_TYPE_ERROR = "`strict` must be bool."
17
17
  INVALID_NO_CACHE_TYPE_ERROR = "`no_cache` must be bool."
18
18
  INVALID_THREADED_TYPE_ERROR = "`threaded` must be bool."
19
+ INVALID_AUTO_OPEN_TYPE_ERROR = "`auto_open` must be bool."
@@ -3,6 +3,7 @@
3
3
 
4
4
  import http.server
5
5
  import socketserver
6
+ import webbrowser
6
7
  from typing import Optional, Any
7
8
  from pathlib import Path
8
9
  from urllib.parse import unquote
@@ -17,6 +18,7 @@ from .params import (
17
18
  INVALID_STRICT_TYPE_ERROR,
18
19
  INVALID_NO_CACHE_TYPE_ERROR,
19
20
  INVALID_THREADED_TYPE_ERROR,
21
+ INVALID_AUTO_OPEN_TYPE_ERROR
20
22
  )
21
23
 
22
24
 
@@ -27,6 +29,7 @@ def _validate_inputs(
27
29
  strict: Any,
28
30
  no_cache: Any,
29
31
  threaded: Any,
32
+ auto_open: Any,
30
33
  ):
31
34
  """
32
35
  Validate GHPageServer inputs.
@@ -37,6 +40,7 @@ def _validate_inputs(
37
40
  :param strict: If False, enables automatic ".html" resolution.
38
41
  :param no_cache: If True, disables client-side caching.
39
42
  :param threaded: If True, handles requests using threads.
43
+ :param auto_open: If True, automatically opens the server URL in the default web browser.
40
44
  """
41
45
  if not isinstance(directory, (str, Path)):
42
46
  raise ValueError(INVALID_DIRECTORY_TYPE_ERROR)
@@ -51,7 +55,7 @@ def _validate_inputs(
51
55
  if not isinstance(port, int):
52
56
  raise ValueError(INVALID_PORT_TYPE_ERROR)
53
57
 
54
- if not (1 <= port <= 65535):
58
+ if not (0 <= port <= 65535):
55
59
  raise ValueError(INVALID_PORT_RANGE_ERROR)
56
60
 
57
61
  if not isinstance(base_path, str):
@@ -69,6 +73,9 @@ def _validate_inputs(
69
73
  if not isinstance(threaded, bool):
70
74
  raise ValueError(INVALID_THREADED_TYPE_ERROR)
71
75
 
76
+ if not isinstance(auto_open, bool):
77
+ raise ValueError(INVALID_AUTO_OPEN_TYPE_ERROR)
78
+
72
79
 
73
80
  class _GHRequestHandler(http.server.SimpleHTTPRequestHandler):
74
81
  """Custom HTTP request handler for serving static files with optional base path stripping, strict routing, custom 404 page support, and cache control headers."""
@@ -178,6 +185,7 @@ class GHPageServer:
178
185
  strict: bool = True,
179
186
  no_cache: bool = False,
180
187
  threaded: bool = True,
188
+ auto_open: bool = False,
181
189
  ):
182
190
  """
183
191
  Initialize the server.
@@ -188,6 +196,7 @@ class GHPageServer:
188
196
  :param strict: If False, enables automatic ".html" resolution.
189
197
  :param no_cache: If True, disables client-side caching.
190
198
  :param threaded: If True, handles requests using threads.
199
+ :param auto_open: If True, automatically opens the server URL in the default web browser.
191
200
  """
192
201
  _validate_inputs(
193
202
  directory=directory,
@@ -196,6 +205,7 @@ class GHPageServer:
196
205
  strict=strict,
197
206
  no_cache=no_cache,
198
207
  threaded=threaded,
208
+ auto_open=auto_open,
199
209
  )
200
210
  self._directory = str(Path(directory).resolve())
201
211
  self._port = port
@@ -203,6 +213,7 @@ class GHPageServer:
203
213
  self._strict = strict
204
214
  self._no_cache = no_cache
205
215
  self._threaded = threaded
216
+ self._auto_open = auto_open
206
217
  self._httpd = None
207
218
 
208
219
  def start(self) -> None:
@@ -223,12 +234,18 @@ class GHPageServer:
223
234
  server_cls = _ThreadedTCPServer if self._threaded else socketserver.TCPServer
224
235
 
225
236
  self._httpd = server_cls(("", self._port), handler)
226
-
227
- print(f"Serving at http://localhost:{self._port}{self._base_path}")
237
+ self._port = self._httpd.server_address[1]
238
+ url = f"http://localhost:{self._port}{self._base_path}"
239
+ print(f"Serving at {url}")
228
240
  print(f"Directory: {self._directory}")
229
241
  print(f"Strict mode: {'ON' if self._strict else 'OFF'}")
230
242
  print(f"Cache disabled: {'YES' if self._no_cache else 'NO'}")
231
243
 
244
+ if self._auto_open:
245
+ try:
246
+ webbrowser.open(url)
247
+ except Exception:
248
+ print("[GHPS ERROR]: Failed to open browser automatically")
232
249
  try:
233
250
  self._httpd.serve_forever()
234
251
  except KeyboardInterrupt:
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ghps
3
- Version: 0.2
3
+ Version: 0.3
4
4
  Summary: Ghps: A Minimal GitHub Pages Simulator for Local Development
5
5
  Home-page: https://github.com/sepandhaghighi/ghps
6
- Download-URL: https://github.com/sepandhaghighi/ghps/tarball/v0.2
6
+ Download-URL: https://github.com/sepandhaghighi/ghps/tarball/v0.3
7
7
  Author: Sepand Haghighi
8
8
  Author-email: me@sepand.tech
9
9
  License: MIT
@@ -101,13 +101,13 @@ Dynamic: summary
101
101
  ## Installation
102
102
 
103
103
  ### Source Code
104
- - Download [Version 0.2](https://github.com/sepandhaghighi/ghps/archive/v0.2.zip) or [Latest Source](https://github.com/sepandhaghighi/ghps/archive/dev.zip)
104
+ - Download [Version 0.3](https://github.com/sepandhaghighi/ghps/archive/v0.3.zip) or [Latest Source](https://github.com/sepandhaghighi/ghps/archive/dev.zip)
105
105
  - `pip install .`
106
106
 
107
107
  ### PyPI
108
108
 
109
109
  - Check [Python Packaging User Guide](https://packaging.python.org/installing/)
110
- - `pip install ghps==0.2`
110
+ - `pip install ghps==0.3`
111
111
 
112
112
 
113
113
  ## Usage
@@ -130,6 +130,9 @@ ghps --port=8080 --no-cache --no-threaded
130
130
  | `--no-strict` | Enable `.html` fallback| Strict mode enabled |
131
131
  | `--no-cache` | Disable HTTP caching headers | Cache enabled |
132
132
  | `--no-threaded` | Disable threaded server | Threaded enabled |
133
+ | `--auto-open` | Automatically open the server URL | Disable |
134
+
135
+ ℹ️ You can set `--port=0` to let the OS automatically select an available port
133
136
 
134
137
 
135
138
  ### Library
@@ -144,6 +147,7 @@ server = GHPageServer(
144
147
  strict=True,
145
148
  no_cache=False,
146
149
  threaded=True,
150
+ auto_open=True,
147
151
  )
148
152
 
149
153
  server.start()
@@ -159,6 +163,9 @@ server.start()
159
163
  | `strict` | `bool` | Enforce GitHub-like routing behavior | `True` |
160
164
  | `no_cache` | `bool` | Disable cache headers | `False` |
161
165
  | `threaded` | `bool` | Enable threaded request handling | `True` |
166
+ | `auto_open` | `bool` | Automatically open the server URL | `False` |
167
+
168
+ ℹ️ You can set `port=0` to let the OS automatically select an available port
162
169
 
163
170
  ## Issues & Bug Reports
164
171
 
@@ -209,6 +216,15 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
209
216
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
210
217
 
211
218
  ## [Unreleased]
219
+ ## [0.3] - 2026-04-05
220
+ ### Added
221
+ - `auto_open` parameter
222
+ - `--auto-open` CLI argument
223
+ - Random port support
224
+ ### Changed
225
+ - Test system modified
226
+ - CLI error messages updated
227
+ - `README.md` updated
212
228
  ## [0.2] - 2026-03-19
213
229
  ### Added
214
230
  - Logo
@@ -222,7 +238,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
222
238
  - Command line interface
223
239
  - Test system
224
240
 
225
- [Unreleased]: https://github.com/sepandhaghighi/ghps/compare/v0.2...dev
241
+ [Unreleased]: https://github.com/sepandhaghighi/ghps/compare/v0.3...dev
242
+ [0.3]: https://github.com/sepandhaghighi/ghps/compare/v0.2...v0.3
226
243
  [0.2]: https://github.com/sepandhaghighi/ghps/compare/v0.1...v0.2
227
244
  [0.1]: https://github.com/sepandhaghighi/ghps/compare/bc0a425...v0.1
228
245
 
@@ -32,7 +32,7 @@ def read_description() -> str:
32
32
  setup(
33
33
  name='ghps',
34
34
  packages=['ghps'],
35
- version='0.2',
35
+ version='0.3',
36
36
  description='Ghps: A Minimal GitHub Pages Simulator for Local Development',
37
37
  long_description=read_description(),
38
38
  long_description_content_type='text/markdown',
@@ -40,7 +40,7 @@ setup(
40
40
  author='Sepand Haghighi',
41
41
  author_email='me@sepand.tech',
42
42
  url='https://github.com/sepandhaghighi/ghps',
43
- download_url='https://github.com/sepandhaghighi/ghps/tarball/v0.2',
43
+ download_url='https://github.com/sepandhaghighi/ghps/tarball/v0.3',
44
44
  keywords="github gh-pages static-server static-hosting development server local http simulator testing cli python",
45
45
  project_urls={
46
46
  'Source': 'https://github.com/sepandhaghighi/ghps'
@@ -110,3 +110,17 @@ def test_cli_invalid_directory(monkeypatch):
110
110
 
111
111
  with pytest.raises(SystemExit):
112
112
  ghps.cli.main()
113
+
114
+
115
+ @patch("ghps.cli.GHPageServer")
116
+ @patch("sys.stderr")
117
+ def test_cli_unexpected_error(mock_stderr, mock_server_cls):
118
+ mock_server = mock_server_cls.return_value
119
+ mock_server.start.side_effect = Exception("boom")
120
+ test_args = ["ghps"]
121
+ with patch("sys.argv", test_args):
122
+ with pytest.raises(SystemExit) as exc:
123
+ ghps.cli.main()
124
+ assert exc.value.code == 1
125
+ written = "".join(call.args[0] for call in mock_stderr.write.call_args_list)
126
+ assert "[GHPS ERROR] Unexpected error: boom" in written
@@ -1,5 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  import pytest
3
+ from unittest.mock import patch
3
4
  from ghps import GHPageServer
4
5
 
5
6
 
@@ -124,3 +125,36 @@ def test_invalid_threaded_type(tmp_path):
124
125
  no_cache=False,
125
126
  threaded="true",
126
127
  )
128
+
129
+
130
+ def test_invalid_auto_open_type(tmp_path):
131
+ with pytest.raises(ValueError, match="`auto_open` must be bool."):
132
+ GHPageServer(
133
+ directory=tmp_path,
134
+ port=8000,
135
+ base_path="",
136
+ strict=True,
137
+ no_cache=False,
138
+ threaded=True,
139
+ auto_open="true",
140
+ )
141
+
142
+
143
+ @patch("ghps.server.webbrowser.open", side_effect=Exception("boom"))
144
+ @patch("ghps.server._ThreadedTCPServer")
145
+ @patch("builtins.print")
146
+ def test_auto_open_failure_logs_error(mock_print, mock_server_cls, mock_web_open, tmp_path):
147
+ mock_server = mock_server_cls.return_value
148
+ mock_server.server_address = ("127.0.0.1", 8000)
149
+ mock_server.serve_forever.side_effect = KeyboardInterrupt
150
+ server = GHPageServer(
151
+ directory=tmp_path,
152
+ port=8000,
153
+ auto_open=True,
154
+ )
155
+ server.start()
156
+ mock_web_open.assert_called_once_with("http://localhost:8000")
157
+ assert any(
158
+ "[GHPS ERROR]: Failed to open browser automatically" in str(call)
159
+ for call in mock_print.call_args_list
160
+ )
@@ -128,3 +128,52 @@ def test_keyboard_interrupt(capsys):
128
128
 
129
129
  captured = capsys.readouterr()
130
130
  assert "Server stopped." in captured.out
131
+
132
+
133
+ @patch("ghps.server.webbrowser.open")
134
+ @patch("ghps.server._ThreadedTCPServer")
135
+ def test_auto_open_enabled(mock_server_cls, mock_web_open, tmp_path):
136
+ mock_server = mock_server_cls.return_value
137
+ mock_server.server_address = ("127.0.0.1", 8000)
138
+ mock_server.serve_forever.side_effect = KeyboardInterrupt
139
+
140
+ server = GHPageServer(
141
+ directory=tmp_path,
142
+ port=8000,
143
+ auto_open=True,
144
+ )
145
+
146
+ server.start()
147
+
148
+ mock_web_open.assert_called_once_with("http://localhost:8000")
149
+
150
+
151
+ @patch("ghps.server.webbrowser.open")
152
+ @patch("ghps.server._ThreadedTCPServer")
153
+ def test_auto_open_disabled(mock_server_cls, mock_web_open, tmp_path):
154
+ mock_server = mock_server_cls.return_value
155
+ mock_server.server_address = ("127.0.0.1", 8000)
156
+ mock_server.serve_forever.side_effect = KeyboardInterrupt
157
+
158
+ server = GHPageServer(
159
+ directory=tmp_path,
160
+ port=8000,
161
+ auto_open=False,
162
+ )
163
+
164
+ server.start()
165
+
166
+ mock_web_open.assert_not_called()
167
+
168
+
169
+ @patch("ghps.server._ThreadedTCPServer")
170
+ def test_random_port_resolution(mock_server_cls, tmp_path):
171
+ mock_server = mock_server_cls.return_value
172
+ mock_server.server_address = ("127.0.0.1", 54321)
173
+ mock_server.serve_forever.side_effect = KeyboardInterrupt
174
+ server = GHPageServer(
175
+ directory=tmp_path,
176
+ port=0,
177
+ )
178
+ server.start()
179
+ assert server._port == 54321
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