From 662ad5a4c77ad37fd096ac80921b06a544fef2bb Mon Sep 17 00:00:00 2001 From: zrayn Date: Thu, 2 Jun 2016 15:21:56 -0700 Subject: Ripping daemonization out of pserve --- CONTRIBUTORS.txt | 2 + pyramid/scripts/pserve.py | 342 +----------------------------- pyramid/tests/test_scripts/test_pserve.py | 195 ----------------- 3 files changed, 4 insertions(+), 535 deletions(-) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 762793d0b..7b6473e97 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -270,3 +270,5 @@ Contributors - Vincent Férotin, 2016/05/08 - Berker Peksag, 2016/05/16 + +- Zack Brunson, 2016/06/02 diff --git a/pyramid/scripts/pserve.py b/pyramid/scripts/pserve.py index 74bda1dce..9c9be2d38 100644 --- a/pyramid/scripts/pserve.py +++ b/pyramid/scripts/pserve.py @@ -10,8 +10,6 @@ import atexit import ctypes -import errno -import logging import optparse import os import py_compile @@ -59,20 +57,13 @@ def main(argv=sys.argv, quiet=False): command = PServeCommand(argv, quiet=quiet) return command.run() -class DaemonizeException(Exception): - pass - class PServeCommand(object): - usage = '%prog config_uri [start|stop|restart|status] [var=value]' + usage = '%prog config_uri [var=value]' description = """\ This command serves a web application that uses a PasteDeploy configuration file for the server and application. - If start/stop/restart is given, then --daemon is implied, and it will - start (normal operation), stop (--stop-daemon), or do both. - Note: Daemonization features are deprecated. - You can also include variable assignments like 'http_port=8080' and then use %(http_port)s in your config files. """ @@ -98,23 +89,6 @@ class PServeCommand(object): metavar='SECTION_NAME', help=("Use the named server as defined in the configuration file " "(default: main)")) - if hasattr(os, 'fork'): - parser.add_option( - '--daemon', - dest="daemon", - action="store_true", - help="Run in daemon (background) mode [DEPRECATED]") - parser.add_option( - '--pid-file', - dest='pid_file', - metavar='FILENAME', - help=("Save PID to file (default to pyramid.pid if running in " - "daemon mode) [DEPRECATED]")) - parser.add_option( - '--log-file', - dest='log_file', - metavar='LOG_FILE', - help="Save output to the given log file (redirects stdout) [DEPRECATED]") parser.add_option( '--reload', dest='reload', @@ -126,22 +100,11 @@ class PServeCommand(object): default=1, help=("Seconds between checking files (low number can cause " "significant CPU usage)")) - parser.add_option( - '--monitor-restart', - dest='monitor_restart', - action='store_true', - help="Auto-restart server if it dies [DEPRECATED]") parser.add_option( '-b', '--browser', dest='browser', action='store_true', help="Open a web browser to server url") - parser.add_option( - '--status', - action='store_true', - dest='show_status', - help=("Show the status of the (presumably daemonized) server " - "[DEPRECATED]")) parser.add_option( '-v', '--verbose', default=default_verbosity, @@ -168,20 +131,11 @@ class PServeCommand(object): metavar="GROUP", help="Set the group (usually only possible when run as root)") - parser.add_option( - '--stop-daemon', - dest='stop_daemon', - action='store_true', - help=('Stop a daemonized server (given a PID file, or default ' - 'pyramid.pid file) [DEPRECATED]')) - _scheme_re = re.compile(r'^[a-z][a-z]+:', re.I) _reloader_environ_key = 'PYTHON_RELOADER_SHOULD_RUN' _monitor_environ_key = 'PASTE_MONITOR_SHOULD_RUN' - possible_subcommands = ('start', 'stop', 'restart', 'status') - def __init__(self, argv, quiet=False): self.options, self.args = self.parser.parse_args(argv[1:]) if quiet: @@ -192,21 +146,10 @@ class PServeCommand(object): print(msg) def get_options(self): - if ( - len(self.args) > 1 and - self.args[1] in self.possible_subcommands - ): - restvars = self.args[2:] - else: - restvars = self.args[1:] - + restvars = self.args[1:] return parse_vars(restvars) def run(self): # pragma: no cover - if self.options.stop_daemon: - self._warn_daemon_deprecated() - return self.stop_daemon() - if not hasattr(self.options, 'set_user'): # Windows case: self.options.set_user = self.options.set_group = None @@ -221,22 +164,7 @@ class PServeCommand(object): return 2 app_spec = self.args[0] - if ( - len(self.args) > 1 and - self.args[1] in self.possible_subcommands - ): - cmd = self.args[1] - else: - cmd = None - if self.options.reload: - if ( - getattr(self.options, 'daemon', False) or - cmd in ('start', 'stop', 'restart') - ): - self.out( - 'Error: Cannot use reloading while running as a dameon.') - return 2 if os.environ.get(self._reloader_environ_key): if self.options.verbose > 1: self.out('Running reloading file monitor') @@ -246,31 +174,6 @@ class PServeCommand(object): else: return self.restart_with_reloader() - if cmd not in (None, 'start', 'stop', 'restart', 'status'): - self.out( - 'Error: must give start|stop|restart (not %s)' % cmd) - return 2 - - if cmd == 'status' or self.options.show_status: - self._warn_daemon_deprecated() - return self.show_status() - - if cmd in ('restart', 'stop'): - self._warn_daemon_deprecated() - result = self.stop_daemon() - if result: - if cmd == 'restart': - self.out("Could not stop daemon; aborting") - else: - self.out("Could not stop daemon") - return result - if cmd == 'stop': - return result - self.options.daemon = True - - if cmd == 'start': - self.options.daemon = True - app_name = self.options.app_name vars = self.get_options() @@ -286,75 +189,6 @@ class PServeCommand(object): server_spec = app_spec base = os.getcwd() - # warn before setting a default - if self.options.pid_file or self.options.log_file: - self._warn_daemon_deprecated() - - if getattr(self.options, 'daemon', False): - if not self.options.pid_file: - self.options.pid_file = 'pyramid.pid' - if not self.options.log_file: - self.options.log_file = 'pyramid.log' - - # Ensure the log file is writeable - if self.options.log_file: - try: - writeable_log_file = open(self.options.log_file, 'a') - except IOError as ioe: - msg = 'Error: Unable to write to log file: %s' % ioe - raise ValueError(msg) - writeable_log_file.close() - - # Ensure the pid file is writeable - if self.options.pid_file: - try: - writeable_pid_file = open(self.options.pid_file, 'a') - except IOError as ioe: - msg = 'Error: Unable to write to pid file: %s' % ioe - raise ValueError(msg) - writeable_pid_file.close() - - # warn before forking - if ( - self.options.monitor_restart and - not os.environ.get(self._monitor_environ_key) - ): - self.out('''\ ---monitor-restart has been deprecated in Pyramid 1.6. It will be removed -in a future release per Pyramid's deprecation policy. Please consider using -a real process manager for your processes like Systemd, Circus, or Supervisor. -''') - - if ( - getattr(self.options, 'daemon', False) and - not os.environ.get(self._monitor_environ_key) - ): - self._warn_daemon_deprecated() - try: - self.daemonize() - except DaemonizeException as ex: - if self.options.verbose > 0: - self.out(str(ex)) - return 2 - - if ( - not os.environ.get(self._monitor_environ_key) and - self.options.pid_file - ): - self.record_pid(self.options.pid_file) - - if ( - self.options.monitor_restart and - not os.environ.get(self._monitor_environ_key) - ): - return self.restart_with_monitor() - - if self.options.log_file: - stdout_log = LazyWriter(self.options.log_file, 'a') - sys.stdout = stdout_log - sys.stderr = stdout_log - logging.basicConfig(stream=stdout_log) - log_fn = app_spec if log_fn.startswith('config:'): log_fn = app_spec[len('config:'):] @@ -442,141 +276,6 @@ a real process manager for your processes like Systemd, Circus, or Supervisor. name += '.exe' return name - def daemonize(self): # pragma: no cover - pid = live_pidfile(self.options.pid_file) - if pid: - raise DaemonizeException( - "Daemon is already running (PID: %s from PID file %s)" - % (pid, self.options.pid_file)) - - if self.options.verbose > 0: - self.out('Entering daemon mode') - pid = os.fork() - if pid: - # The forked process also has a handle on resources, so we - # *don't* want proper termination of the process, we just - # want to exit quick (which os._exit() does) - os._exit(0) - # Make this the session leader - os.setsid() - # Fork again for good measure! - pid = os.fork() - if pid: - os._exit(0) - - # @@: Should we set the umask and cwd now? - - import resource # Resource usage information. - maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1] - if (maxfd == resource.RLIM_INFINITY): - maxfd = MAXFD - # Iterate through and close all file descriptors. - for fd in range(0, maxfd): - try: - os.close(fd) - except OSError: # ERROR, fd wasn't open to begin with (ignored) - pass - - if (hasattr(os, "devnull")): - REDIRECT_TO = os.devnull - else: - REDIRECT_TO = "/dev/null" - os.open(REDIRECT_TO, os.O_RDWR) # standard input (0) - # Duplicate standard input to standard output and standard error. - os.dup2(0, 1) # standard output (1) - os.dup2(0, 2) # standard error (2) - - def _remove_pid_file(self, written_pid, filename, verbosity): - current_pid = os.getpid() - if written_pid != current_pid: - # A forked process must be exiting, not the process that - # wrote the PID file - return - if not os.path.exists(filename): - return - with open(filename) as f: - content = f.read().strip() - try: - pid_in_file = int(content) - except ValueError: - pass - else: - if pid_in_file != current_pid: - msg = "PID file %s contains %s, not expected PID %s" - self.out(msg % (filename, pid_in_file, current_pid)) - return - if verbosity > 0: - self.out("Removing PID file %s" % filename) - try: - os.unlink(filename) - return - except OSError as e: - # Record, but don't give traceback - self.out("Cannot remove PID file: (%s)" % e) - # well, at least lets not leave the invalid PID around... - try: - with open(filename, 'w') as f: - f.write('') - except OSError as e: - self.out('Stale PID left in file: %s (%s)' % (filename, e)) - else: - self.out('Stale PID removed') - - def record_pid(self, pid_file): - pid = os.getpid() - if self.options.verbose > 1: - self.out('Writing PID %s to %s' % (pid, pid_file)) - with open(pid_file, 'w') as f: - f.write(str(pid)) - atexit.register(self._remove_pid_file, pid, pid_file, self.options.verbose) - - def stop_daemon(self): # pragma: no cover - pid_file = self.options.pid_file or 'pyramid.pid' - if not os.path.exists(pid_file): - self.out('No PID file exists in %s' % pid_file) - return 1 - pid = read_pidfile(pid_file) - if not pid: - self.out("Not a valid PID file in %s" % pid_file) - return 1 - pid = live_pidfile(pid_file) - if not pid: - self.out("PID in %s is not valid (deleting)" % pid_file) - try: - os.unlink(pid_file) - except (OSError, IOError) as e: - self.out("Could not delete: %s" % e) - return 2 - return 1 - for j in range(10): - if not live_pidfile(pid_file): - break - import signal - kill(pid, signal.SIGTERM) - time.sleep(1) - else: - self.out("failed to kill web process %s" % pid) - return 3 - if os.path.exists(pid_file): - os.unlink(pid_file) - return 0 - - def show_status(self): # pragma: no cover - pid_file = self.options.pid_file or 'pyramid.pid' - if not os.path.exists(pid_file): - self.out('No PID file %s' % pid_file) - return 1 - pid = read_pidfile(pid_file) - if not pid: - self.out('No PID in file %s' % pid_file) - return 1 - pid = live_pidfile(pid_file) - if not pid: - self.out('PID %s in %s is not running' % (pid, pid_file)) - return 1 - self.out('Server running in PID %s' % pid) - return 0 - def restart_with_reloader(self): # pragma: no cover self.restart_with_monitor(reloader=True) @@ -668,16 +367,6 @@ or Supervisor, all of which support process security. if uid: os.setuid(uid) - def _warn_daemon_deprecated(self): - self.out('''\ -The daemon options have been deprecated in Pyramid 1.6. They will be removed -in a future release per Pyramid's deprecation policy. Please consider using -a real process manager for your processes like Systemd, Circus, or Supervisor. - -The following commands are deprecated: - [start,stop,restart,status] --daemon, --stop-server, --status, --pid-file, --log-file -''') - class LazyWriter(object): """ @@ -718,33 +407,6 @@ class LazyWriter(object): def flush(self): self.open().flush() -def live_pidfile(pidfile): # pragma: no cover - """(pidfile:str) -> int | None - Returns an int found in the named file, if there is one, - and if there is a running process with that process id. - Return None if no such process exists. - """ - pid = read_pidfile(pidfile) - if pid: - try: - kill(int(pid), 0) - return pid - except OSError as e: - if e.errno == errno.EPERM: - return pid - return None - -def read_pidfile(filename): - if os.path.exists(filename): - try: - with open(filename) as f: - content = f.read() - return int(content.strip()) - except (ValueError, IOError): - return None - else: - return None - def ensure_port_cleanup( bound_addresses, maxtries=30, sleeptime=2): # pragma: no cover """ diff --git a/pyramid/tests/test_scripts/test_pserve.py b/pyramid/tests/test_scripts/test_pserve.py index bc21665aa..bf4763602 100644 --- a/pyramid/tests/test_scripts/test_pserve.py +++ b/pyramid/tests/test_scripts/test_pserve.py @@ -1,23 +1,11 @@ -import atexit import os import tempfile import unittest -from pyramid.compat import PY2 -if PY2: - import __builtin__ -else: - import builtins as __builtin__ - class TestPServeCommand(unittest.TestCase): def setUp(self): from pyramid.compat import NativeIO self.out_ = NativeIO() - self.pid_file = None - - def tearDown(self): - if self.pid_file and os.path.exists(self.pid_file): - os.remove(self.pid_file) def out(self, msg): self.out_.write(msg) @@ -39,172 +27,12 @@ class TestPServeCommand(unittest.TestCase): cmd.out = self.out return cmd - def _makeOneWithPidFile(self, pid): - self.pid_file = tempfile.mktemp() - inst = self._makeOne() - with open(self.pid_file, 'w') as f: - f.write(str(pid)) - return inst - - def test_remove_pid_file_verbose(self): - inst = self._makeOneWithPidFile(os.getpid()) - inst._remove_pid_file(os.getpid(), self.pid_file, verbosity=1) - self._assert_pid_file_removed(verbose=True) - - def test_remove_pid_file_not_verbose(self): - inst = self._makeOneWithPidFile(os.getpid()) - inst._remove_pid_file(os.getpid(), self.pid_file, verbosity=0) - self._assert_pid_file_removed(verbose=False) - - def test_remove_pid_not_a_number(self): - inst = self._makeOneWithPidFile('not a number') - inst._remove_pid_file(os.getpid(), self.pid_file, verbosity=1) - self._assert_pid_file_removed(verbose=True) - - def test_remove_pid_current_pid_is_not_written_pid(self): - inst = self._makeOneWithPidFile(os.getpid()) - inst._remove_pid_file('99999', self.pid_file, verbosity=1) - self._assert_pid_file_not_removed('') - - def test_remove_pid_current_pid_is_not_pid_in_file(self): - inst = self._makeOneWithPidFile('99999') - inst._remove_pid_file(os.getpid(), self.pid_file, verbosity=1) - msg = 'PID file %s contains 99999, not expected PID %s' - self._assert_pid_file_not_removed(msg % (self.pid_file, os.getpid())) - - def test_remove_pid_no_pid_file(self): - inst = self._makeOne() - self.pid_file = 'some unknown path' - inst._remove_pid_file(os.getpid(), self.pid_file, verbosity=1) - self._assert_pid_file_removed(verbose=False) - - def test_remove_pid_file_unlink_exception(self): - inst = self._makeOneWithPidFile(os.getpid()) - self._remove_pid_unlink_exception(inst) - msg = [ - 'Removing PID file %s' % (self.pid_file), - 'Cannot remove PID file: (Some OSError - unlink)', - 'Stale PID removed'] - self._assert_pid_file_not_removed(msg=''.join(msg)) - with open(self.pid_file) as f: - self.assertEqual(f.read(), '') - - def test_remove_pid_file_stale_pid_write_exception(self): - inst = self._makeOneWithPidFile(os.getpid()) - self._remove_pid_unlink_and_write_exceptions(inst) - msg = [ - 'Removing PID file %s' % (self.pid_file), - 'Cannot remove PID file: (Some OSError - unlink)', - 'Stale PID left in file: %s ' % (self.pid_file), - '(Some OSError - open)'] - self._assert_pid_file_not_removed(msg=''.join(msg)) - with open(self.pid_file) as f: - self.assertEqual(int(f.read()), os.getpid()) - - def test_record_pid_verbose(self): - self._assert_record_pid(verbosity=2, msg='Writing PID %d to %s') - - def test_record_pid_not_verbose(self): - self._assert_record_pid(verbosity=1, msg='') - - def _remove_pid_unlink_exception(self, inst): - old_unlink = os.unlink - def fake_unlink(filename): - raise OSError('Some OSError - unlink') - - try: - os.unlink = fake_unlink - inst._remove_pid_file(os.getpid(), self.pid_file, verbosity=1) - finally: - os.unlink = old_unlink - - def _remove_pid_unlink_and_write_exceptions(self, inst): - old_unlink = os.unlink - def fake_unlink(filename): - raise OSError('Some OSError - unlink') - - run_already = [] - old_open = __builtin__.open - def fake_open(*args): - if not run_already: - run_already.append(True) - return old_open(*args) - raise OSError('Some OSError - open') - - try: - os.unlink = fake_unlink - __builtin__.open = fake_open - inst._remove_pid_file(os.getpid(), self.pid_file, verbosity=1) - finally: - os.unlink = old_unlink - __builtin__.open = old_open - - def _assert_pid_file_removed(self, verbose=False): - self.assertFalse(os.path.exists(self.pid_file)) - msg = 'Removing PID file %s' % (self.pid_file) if verbose else '' - self.assertEqual(self.out_.getvalue(), msg) - - def _assert_pid_file_not_removed(self, msg): - self.assertTrue(os.path.exists(self.pid_file)) - self.assertEqual(self.out_.getvalue(), msg) - - def _assert_record_pid(self, verbosity, msg): - old_atexit = atexit.register - def fake_atexit(*args): - pass - - self.pid_file = tempfile.mktemp() - pid = os.getpid() - inst = self._makeOne() - inst.options.verbose = verbosity - - try: - atexit.register = fake_atexit - inst.record_pid(self.pid_file) - finally: - atexit.register = old_atexit - - msg = msg % (pid, self.pid_file) if msg else '' - self.assertEqual(self.out_.getvalue(), msg) - with open(self.pid_file) as f: - self.assertEqual(int(f.read()), pid) - def test_run_no_args(self): inst = self._makeOne() result = inst.run() self.assertEqual(result, 2) self.assertEqual(self.out_.getvalue(), 'You must give a config file') - def test_run_stop_daemon_no_such_pid_file(self): - path = os.path.join(os.path.dirname(__file__), 'wontexist.pid') - inst = self._makeOne('--stop-daemon', '--pid-file=%s' % path) - inst.run() - msg = 'No PID file exists in %s' % path - self.assertTrue(msg in self.out_.getvalue()) - - def test_run_stop_daemon_bad_pid_file(self): - path = __file__ - inst = self._makeOne('--stop-daemon', '--pid-file=%s' % path) - inst.run() - msg = 'Not a valid PID file in %s' % path - self.assertTrue(msg in self.out_.getvalue()) - - def test_run_stop_daemon_invalid_pid_in_file(self): - fn = tempfile.mktemp() - with open(fn, 'wb') as tmp: - tmp.write(b'9999999') - tmp.close() - inst = self._makeOne('--stop-daemon', '--pid-file=%s' % fn) - inst.run() - msg = 'PID in %s is not valid (deleting)' % fn - self.assertTrue(msg in self.out_.getvalue()) - - def test_get_options_with_command(self): - inst = self._makeOne() - inst.args = ['foo', 'stop', 'a=1', 'b=2'] - result = inst.get_options() - self.assertEqual(result, {'a': '1', 'b': '2'}) - def test_get_options_no_command(self): inst = self._makeOne() inst.args = ['foo', 'a=1', 'b=2'] @@ -233,29 +61,6 @@ class TestPServeCommand(unittest.TestCase): inst.loadserver = self._get_server self.assertRaises(ValueError, inst.run) -class Test_read_pidfile(unittest.TestCase): - def _callFUT(self, filename): - from pyramid.scripts.pserve import read_pidfile - return read_pidfile(filename) - - def test_read_pidfile(self): - filename = tempfile.mktemp() - try: - with open(filename, 'w') as f: - f.write('12345') - result = self._callFUT(filename) - self.assertEqual(result, 12345) - finally: - os.remove(filename) - - def test_read_pidfile_no_pid_file(self): - result = self._callFUT('some unknown path') - self.assertEqual(result, None) - - def test_read_pidfile_not_a_number(self): - result = self._callFUT(__file__) - self.assertEqual(result, None) - class Test_main(unittest.TestCase): def _callFUT(self, argv): from pyramid.scripts.pserve import main -- cgit v1.2.3 From addb956a07a15e008c0fc4febf890dc410111868 Mon Sep 17 00:00:00 2001 From: zrayn Date: Thu, 2 Jun 2016 16:10:08 -0700 Subject: Removing changing user/group option --- pyramid/scripts/pserve.py | 66 ----------------------------------------------- 1 file changed, 66 deletions(-) diff --git a/pyramid/scripts/pserve.py b/pyramid/scripts/pserve.py index 9c9be2d38..ec7f31704 100644 --- a/pyramid/scripts/pserve.py +++ b/pyramid/scripts/pserve.py @@ -118,19 +118,6 @@ class PServeCommand(object): dest='verbose', help="Suppress verbose output") - if hasattr(os, 'setuid'): - # I don't think these are available on Windows - parser.add_option( - '--user', - dest='set_user', - metavar="USERNAME", - help="Set the user (usually only possible when run as root)") - parser.add_option( - '--group', - dest='set_group', - metavar="GROUP", - help="Set the group (usually only possible when run as root)") - _scheme_re = re.compile(r'^[a-z][a-z]+:', re.I) _reloader_environ_key = 'PYTHON_RELOADER_SHOULD_RUN' @@ -150,15 +137,6 @@ class PServeCommand(object): return parse_vars(restvars) def run(self): # pragma: no cover - if not hasattr(self.options, 'set_user'): - # Windows case: - self.options.set_user = self.options.set_group = None - - # @@: Is this the right stage to set the user at? - if self.options.set_user or self.options.set_group: - self.change_user_group( - self.options.set_user, self.options.set_group) - if not self.args: self.out('You must give a config file') return 2 @@ -323,50 +301,6 @@ class PServeCommand(object): if self.options.verbose > 0: self.out('%s %s %s' % ('-' * 20, 'Restarting', '-' * 20)) - def change_user_group(self, user, group): # pragma: no cover - import pwd - import grp - - self.out('''\ -The --user and --group options have been deprecated in Pyramid 1.6. They will -be removed in a future release per Pyramid's deprecation policy. Please -consider using a real process manager for your processes like Systemd, Circus, -or Supervisor, all of which support process security. -''') - - uid = gid = None - if group: - try: - gid = int(group) - group = grp.getgrgid(gid).gr_name - except ValueError: - import grp - try: - entry = grp.getgrnam(group) - except KeyError: - raise ValueError( - "Bad group: %r; no such group exists" % group) - gid = entry.gr_gid - try: - uid = int(user) - user = pwd.getpwuid(uid).pw_name - except ValueError: - try: - entry = pwd.getpwnam(user) - except KeyError: - raise ValueError( - "Bad username: %r; no such user exists" % user) - if not gid: - gid = entry.pw_gid - uid = entry.pw_uid - if self.options.verbose > 0: - self.out('Changing user to %s:%s (%s:%s)' % ( - user, group or '(unknown)', uid, gid)) - if gid: - os.setgid(gid) - if uid: - os.setuid(uid) - class LazyWriter(object): """ -- cgit v1.2.3 From 6439ce6622d1792cee66b13151ee7bcd586add47 Mon Sep 17 00:00:00 2001 From: Marco M Date: Thu, 2 Jun 2016 16:17:33 -0700 Subject: Add route name to view deriver options. Closes: #2609 --- pyramid/config/views.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pyramid/config/views.py b/pyramid/config/views.py index 9e46ba155..5cb3f5099 100644 --- a/pyramid/config/views.py +++ b/pyramid/config/views.py @@ -885,6 +885,7 @@ class ViewsConfiguratorMixin(object): # __no_permission_required__ handled by _secure_view derived_view = self._derive_view( view, + route_name=route_name, permission=permission, predicates=preds, attr=attr, @@ -1331,7 +1332,7 @@ class ViewsConfiguratorMixin(object): def _derive_view(self, view, permission=None, predicates=(), attr=None, renderer=None, wrapper_viewname=None, viewname=None, accept=None, order=MAX_ORDER, - phash=DEFAULT_PHASH, decorator=None, + phash=DEFAULT_PHASH, decorator=None, route_name=None, mapper=None, http_cache=None, context=None, require_csrf=None, extra_options=None): view = self.maybe_dotted(view) @@ -1361,6 +1362,7 @@ class ViewsConfiguratorMixin(object): decorator=decorator, http_cache=http_cache, require_csrf=require_csrf, + route_name=route_name ) if extra_options: options.update(extra_options) -- cgit v1.2.3 From 5c0c7c621cf59738c32f4474db8bd7e91741c1c8 Mon Sep 17 00:00:00 2001 From: Marco M Date: Thu, 2 Jun 2016 16:20:43 -0700 Subject: Sign CONTRIBUTORS.txt --- CONTRIBUTORS.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 762793d0b..d40d7d79c 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -270,3 +270,5 @@ Contributors - Vincent Férotin, 2016/05/08 - Berker Peksag, 2016/05/16 + +- Marco Martinez, 2016/06/02 -- cgit v1.2.3 From a5cbfca0f0567db8c00fe401dcfb895ab9860710 Mon Sep 17 00:00:00 2001 From: zrayn Date: Thu, 2 Jun 2016 16:41:25 -0700 Subject: Adding daemon support remove to CHANGES.txt --- CHANGES.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index c0681053d..4fdd7bf2f 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -4,6 +4,16 @@ unreleased Backward Incompatibilities -------------------------- + - Following the Pyramid deprecation period (1.6 -> 1.8), + daemon support for pserve has been removed. This includes removing the + daemon commands (start, stop, restart, status) as well as the following + arguments: + --daemon --pid-file --log-file --monitor-restart --status --user --group + --stop-daemon + + To run your server as a daemon you should use a process manager instead of + pserve. + Features -------- -- cgit v1.2.3 From a954081ea6fdb3cc276e0a258f133310cb0c4ddb Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 2 Jun 2016 17:04:16 -0700 Subject: fix broken links in msg and update summary in scaffold base class PyramidTemplate. - Closes #2604 --- pyramid/scaffolds/__init__.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pyramid/scaffolds/__init__.py b/pyramid/scaffolds/__init__.py index 4e811a42b..62c3eeecc 100644 --- a/pyramid/scaffolds/__init__.py +++ b/pyramid/scaffolds/__init__.py @@ -35,11 +35,10 @@ class PyramidTemplate(Template): msg = dedent( """ %(separator)s - Tutorials: http://docs.pylonsproject.org/projects/pyramid_tutorials - Documentation: http://docs.pylonsproject.org/projects/pyramid - - Twitter (tips & updates): http://twitter.com/pylons - Mailing List: http://groups.google.com/group/pylons-discuss + Tutorials: http://docs.pylonsproject.org/projects/pyramid_tutorials/en/latest/ + Documentation: http://docs.pylonsproject.org/projects/pyramid/en/latest/ + Twitter: https://twitter.com/trypyramid + Mailing List: https://groups.google.com/forum/#!forum/pylons-discuss Welcome to Pyramid. Sorry for the convenience. %(separator)s @@ -53,12 +52,13 @@ class PyramidTemplate(Template): class StarterProjectTemplate(PyramidTemplate): _template_dir = 'starter' - summary = 'Pyramid starter project' + summary = 'Pyramid starter project using URL dispatch and Chameleon' class ZODBProjectTemplate(PyramidTemplate): _template_dir = 'zodb' - summary = 'Pyramid ZODB project using traversal' + summary = 'Pyramid project using ZODB, traversal, and Chameleon' class AlchemyProjectTemplate(PyramidTemplate): _template_dir = 'alchemy' - summary = 'Pyramid SQLAlchemy project using url dispatch' + summary = 'Pyramid project using SQLAlchemy, SQLite, URL dispatch, and' + ' Chameleon' -- cgit v1.2.3 From 96a62f361a97ccf73738f3b576962817fc515305 Mon Sep 17 00:00:00 2001 From: cewing Date: Fri, 3 Jun 2016 10:31:08 -0700 Subject: update contributing docs to reflect current practice and clarify steps --- CONTRIBUTORS.txt | 2 ++ contributing.md | 32 +++++++++++++++++--------------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 16023c821..9f1ca0eae 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -274,3 +274,5 @@ Contributors - Zack Brunson, 2016/06/02 - Marco Martinez, 2016/06/02 + +- Cris Ewing, 2016/06/03 \ No newline at end of file diff --git a/contributing.md b/contributing.md index ae201d370..922d2e740 100644 --- a/contributing.md +++ b/contributing.md @@ -56,11 +56,15 @@ System](http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.ht git clone git@github.com:/pyramid.git +2. Change directories into the cloned repository + + cd pyramid + 3. Add a git remote "upstream" for the cloned fork. git remote add upstream git@github.com:Pylons/pyramid.git -4. Set an environment variable as instructed in the +4. Create a virtualenv and set an environment variable as instructed in the [prerequisites](https://github.com/Pylons/pyramid/blob/master/HACKING.txt#L55-L58). # Mac and Linux @@ -69,28 +73,26 @@ System](http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.ht # Windows set VENV=c:\hack-on-pyramid\env -5. Try to build the docs in your workspace. +4. Install `tox` into your virtualenv. - # Mac and Linux - $ make clean html SPHINXBUILD=$VENV/bin/sphinx-build + $ $VENV/bin/pip install tox - # Windows - c:\> make clean html SPHINXBUILD=%VENV%\bin\sphinx-build +5. Try to build the docs in your workspace. + + $ $VENV/bin/tox -e docs - If successful, then you can make changes to the documentation. You can - load the built documentation in the `/_build/html/` directory in a web - browser. + When the build finishes, you'll find HTML documentation rendered in + `.tox/docs/html`. An `epub` version will be in `.tox/docs/epub`. And the + result of the tests that are run on the documentation will be in + `.tox/docs/doctest`. 6. From this point forward, follow the typical [git workflow](https://help.github.com/articles/what-is-a-good-git-workflow/). - Start by pulling from the upstream to get the most current changes. + *Always* start by pulling from the upstream to get the most current changes. git pull upstream master -7. Make a branch, make changes to the docs, and rebuild them as indicated in - step 5. To speed up the build process, you can omit `clean` from the above - command to rebuild only those pages that depend on the files you have - changed. +7. Make a branch, make changes to the docs, and rebuild them as indicated above. 8. Once you are satisfied with your changes and the documentation builds successfully without errors or warnings, then git commit and push them to @@ -101,4 +103,4 @@ System](http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.ht 9. Create a [pull request](https://help.github.com/articles/using-pull-requests/). -10. Repeat the process starting from Step 6. +10. Repeat the process starting from Step 8. -- cgit v1.2.3 From 21227087f7f933eaae364627d8908f19c32c9990 Mon Sep 17 00:00:00 2001 From: cewing Date: Fri, 3 Jun 2016 10:50:45 -0700 Subject: make term less specific to one implementation --- contributing.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contributing.md b/contributing.md index 922d2e740..33a9dc55b 100644 --- a/contributing.md +++ b/contributing.md @@ -64,7 +64,7 @@ System](http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.ht git remote add upstream git@github.com:Pylons/pyramid.git -4. Create a virtualenv and set an environment variable as instructed in the +4. Create a virtual environment and set an environment variable as instructed in the [prerequisites](https://github.com/Pylons/pyramid/blob/master/HACKING.txt#L55-L58). # Mac and Linux @@ -73,7 +73,7 @@ System](http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.ht # Windows set VENV=c:\hack-on-pyramid\env -4. Install `tox` into your virtualenv. +4. Install `tox` into your virtual environment. $ $VENV/bin/pip install tox -- cgit v1.2.3 From aaca3310e15c4528de41c9b0a26ccbf1d5ce3763 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Fri, 3 Jun 2016 11:36:35 -0700 Subject: fix up numbering --- contributing.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/contributing.md b/contributing.md index 33a9dc55b..b5f17ae06 100644 --- a/contributing.md +++ b/contributing.md @@ -56,15 +56,15 @@ System](http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.ht git clone git@github.com:/pyramid.git -2. Change directories into the cloned repository +3. Change directories into the cloned repository cd pyramid -3. Add a git remote "upstream" for the cloned fork. +4. Add a git remote "upstream" for the cloned fork. git remote add upstream git@github.com:Pylons/pyramid.git -4. Create a virtual environment and set an environment variable as instructed in the +5. Create a virtual environment and set an environment variable as instructed in the [prerequisites](https://github.com/Pylons/pyramid/blob/master/HACKING.txt#L55-L58). # Mac and Linux @@ -73,11 +73,11 @@ System](http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.ht # Windows set VENV=c:\hack-on-pyramid\env -4. Install `tox` into your virtual environment. +6. Install `tox` into your virtual environment. $ $VENV/bin/pip install tox -5. Try to build the docs in your workspace. +7. Try to build the docs in your workspace. $ $VENV/bin/tox -e docs @@ -86,21 +86,21 @@ System](http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.ht result of the tests that are run on the documentation will be in `.tox/docs/doctest`. -6. From this point forward, follow the typical [git +8. From this point forward, follow the typical [git workflow](https://help.github.com/articles/what-is-a-good-git-workflow/). *Always* start by pulling from the upstream to get the most current changes. git pull upstream master -7. Make a branch, make changes to the docs, and rebuild them as indicated above. +9. Make a branch, make changes to the docs, and rebuild them as indicated above. -8. Once you are satisfied with your changes and the documentation builds - successfully without errors or warnings, then git commit and push them to - your "origin" repository on GitHub. +10. Once you are satisfied with your changes and the documentation builds + successfully without errors or warnings, then git commit and push them to + your "origin" repository on GitHub. git commit -m "commit message" git push -u origin --all # first time only, subsequent can be just 'git push'. -9. Create a [pull request](https://help.github.com/articles/using-pull-requests/). +11. Create a [pull request](https://help.github.com/articles/using-pull-requests/). -10. Repeat the process starting from Step 8. +12. Repeat the process starting from Step 8. -- cgit v1.2.3 From 5a43e63ded3d80ee5d65a8595d747b923abc94af Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 4 Jun 2016 12:07:18 -0700 Subject: We got our Bobo back! --- docs/designdefense.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/designdefense.rst b/docs/designdefense.rst index f42582e47..5f65671bb 100644 --- a/docs/designdefense.rst +++ b/docs/designdefense.rst @@ -1009,7 +1009,7 @@ Microframeworks have smaller Hello World programs Self-described "microframeworks" exist. `Bottle `_ and `Flask `_ are two that are becoming popular. `Bobo -`_ doesn't describe itself as a +`_ doesn't describe itself as a microframework, but its intended user base is much the same. Many others exist. We've even (only as a teaching tool, not as any sort of official project) `created one using Pyramid `_. -- cgit v1.2.3 From 1129435966dfb80f81ea9513867713e3cf248b49 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Tue, 7 Jun 2016 03:49:14 -0700 Subject: update links in readme --- README.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.rst b/README.rst index dec7e03d0..a9e38f636 100644 --- a/README.rst +++ b/README.rst @@ -17,11 +17,11 @@ Pyramid :target: https://webchat.freenode.net/?channels=pyramid :alt: IRC Freenode -Pyramid is a small, fast, down-to-earth, open source Python web framework. It -makes real-world web application development and deployment more fun, more -predictable, and more productive. +`Pyramid `_ is a small, fast, down-to-earth, open +source Python web framework. It makes real-world web application development +and deployment more fun, more predictable, and more productive. -Pyramid is produced by the `Pylons Project `_. +Pyramid is a project of the `Pylons Project `_. Support and Documentation ------------------------- @@ -46,6 +46,6 @@ Pyramid is offered under the BSD-derived `Repoze Public License Authors ------- -Pyramid is made available by `Agendaless Consulting `_ -and a team of contributors. - +Pyramid is made available by `Agendaless Consulting `_ +and a team of `contributors +`_. -- cgit v1.2.3 From bb800f2cd7424c6280a7346303963d0f0daed935 Mon Sep 17 00:00:00 2001 From: Julien MIOTTE Date: Fri, 3 Jun 2016 09:20:14 +0200 Subject: Adding a warning discouraging use of __acl__ properties attributes --- docs/narr/security.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/narr/security.rst b/docs/narr/security.rst index 7cbea113c..842aad23f 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -290,6 +290,13 @@ properties of the instance. def __init__(self, owner): self.owner = owner +.. warning:: + + Writing ``__acl__`` as properties is discouraged, as AttributeErrors + occuring in ``fget`` or ``fset`` will be silently dismissed (this is consistent + with Python ``getattr`` and ``hasattr`` behaviors). For dynamic ACLs, simply use + callables, as documented above. + .. index:: single: ACE single: access control entry -- cgit v1.2.3 From dd09252dedf58f2b40a32e1d1fec76595bb0f775 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 9 Jun 2016 01:24:07 -0700 Subject: grammar, spelling, wrapping fix --- docs/narr/security.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/narr/security.rst b/docs/narr/security.rst index 842aad23f..77e7fd707 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -292,10 +292,11 @@ properties of the instance. .. warning:: - Writing ``__acl__`` as properties is discouraged, as AttributeErrors - occuring in ``fget`` or ``fset`` will be silently dismissed (this is consistent - with Python ``getattr`` and ``hasattr`` behaviors). For dynamic ACLs, simply use - callables, as documented above. + Writing ``__acl__`` as properties is discouraged because an + ``AttributeError`` occurring in ``fget`` or ``fset`` will be silently + dismissed (this is consistent with Python ``getattr`` and ``hasattr`` + behaviors). For dynamic ACLs, simply use callables, as documented above. + .. index:: single: ACE -- cgit v1.2.3 From 7b536fa7164530f84683a9daae04c59009691941 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Fri, 10 Jun 2016 11:55:15 -0500 Subject: see how a code example looks in the readme --- README.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.rst b/README.rst index a9e38f636..35c335d9c 100644 --- a/README.rst +++ b/README.rst @@ -21,6 +21,23 @@ Pyramid source Python web framework. It makes real-world web application development and deployment more fun, more predictable, and more productive. +.. code-block:: python + + from wsgiref.simple_server import make_server + from pyramid.config import Configurator + from pyramid.response import Response + + def hello_world(request): + return Response('Hello %(name)s!' % request.matchdict) + + if __name__ == '__main__': + config = Configurator() + config.add_route('hello', '/hello/{name}') + config.add_view(hello_world, route_name='hello') + app = config.make_wsgi_app() + server = make_server('0.0.0.0', 8080, app) + server.serve_forever() + Pyramid is a project of the `Pylons Project `_. Support and Documentation -- cgit v1.2.3 From 47900408a701be8f7d09ef1377186f7b63327cdf Mon Sep 17 00:00:00 2001 From: JC Bohin Date: Mon, 13 Jun 2016 17:59:29 +0200 Subject: Fix flake8's noqa directive in documentation and scaffolds --- CONTRIBUTORS.txt | 4 +++- docs/quick_tour/sqla_demo/sqla_demo/models/__init__.py | 2 +- docs/tutorials/wiki2/src/authentication/tutorial/models/__init__.py | 4 ++-- docs/tutorials/wiki2/src/authorization/tutorial/models/__init__.py | 4 ++-- docs/tutorials/wiki2/src/basiclayout/tutorial/models/__init__.py | 2 +- docs/tutorials/wiki2/src/installation/tutorial/models/__init__.py | 2 +- docs/tutorials/wiki2/src/models/tutorial/models/__init__.py | 4 ++-- docs/tutorials/wiki2/src/tests/tutorial/models/__init__.py | 4 ++-- docs/tutorials/wiki2/src/views/tutorial/models/__init__.py | 4 ++-- pyramid/scaffolds/alchemy/+package+/models/__init__.py_tmpl | 2 +- 10 files changed, 17 insertions(+), 15 deletions(-) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 9f1ca0eae..25ccf6838 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -275,4 +275,6 @@ Contributors - Marco Martinez, 2016/06/02 -- Cris Ewing, 2016/06/03 \ No newline at end of file +- Cris Ewing, 2016/06/03 + +- Jean-Christophe Bohin, 2016/06/13 \ No newline at end of file diff --git a/docs/quick_tour/sqla_demo/sqla_demo/models/__init__.py b/docs/quick_tour/sqla_demo/sqla_demo/models/__init__.py index 6ffc10a78..76e0fd26b 100644 --- a/docs/quick_tour/sqla_demo/sqla_demo/models/__init__.py +++ b/docs/quick_tour/sqla_demo/sqla_demo/models/__init__.py @@ -1,7 +1,7 @@ from sqlalchemy.orm import configure_mappers # import all models classes here for sqlalchemy mappers # to pick up -from .mymodel import MyModel # flake8: noqa +from .mymodel import MyModel # noqa # run configure mappers to ensure we avoid any race conditions configure_mappers() diff --git a/docs/tutorials/wiki2/src/authentication/tutorial/models/__init__.py b/docs/tutorials/wiki2/src/authentication/tutorial/models/__init__.py index a8871f6f5..8147052ad 100644 --- a/docs/tutorials/wiki2/src/authentication/tutorial/models/__init__.py +++ b/docs/tutorials/wiki2/src/authentication/tutorial/models/__init__.py @@ -5,8 +5,8 @@ import zope.sqlalchemy # import or define all models here to ensure they are attached to the # Base.metadata prior to any initialization routines -from .page import Page # flake8: noqa -from .user import User # flake8: noqa +from .page import Page # noqa +from .user import User # noqa # run configure_mappers after defining all of the models to ensure # all relationships can be setup diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/models/__init__.py b/docs/tutorials/wiki2/src/authorization/tutorial/models/__init__.py index a8871f6f5..8147052ad 100644 --- a/docs/tutorials/wiki2/src/authorization/tutorial/models/__init__.py +++ b/docs/tutorials/wiki2/src/authorization/tutorial/models/__init__.py @@ -5,8 +5,8 @@ import zope.sqlalchemy # import or define all models here to ensure they are attached to the # Base.metadata prior to any initialization routines -from .page import Page # flake8: noqa -from .user import User # flake8: noqa +from .page import Page # noqa +from .user import User # noqa # run configure_mappers after defining all of the models to ensure # all relationships can be setup diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/models/__init__.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/models/__init__.py index 48a957ecb..3fc82cfba 100644 --- a/docs/tutorials/wiki2/src/basiclayout/tutorial/models/__init__.py +++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/models/__init__.py @@ -5,7 +5,7 @@ import zope.sqlalchemy # import or define all models here to ensure they are attached to the # Base.metadata prior to any initialization routines -from .mymodel import MyModel # flake8: noqa +from .mymodel import MyModel # noqa # run configure_mappers after defining all of the models to ensure # all relationships can be setup diff --git a/docs/tutorials/wiki2/src/installation/tutorial/models/__init__.py b/docs/tutorials/wiki2/src/installation/tutorial/models/__init__.py index 48a957ecb..3fc82cfba 100644 --- a/docs/tutorials/wiki2/src/installation/tutorial/models/__init__.py +++ b/docs/tutorials/wiki2/src/installation/tutorial/models/__init__.py @@ -5,7 +5,7 @@ import zope.sqlalchemy # import or define all models here to ensure they are attached to the # Base.metadata prior to any initialization routines -from .mymodel import MyModel # flake8: noqa +from .mymodel import MyModel # noqa # run configure_mappers after defining all of the models to ensure # all relationships can be setup diff --git a/docs/tutorials/wiki2/src/models/tutorial/models/__init__.py b/docs/tutorials/wiki2/src/models/tutorial/models/__init__.py index a8871f6f5..8147052ad 100644 --- a/docs/tutorials/wiki2/src/models/tutorial/models/__init__.py +++ b/docs/tutorials/wiki2/src/models/tutorial/models/__init__.py @@ -5,8 +5,8 @@ import zope.sqlalchemy # import or define all models here to ensure they are attached to the # Base.metadata prior to any initialization routines -from .page import Page # flake8: noqa -from .user import User # flake8: noqa +from .page import Page # noqa +from .user import User # noqa # run configure_mappers after defining all of the models to ensure # all relationships can be setup diff --git a/docs/tutorials/wiki2/src/tests/tutorial/models/__init__.py b/docs/tutorials/wiki2/src/tests/tutorial/models/__init__.py index a8871f6f5..fb250da60 100644 --- a/docs/tutorials/wiki2/src/tests/tutorial/models/__init__.py +++ b/docs/tutorials/wiki2/src/tests/tutorial/models/__init__.py @@ -5,8 +5,8 @@ import zope.sqlalchemy # import or define all models here to ensure they are attached to the # Base.metadata prior to any initialization routines -from .page import Page # flake8: noqa -from .user import User # flake8: noqa +from .page import Page # noqa +from .user import User # noqa # run configure_mappers after defining all of the models to ensure # all relationships can be setup diff --git a/docs/tutorials/wiki2/src/views/tutorial/models/__init__.py b/docs/tutorials/wiki2/src/views/tutorial/models/__init__.py index a8871f6f5..fb250da60 100644 --- a/docs/tutorials/wiki2/src/views/tutorial/models/__init__.py +++ b/docs/tutorials/wiki2/src/views/tutorial/models/__init__.py @@ -5,8 +5,8 @@ import zope.sqlalchemy # import or define all models here to ensure they are attached to the # Base.metadata prior to any initialization routines -from .page import Page # flake8: noqa -from .user import User # flake8: noqa +from .page import Page # noqa +from .user import User # noqa # run configure_mappers after defining all of the models to ensure # all relationships can be setup diff --git a/pyramid/scaffolds/alchemy/+package+/models/__init__.py_tmpl b/pyramid/scaffolds/alchemy/+package+/models/__init__.py_tmpl index 26b50aaf6..f626d1ef0 100644 --- a/pyramid/scaffolds/alchemy/+package+/models/__init__.py_tmpl +++ b/pyramid/scaffolds/alchemy/+package+/models/__init__.py_tmpl @@ -5,7 +5,7 @@ import zope.sqlalchemy # import or define all models here to ensure they are attached to the # Base.metadata prior to any initialization routines -from .mymodel import MyModel # flake8: noqa +from .mymodel import MyModel # noqa # run configure_mappers after defining all of the models to ensure # all relationships can be setup -- cgit v1.2.3 From ba7ab2c0a3b8797d02d7f522fa52818c0d390e09 Mon Sep 17 00:00:00 2001 From: JC Bohin Date: Mon, 13 Jun 2016 18:03:30 +0200 Subject: pep8: inline comment must have 2 spaces before --- docs/tutorials/wiki2/src/tests/tutorial/models/__init__.py | 4 ++-- docs/tutorials/wiki2/src/views/tutorial/models/__init__.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/tutorials/wiki2/src/tests/tutorial/models/__init__.py b/docs/tutorials/wiki2/src/tests/tutorial/models/__init__.py index fb250da60..8147052ad 100644 --- a/docs/tutorials/wiki2/src/tests/tutorial/models/__init__.py +++ b/docs/tutorials/wiki2/src/tests/tutorial/models/__init__.py @@ -5,8 +5,8 @@ import zope.sqlalchemy # import or define all models here to ensure they are attached to the # Base.metadata prior to any initialization routines -from .page import Page # noqa -from .user import User # noqa +from .page import Page # noqa +from .user import User # noqa # run configure_mappers after defining all of the models to ensure # all relationships can be setup diff --git a/docs/tutorials/wiki2/src/views/tutorial/models/__init__.py b/docs/tutorials/wiki2/src/views/tutorial/models/__init__.py index fb250da60..8147052ad 100644 --- a/docs/tutorials/wiki2/src/views/tutorial/models/__init__.py +++ b/docs/tutorials/wiki2/src/views/tutorial/models/__init__.py @@ -5,8 +5,8 @@ import zope.sqlalchemy # import or define all models here to ensure they are attached to the # Base.metadata prior to any initialization routines -from .page import Page # noqa -from .user import User # noqa +from .page import Page # noqa +from .user import User # noqa # run configure_mappers after defining all of the models to ensure # all relationships can be setup -- cgit v1.2.3 From 715ec5efbc3fc46e8e1cfef458667bded49d243e Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 16 Jun 2016 11:01:25 -0700 Subject: Quick Tour - static_assets - closes #2648 - swap contents of jinja2 templates - use __main__ to specify package - carry forward template to json step - use :language: python directive for correct syntax highlighting --- docs/quick_tour.rst | 13 +++++++------ docs/quick_tour/json/hello_world.jinja2 | 2 +- docs/quick_tour/static_assets/hello_world.jinja2 | 2 +- docs/quick_tour/static_assets/hello_world_static.jinja2 | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/quick_tour.rst b/docs/quick_tour.rst index b170e5d98..55557f501 100644 --- a/docs/quick_tour.rst +++ b/docs/quick_tour.rst @@ -339,9 +339,10 @@ Static assets Of course the Web is more than just markup. You need static assets: CSS, JS, and images. Let's point our web app at a directory from which Pyramid will serve some static assets. First let's make another call to the -:term:`configurator`: +:term:`configurator` in ``app.py``: .. literalinclude:: quick_tour/static_assets/app.py + :language: python :linenos: :lines: 6-8 :lineno-start: 6 @@ -359,7 +360,7 @@ Next make a directory named ``static``, and place ``app.css`` inside: All we need to do now is point to it in the ```` of our Jinja2 template, ``hello_world.jinja2``: -.. literalinclude:: quick_tour/static_assets/hello_world.jinja2 +.. literalinclude:: quick_tour/static_assets/hello_world_static.jinja2 :language: jinja :linenos: :lines: 4-6 @@ -371,16 +372,16 @@ the site is later moved under ``/somesite/static/``? Or perhaps a web developer changes the arrangement on disk? Pyramid provides a helper to allow flexibility on URL generation: -.. literalinclude:: quick_tour/static_assets/hello_world_static.jinja2 +.. literalinclude:: quick_tour/static_assets/hello_world.jinja2 :language: jinja :linenos: :lines: 4-6 :lineno-start: 4 :emphasize-lines: 2 -By using ``request.static_url`` to generate the full URL to the static -assets, you both ensure you stay in sync with the configuration and -gain refactoring flexibility later. +By using ``request.static_url`` to generate the full URL to the static assets, +you ensure that you stay in sync with the configuration and gain refactoring +flexibility later. .. seealso:: See also: :ref:`Quick Tutorial Static Assets `, diff --git a/docs/quick_tour/json/hello_world.jinja2 b/docs/quick_tour/json/hello_world.jinja2 index 4fb9be074..a55865231 100644 --- a/docs/quick_tour/json/hello_world.jinja2 +++ b/docs/quick_tour/json/hello_world.jinja2 @@ -2,7 +2,7 @@ Hello World - +

