|
@@ -21,7 +21,7 @@ import time
|
|
import typing as t
|
|
import typing as t
|
|
import webbrowser
|
|
import webbrowser
|
|
from importlib import util
|
|
from importlib import util
|
|
-from random import randint
|
|
|
|
|
|
+from random import choices, randint
|
|
|
|
|
|
from flask import Blueprint, Flask, json, jsonify, render_template, request, send_from_directory
|
|
from flask import Blueprint, Flask, json, jsonify, render_template, request, send_from_directory
|
|
from flask_cors import CORS
|
|
from flask_cors import CORS
|
|
@@ -258,7 +258,7 @@ class _Server:
|
|
if self._get_async_mode() == "gevent" and util.find_spec("gevent"):
|
|
if self._get_async_mode() == "gevent" and util.find_spec("gevent"):
|
|
from gevent import get_hub, monkey
|
|
from gevent import get_hub, monkey
|
|
|
|
|
|
- get_hub().NOT_ERROR += (KeyboardInterrupt, )
|
|
|
|
|
|
+ get_hub().NOT_ERROR += (KeyboardInterrupt,)
|
|
if not monkey.is_module_patched("time"):
|
|
if not monkey.is_module_patched("time"):
|
|
monkey.patch_time()
|
|
monkey.patch_time()
|
|
if self._get_async_mode() == "eventlet" and util.find_spec("eventlet"):
|
|
if self._get_async_mode() == "eventlet" and util.find_spec("eventlet"):
|
|
@@ -267,17 +267,35 @@ class _Server:
|
|
if not patcher.is_monkey_patched("time"):
|
|
if not patcher.is_monkey_patched("time"):
|
|
monkey_patch(time=True)
|
|
monkey_patch(time=True)
|
|
|
|
|
|
- def _get_random_port(self): # pragma: no cover
|
|
|
|
|
|
+ def _get_random_port(
|
|
|
|
+ self, port_auto_ranges: t.Optional[t.List[t.Union[int, t.Tuple[int, int]]]] = None
|
|
|
|
+ ): # pragma: no cover
|
|
|
|
+ port_auto_ranges = port_auto_ranges or [(49152, 65535)]
|
|
|
|
+ random_weights = [1 if isinstance(r, int) else abs(r[1] - r[0]) + 1 for r in port_auto_ranges]
|
|
while True:
|
|
while True:
|
|
- port = randint(49152, 65535)
|
|
|
|
|
|
+ random_choices = [
|
|
|
|
+ r if isinstance(r, int) else randint(min(r[0], r[1]), max(r[0], r[1])) for r in port_auto_ranges
|
|
|
|
+ ]
|
|
|
|
+ port = choices(random_choices, weights=random_weights)[0]
|
|
if port not in _RuntimeManager().get_used_port() and not _is_port_open(self._host, port):
|
|
if port not in _RuntimeManager().get_used_port() and not _is_port_open(self._host, port):
|
|
return port
|
|
return port
|
|
|
|
|
|
- def run(self, host, port, debug, use_reloader, flask_log, run_in_thread, allow_unsafe_werkzeug, notebook_proxy):
|
|
|
|
|
|
+ def run(
|
|
|
|
+ self,
|
|
|
|
+ host,
|
|
|
|
+ port,
|
|
|
|
+ debug,
|
|
|
|
+ use_reloader,
|
|
|
|
+ flask_log,
|
|
|
|
+ run_in_thread,
|
|
|
|
+ allow_unsafe_werkzeug,
|
|
|
|
+ notebook_proxy,
|
|
|
|
+ port_auto_ranges,
|
|
|
|
+ ):
|
|
host_value = host if host != "0.0.0.0" else "localhost"
|
|
host_value = host if host != "0.0.0.0" else "localhost"
|
|
self._host = host
|
|
self._host = host
|
|
if port == "auto":
|
|
if port == "auto":
|
|
- port = self._get_random_port()
|
|
|
|
|
|
+ port = self._get_random_port(port_auto_ranges)
|
|
self._port = port
|
|
self._port = port
|
|
if _is_in_notebook() and notebook_proxy: # pragma: no cover
|
|
if _is_in_notebook() and notebook_proxy: # pragma: no cover
|
|
from .utils.proxy import NotebookProxy
|
|
from .utils.proxy import NotebookProxy
|