Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pserve open_url config setting #2984

Merged
merged 3 commits into from
Mar 29, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
---------

Expand Down
74 changes: 55 additions & 19 deletions pyramid/scripts/pserve.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@
loadapp,
loadserver,
)
from paste.deploy.loadwsgi import (
SERVER,
loadcontext,
)

from pyramid.compat import PY2
from pyramid.compat import configparser
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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):
Expand All @@ -127,7 +127,7 @@ def __init__(self, argv, quiet=False):
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:
Expand Down Expand Up @@ -161,7 +161,32 @@ def pserve_file_config(self, filename, global_conf=None):
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:
Expand All @@ -188,16 +213,27 @@ def run(self): # pragma: no cover

# 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:
Expand All @@ -213,11 +249,11 @@ def open_browser():
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)
Expand Down
30 changes: 28 additions & 2 deletions pyramid/tests/test_scripts/test_pserve.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,37 @@ def test_config_file_finds_watch_files(self):
'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
Expand Down