summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.txt8
-rw-r--r--pyramid/scripts/pserve.py74
-rw-r--r--pyramid/tests/test_scripts/test_pserve.py30
3 files changed, 91 insertions, 21 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 9056320c5..7676a69f9 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -10,6 +10,14 @@ Features
request that the policy may create more than one request for retry
purposes. See https://github.com/Pylons/pyramid/pull/2964
+- Support an ``open_url`` config setting in the ``pserve`` section of the
+ config file. This url is used to open a web browser when ``pserve --browser``
+ is invoked. When this setting is unavailable the ``pserve`` script will
+ attempt to guess the port the server is using from the
+ ``server:<server_name>`` section of the config file but there is no
+ requirement that the server is being run in this format so it may fail.
+ See https://github.com/Pylons/pyramid/pull/2984
+
Bug Fixes
---------
diff --git a/pyramid/scripts/pserve.py b/pyramid/scripts/pserve.py
index b89f9b982..c469dde04 100644
--- a/pyramid/scripts/pserve.py
+++ b/pyramid/scripts/pserve.py
@@ -22,10 +22,6 @@ from paste.deploy import (
loadapp,
loadserver,
)
-from paste.deploy.loadwsgi import (
- SERVER,
- loadcontext,
-)
from pyramid.compat import PY2
from pyramid.compat import configparser
@@ -87,7 +83,9 @@ class PServeCommand(object):
'-b', '--browser',
dest='browser',
action='store_true',
- help="Open a web browser to server url")
+ help=("Open a web browser to the server url. The server url is "
+ "determined from the 'open_url' setting in the 'pserve' "
+ "section of the configuration file."))
parser.add_argument(
'-v', '--verbose',
default=default_verbosity,
@@ -119,6 +117,8 @@ class PServeCommand(object):
loadapp = staticmethod(loadapp) # testing
loadserver = staticmethod(loadserver) # testing
+ open_url = None
+
_scheme_re = re.compile(r'^[a-z][a-z]+:', re.I)
def __init__(self, argv, quiet=False):
@@ -127,7 +127,7 @@ class PServeCommand(object):
self.args.verbose = 0
if self.args.reload:
self.worker_kwargs = {'argv': argv, "quiet": quiet}
- self.watch_files = []
+ self.watch_files = set()
def out(self, msg): # pragma: no cover
if self.args.verbose > 0:
@@ -161,7 +161,32 @@ class PServeCommand(object):
file = resolver.resolve(file).abspath()
elif not os.path.isabs(file):
file = os.path.join(here, file)
- self.watch_files.append(os.path.abspath(file))
+ self.watch_files.add(os.path.abspath(file))
+
+ # attempt to determine the url of the server
+ open_url = items.get('open_url')
+ if open_url:
+ self.open_url = open_url
+
+ def _guess_server_url(self, filename, server_name,
+ global_conf=None): # pragma: no cover
+ server_name = server_name or 'main'
+ here = os.path.abspath(os.path.dirname(filename))
+ defaults = {}
+ if global_conf:
+ defaults.update(global_conf)
+ defaults['here'] = here
+
+ config = self.ConfigParser(defaults=defaults)
+ config.optionxform = str
+ config.read(filename)
+ try:
+ items = dict(config.items('server:' + server_name))
+ except configparser.NoSectionError:
+ return
+
+ if 'port' in items:
+ return 'http://127.0.0.1:{port}'.format(**items)
def run(self): # pragma: no cover
if not self.args.config_uri:
@@ -188,16 +213,27 @@ class PServeCommand(object):
# do not open the browser on each reload so check hupper first
if self.args.browser and not hupper.is_active():
- def open_browser():
- context = loadcontext(
- SERVER, app_spec, name=server_name, relative_to=base,
- global_conf=vars)
- url = 'http://127.0.0.1:{port}/'.format(**context.config())
- time.sleep(1)
- webbrowser.open(url)
- t = threading.Thread(target=open_browser)
- t.setDaemon(True)
- t.start()
+ self.pserve_file_config(config_path, global_conf=vars)
+ url = self.open_url
+
+ # do not guess the url if the server is sourced from a different
+ # location than the config_path
+ if not url and server_spec == app_spec:
+ url = self._guess_server_url(config_path, server_name, vars)
+
+ if not url:
+ self.out('WARNING: could not determine the server\'s url to '
+ 'open the browser. To fix this set the "open_url" '
+ 'setting in the [pserve] section of the '
+ 'configuration file.')
+
+ else:
+ def open_browser():
+ time.sleep(1)
+ webbrowser.open(url)
+ t = threading.Thread(target=open_browser)
+ t.setDaemon(True)
+ t.start()
if self.args.reload and not hupper.is_active():
if self.args.verbose > 1:
@@ -213,11 +249,11 @@ class PServeCommand(object):
if config_path:
setup_logging(config_path, global_conf=vars)
self.pserve_file_config(config_path, global_conf=vars)
- self.watch_files.append(config_path)
+ self.watch_files.add(config_path)
if hupper.is_active():
reloader = hupper.get_reloader()
- reloader.watch_files(self.watch_files)
+ reloader.watch_files(list(self.watch_files))
server = self.loadserver(
server_spec, name=server_name, relative_to=base, global_conf=vars)
diff --git a/pyramid/tests/test_scripts/test_pserve.py b/pyramid/tests/test_scripts/test_pserve.py
index 8eb63b8d6..d5578b3ea 100644
--- a/pyramid/tests/test_scripts/test_pserve.py
+++ b/pyramid/tests/test_scripts/test_pserve.py
@@ -74,11 +74,37 @@ class TestPServeCommand(unittest.TestCase):
'a': '1',
'here': os.path.abspath('/base'),
})
- self.assertEqual(inst.watch_files, [
+ self.assertEqual(inst.watch_files, set([
os.path.abspath('/base/foo'),
os.path.abspath('/baz'),
os.path.abspath(os.path.join(here, '*.py')),
- ])
+ ]))
+
+ def test_config_file_finds_open_url(self):
+ inst = self._makeOne('development.ini')
+ self.config_factory.items = [(
+ 'open_url', 'http://127.0.0.1:8080/',
+ )]
+ inst.pserve_file_config('/base/path.ini', global_conf={'a': '1'})
+ self.assertEqual(self.config_factory.defaults, {
+ 'a': '1',
+ 'here': os.path.abspath('/base'),
+ })
+ self.assertEqual(inst.open_url, 'http://127.0.0.1:8080/')
+
+ def test__guess_server_url(self):
+ inst = self._makeOne('development.ini')
+ self.config_factory.items = [(
+ 'port', '8080',
+ )]
+ url = inst._guess_server_url(
+ '/base/path.ini', 'main', global_conf={'a': '1'})
+ self.assertEqual(self.config_factory.defaults, {
+ 'a': '1',
+ 'here': os.path.abspath('/base'),
+ })
+ self.assertEqual(self.config_factory.parser.section, 'server:main')
+ self.assertEqual(url, 'http://127.0.0.1:8080')
def test_reload_call_hupper_with_correct_args(self):
from pyramid.scripts import pserve