Hello {{ name }}!

diff --git a/docs/quick_tour/static_assets/hello_world.jinja2 b/docs/quick_tour/static_assets/hello_world.jinja2 index 0fb2ce296..a55865231 100644 --- a/docs/quick_tour/static_assets/hello_world.jinja2 +++ b/docs/quick_tour/static_assets/hello_world.jinja2 @@ -2,7 +2,7 @@ Hello World - +

Hello {{ name }}!

diff --git a/docs/quick_tour/static_assets/hello_world_static.jinja2 b/docs/quick_tour/static_assets/hello_world_static.jinja2 index 4fb9be074..0fb2ce296 100644 --- a/docs/quick_tour/static_assets/hello_world_static.jinja2 +++ b/docs/quick_tour/static_assets/hello_world_static.jinja2 @@ -2,7 +2,7 @@ Hello World - +

Hello {{ name }}!

-- cgit v1.2.3 From da42d5794a1d2fff3e6a57980cf7018ec2e361b9 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 16 Jun 2016 11:05:06 -0700 Subject: Quick Tour - explicitly use :language: python directive for proper syntax highlighting --- docs/quick_tour.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/quick_tour.rst b/docs/quick_tour.rst index 55557f501..dde91b495 100644 --- a/docs/quick_tour.rst +++ b/docs/quick_tour.rst @@ -1,3 +1,4 @@ + .. _quick_tour: ===================== @@ -70,6 +71,7 @@ step. Here's a tiny application in Pyramid: .. literalinclude:: quick_tour/hello_world/app.py :linenos: + :language: python This simple example is easy to run. Save this as ``app.py`` and run it: @@ -120,6 +122,7 @@ library for request and response handling. In our example above, Pyramid hands Let's see some features of requests and responses in action: .. literalinclude:: quick_tour/requests/app.py + :language: python :pyobject: hello_world In this Pyramid view, we get the URL being visited from ``request.url``. Also @@ -159,6 +162,7 @@ Let's move the views out to their own ``views.py`` module and change the First our revised ``app.py``: .. literalinclude:: quick_tour/views/app.py + :language: python :linenos: We added some more routes, but we also removed the view code. Our views and @@ -169,6 +173,7 @@ We now have a ``views.py`` module that is focused on handling requests and responses: .. literalinclude:: quick_tour/views/views.py + :language: python :linenos: We have four views, each leading to the other. If you start at @@ -214,6 +219,7 @@ What if we want part of the URL to be available as data in my view? We can use this route declaration, for example: .. literalinclude:: quick_tour/routing/app.py + :language: python :linenos: :lines: 6 :lineno-start: 6 @@ -222,6 +228,7 @@ With this, URLs such as ``/howdy/amy/smith`` will assign ``amy`` to ``first`` and ``smith`` to ``last``. We can then use this data in our view: .. literalinclude:: quick_tour/routing/views.py + :language: python :linenos: :lines: 5-8 :lineno-start: 5 @@ -260,6 +267,7 @@ With the package installed, we can include the template bindings into our configuration in ``app.py``: .. literalinclude:: quick_tour/templating/app.py + :language: python :linenos: :lines: 6-8 :lineno-start: 6 @@ -268,6 +276,7 @@ configuration in ``app.py``: Now lets change our ``views.py`` file: .. literalinclude:: quick_tour/templating/views.py + :language: python :linenos: :emphasize-lines: 4,6 @@ -304,6 +313,7 @@ With the package installed, we can include the template bindings into our configuration: .. literalinclude:: quick_tour/jinja2/app.py + :language: python :linenos: :lines: 6-8 :lineno-start: 6 @@ -312,6 +322,7 @@ configuration: The only change in our view is to point the renderer at the ``.jinja2`` file: .. literalinclude:: quick_tour/jinja2/views.py + :language: python :linenos: :lines: 4-6 :lineno-start: 4 @@ -397,6 +408,7 @@ to update the UI in the browser by requesting server data as JSON. Pyramid supports this with a JSON renderer: .. literalinclude:: quick_tour/json/views.py + :language: python :linenos: :lines: 9- :lineno-start: 9 @@ -409,6 +421,7 @@ We also need to add a route to ``app.py`` so that our app will know how to respond to a request for ``hello.json``. .. literalinclude:: quick_tour/json/app.py + :language: python :linenos: :lines: 6-8 :lineno-start: 6 @@ -438,6 +451,7 @@ The following shows a "Hello World" example with three operations: view a form, save a change, or press the delete button in our ``views.py``: .. literalinclude:: quick_tour/view_classes/views.py + :language: python :linenos: :lines: 7- :lineno-start: 7 @@ -729,6 +743,7 @@ Our unit test passed, although its coverage is incomplete. What did our test look like? .. literalinclude:: quick_tour/package/hello_world/tests.py + :language: python :linenos: Pyramid supplies helpers for test writing, which we use in the test setup and @@ -882,6 +897,7 @@ SQLAlchemy uses "models" for this mapping. The scaffold generated a sample model: .. literalinclude:: quick_tour/sqla_demo/sqla_demo/models/mymodel.py + :language: python :start-after: Start Sphinx Include :end-before: End Sphinx Include @@ -889,6 +905,7 @@ View code, which mediates the logic between web requests and the rest of the system, can then easily get at the data thanks to SQLAlchemy: .. literalinclude:: quick_tour/sqla_demo/sqla_demo/views/default.py + :language: python :start-after: Start Sphinx Include :end-before: End Sphinx Include -- cgit v1.2.3 From 49783e1f9b3b42721c02b7253002826d6f25c79a Mon Sep 17 00:00:00 2001 From: dowwie Date: Mon, 20 Jun 2016 11:33:07 -0400 Subject: typo fix within urldispatch narrative, example 2 --- docs/narr/urldispatch.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst index 2472ace31..7d37c04df 100644 --- a/docs/narr/urldispatch.rst +++ b/docs/narr/urldispatch.rst @@ -557,7 +557,7 @@ Here is an example of a corresponding ``mypackage.views`` module: @view_config(route_name='idea') def idea_view(request): - return Response(request.matchdict['id']) + return Response(request.matchdict['idea']) @view_config(route_name='user') def user_view(request): -- cgit v1.2.3