diff options
| -rw-r--r-- | CHANGES.txt | 8 | ||||
| -rw-r--r-- | pyramid/scripts/pserve.py | 74 | ||||
| -rw-r--r-- | pyramid/tests/test_scripts/test_pserve.py | 30 |
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 |
