summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.rst5
-rw-r--r--CONTRIBUTORS.txt6
-rw-r--r--HACKING.txt6
-rw-r--r--docs/narr/sessions.rst37
-rw-r--r--docs/quick_tutorial/databases/tutorial/models.py8
-rw-r--r--docs/quick_tutorial/json.rst2
-rw-r--r--docs/quick_tutorial/view_classes.rst2
-rw-r--r--docs/whatsnew-2.0.rst2
-rw-r--r--setup.cfg1
-rw-r--r--src/pyramid/config/views.py2
-rw-r--r--src/pyramid/session.py38
-rw-r--r--src/pyramid/threadlocal.py2
-rw-r--r--src/pyramid/traversal.py8
-rw-r--r--tests/test_authentication.py2
-rw-r--r--tests/test_router.py2
-rw-r--r--tests/test_session.py4
-rw-r--r--tests/test_testing.py2
-rw-r--r--tests/test_traversal.py4
-rw-r--r--tests/test_url.py2
19 files changed, 94 insertions, 41 deletions
diff --git a/CHANGES.rst b/CHANGES.rst
index 987d5c3d4..936d487bf 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -62,6 +62,11 @@ Features
Deprecations
------------
+- Deprecated ``pyramid.session.PickleSerializer``.
+ See https://github.com/pylons/pyramid/issues/2709
+ and https://github.com/pylons/pyramid/pull/3353
+ and https://github.com/pylons/pyramid/pull/3413
+
Backward Incompatibilities
--------------------------
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index c01dd49b2..65be5e259 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -344,3 +344,9 @@ Contributors
- Theron Luhn, 2019/03/30
- Mandar Vaze, 2019/07/20
+
+- Jonathan Vanasco, 2019/11/05
+
+- Jan Likar, 2019/11/07
+
+- Andrea Borghi, 2019/11/11
diff --git a/HACKING.txt b/HACKING.txt
index 901eb8518..5ccc318de 100644
--- a/HACKING.txt
+++ b/HACKING.txt
@@ -74,10 +74,10 @@ Running Tests
to your virtual environment:
# run a single test
- $ $VENV/bin/nosetests pyramid.tests.test_module:ClassName.test_mytestname
+ $ $VENV/bin/nosetests tests.test_module:ClassName.test_mytestname
# run all tests in a class
- $ $VENV/bin/nosetests pyramid.tests.test_module:ClassName
+ $ $VENV/bin/nosetests tests.test_module:ClassName
Optionally you can install a nose plugin `nose-selecttests` to run specific
tests.
@@ -93,7 +93,7 @@ Running Tests
tests like so:
$ $VENV/bin/pip install pytest
- $ $VENV/bin/pytest --strict pyramid/
+ $ $VENV/bin/pytest --strict pyramid/ tests/
To run individual tests (i.e., during development), see "pytest usage -
Specifying tests / selecting tests":
diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst
index c2cc60de8..2da524d4c 100644
--- a/docs/narr/sessions.rst
+++ b/docs/narr/sessions.rst
@@ -85,32 +85,49 @@ This is a stricter contract than the previous requirement that all objects be pi
This is a backward-incompatible change.
Previously, if a client-side session implementation was compromised, it left the application vulnerable to remote code execution attacks using specially-crafted sessions that execute code when deserialized.
+Please reference the following tickets if detailed information on these changes is needed:
+
+* `2.0 feature request: Require that sessions are JSON serializable #2709 <https://github.com/pylons/pyramid/issues/2709>`_.
+* `deprecate pickleable sessions, recommend json #3353 <https://github.com/pylons/pyramid/pull/3353>`_.
+* `change to use JSONSerializer for SignedCookieSessionFactory #3413 <https://github.com/pylons/pyramid/pull/3413>`_.
+
For users with compatibility concerns, it's possible to craft a serializer that can handle both formats until you are satisfied that clients have had time to reasonably upgrade.
Remember that sessions should be short-lived and thus the number of clients affected should be small (no longer than an auth token, at a maximum). An example serializer:
.. code-block:: python
:linenos:
+ import pickle
from pyramid.session import JSONSerializer
- from pyramid.session import PickleSerializer
from pyramid.session import SignedCookieSessionFactory
+
class JSONSerializerWithPickleFallback(object):
def __init__(self):
self.json = JSONSerializer()
- self.pickle = PickleSerializer()
- def dumps(self, value):
- # maybe catch serialization errors here and keep using pickle
- # while finding spots in your app that are not storing
- # JSON-serializable objects, falling back to pickle
- return self.json.dumps(value)
+ def dumps(self, appstruct):
+ """
+ Accept a Python object and return bytes.
+
+ During a migration, you may want to catch serialization errors here,
+ and keep using pickle while finding spots in your app that are not
+ storing JSON-serializable objects. You may also want to integrate
+ a fall-back to pickle serialization here as well.
+ """
+ return self.json.dumps(appstruct)
- def loads(self, value):
+ def loads(self, bstruct):
+ """Accept bytes and return a Python object."""
try:
- return self.json.loads(value)
+ return self.json.loads(bstruct)
except ValueError:
- return self.pickle.loads(value)
+ try:
+ return pickle.loads(bstruct)
+ except Exception:
+ # this block should catch at least:
+ # ValueError, AttributeError, ImportError; but more to be safe
+ raise ValueError
# somewhere in your configuration code
serializer = JSONSerializerWithPickleFallback()
diff --git a/docs/quick_tutorial/databases/tutorial/models.py b/docs/quick_tutorial/databases/tutorial/models.py
index b27c38417..8e6649d49 100644
--- a/docs/quick_tutorial/databases/tutorial/models.py
+++ b/docs/quick_tutorial/databases/tutorial/models.py
@@ -13,10 +13,10 @@ from sqlalchemy.orm import (
sessionmaker,
)
-from zope.sqlalchemy import ZopeTransactionExtension
+from zope.sqlalchemy import register
-DBSession = scoped_session(
- sessionmaker(extension=ZopeTransactionExtension()))
+DBSession = scoped_session(sessionmaker())
+register(DBSession)
Base = declarative_base()
@@ -32,4 +32,4 @@ class Root(object):
(Allow, 'group:editors', 'edit')]
def __init__(self, request):
- pass \ No newline at end of file
+ pass
diff --git a/docs/quick_tutorial/json.rst b/docs/quick_tutorial/json.rst
index 44d1de8cb..19d346199 100644
--- a/docs/quick_tutorial/json.rst
+++ b/docs/quick_tutorial/json.rst
@@ -63,7 +63,7 @@ Steps
.. code-block:: bash
- $ $VENV/bin/pserve development.ini --reload
+ $VENV/bin/pserve development.ini --reload
#. Open http://localhost:6543/howdy.json in your browser and you will see the
resulting JSON response.
diff --git a/docs/quick_tutorial/view_classes.rst b/docs/quick_tutorial/view_classes.rst
index 1307857b7..c9f61f5a3 100644
--- a/docs/quick_tutorial/view_classes.rst
+++ b/docs/quick_tutorial/view_classes.rst
@@ -78,7 +78,7 @@ To ease the transition to view classes, we didn't introduce any new
functionality. We simply changed the view functions to methods on a view class,
then updated the tests.
-In our ``TutorialViews`` view class, you can see that our two view classes are
+In our ``TutorialViews`` view class, you can see that our two view functions are
logically grouped together as methods on a common class. Since the two views
shared the same template, we could move that to a ``@view_defaults`` decorator
at the class level.
diff --git a/docs/whatsnew-2.0.rst b/docs/whatsnew-2.0.rst
index 4448e0f69..b5f349166 100644
--- a/docs/whatsnew-2.0.rst
+++ b/docs/whatsnew-2.0.rst
@@ -58,7 +58,7 @@ flexibility in authorization implementations, especially those that do not
match the ACL pattern. If you were previously using
:class:`pyramid.authorization.ACLAuthorizationPolicy`, you can achieve the same
results by writing your own ``permits`` method using
-:class:`pyraid.authorization.ACLHelper`. For more details on implementing an
+:class:`pyramid.authorization.ACLHelper`. For more details on implementing an
ACL, see :ref:`assigning_acls`.
Pyramid does not provide any built-in security policies. Similiar
diff --git a/setup.cfg b/setup.cfg
index 3e10bb55b..19f338b91 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -3,7 +3,6 @@ zip_ok = false
[nosetests]
match = ^test
-tests = tests
nocapture = 1
[aliases]
diff --git a/src/pyramid/config/views.py b/src/pyramid/config/views.py
index afb685f93..bc0b05a08 100644
--- a/src/pyramid/config/views.py
+++ b/src/pyramid/config/views.py
@@ -2045,6 +2045,8 @@ class ViewsConfiguratorMixin(object):
:class:`~pyramid.interfaces.ICacheBuster` interface.
Default: ``False``.
+ .. versionadded:: 1.6
+
"""
spec = self._make_spec(path)
info = self._get_static_info()
diff --git a/src/pyramid/session.py b/src/pyramid/session.py
index 70ac4f55f..10e1ea313 100644
--- a/src/pyramid/session.py
+++ b/src/pyramid/session.py
@@ -44,14 +44,25 @@ def manage_changed(wrapped):
class PickleSerializer(object):
- """ A serializer that uses the pickle protocol to dump Python
- data to bytes.
+ """
+ .. deprecated:: 2.0
+
+ .. warning::
+
+ In :app:`Pyramid` 2.0 the default ``serializer`` option changed to
+ use :class:`pyramid.session.JSONSerializer`, and ``PickleSerializer``
+ has been been removed from active Pyramid code.
+
+ Pyramid will require JSON-serializable objects in :app:`Pyramid` 2.0.
+
+ Please see :ref:`pickle_session_deprecation`.
- This is the default serializer used by Pyramid.
+ A serializer that uses the pickle protocol to dump Python data to bytes.
+
+ This was the default serializer used by Pyramid, but has been deprecated.
``protocol`` may be specified to control the version of pickle used.
Defaults to :attr:`pickle.HIGHEST_PROTOCOL`.
-
"""
def __init__(self, protocol=pickle.HIGHEST_PROTOCOL):
@@ -61,8 +72,9 @@ class PickleSerializer(object):
"""Accept bytes and return a Python object."""
try:
return pickle.loads(bstruct)
- # at least ValueError, AttributeError, ImportError but more to be safe
except Exception:
+ # this block should catch at least:
+ # ValueError, AttributeError, ImportError; but more to be safe
raise ValueError
def dumps(self, appstruct):
@@ -70,6 +82,14 @@ class PickleSerializer(object):
return pickle.dumps(appstruct, self.protocol)
+deprecated(
+ 'PickleSerializer',
+ 'pyramid.session.PickleSerializer is deprecated as of Pyramid 2.0 for '
+ 'security concerns. Use pyramid.session.JSONSerializer or reference the '
+ 'narrative documentation for information on building a migration tool.',
+)
+
+
JSONSerializer = JSONSerializer # api
@@ -438,10 +458,10 @@ def SignedCookieSessionFactory(
.. warning::
- In :app:`Pyramid` 2.0 the default ``serializer`` option changed to
- use :class:`pyramid.session.JSONSerializer`. See
- :ref:`pickle_session_deprecation` for more information about why this
- change was made.
+ In :app:`Pyramid` 2.0 the default ``serializer`` option changed to
+ use :class:`pyramid.session.JSONSerializer`. See
+ :ref:`pickle_session_deprecation` for more information about why this
+ change was made.
.. versionadded: 1.5a3
diff --git a/src/pyramid/threadlocal.py b/src/pyramid/threadlocal.py
index 7eca5b0f0..24bc0ec33 100644
--- a/src/pyramid/threadlocal.py
+++ b/src/pyramid/threadlocal.py
@@ -55,7 +55,7 @@ def get_current_request():
def get_current_registry(
- context=None
+ context=None,
): # context required by getSiteManager API
"""
Return the currently active :term:`application registry` or the
diff --git a/src/pyramid/traversal.py b/src/pyramid/traversal.py
index 9ed5754b7..811c0881b 100644
--- a/src/pyramid/traversal.py
+++ b/src/pyramid/traversal.py
@@ -708,8 +708,8 @@ class ResourceTreeTraverser(object):
ModelGraphTraverser = (
- ResourceTreeTraverser
-) # b/w compat, not API, used in wild
+ ResourceTreeTraverser # b/w compat, not API, used in wild
+)
@implementer(IResourceURL)
@@ -744,8 +744,8 @@ class ResourceURL(object):
self.physical_path = physical_path # IResourceURL attr
self.virtual_path_tuple = virtual_path_tuple # IResourceURL attr (1.5)
self.physical_path_tuple = (
- physical_path_tuple
- ) # IResourceURL attr (1.5)
+ physical_path_tuple # IResourceURL attr (1.5)
+ )
@lru_cache(1000)
diff --git a/tests/test_authentication.py b/tests/test_authentication.py
index 710e87423..cb2a0a035 100644
--- a/tests/test_authentication.py
+++ b/tests/test_authentication.py
@@ -398,7 +398,7 @@ class TestRepozeWho1AuthenticationPolicy(unittest.TestCase):
self.assertEqual(policy.effective_principals(request), [Everyone])
def test_effective_principals_repoze_who_userid_is_unclean_Authenticated(
- self
+ self,
):
from pyramid.security import Everyone
diff --git a/tests/test_router.py b/tests/test_router.py
index 722f4286c..f6b7f64d3 100644
--- a/tests/test_router.py
+++ b/tests/test_router.py
@@ -434,7 +434,7 @@ class TestRouter(unittest.TestCase):
self.assertEqual(request.root, context)
def test_call_view_registered_nonspecific_nondefault_path_and_subpath(
- self
+ self,
):
from pyramid.interfaces import IViewClassifier
diff --git a/tests/test_session.py b/tests/test_session.py
index 8e5e82bb2..582a7ed4a 100644
--- a/tests/test_session.py
+++ b/tests/test_session.py
@@ -564,6 +564,10 @@ class Test_manage_changed(unittest.TestCase):
class TestPickleSerializer(unittest.TestCase):
+ """
+ .. deprecated:: 2.0
+ """
+
def _makeOne(self):
from pyramid.session import PickleSerializer
diff --git a/tests/test_testing.py b/tests/test_testing.py
index d0f23a116..ad1fca1d9 100644
--- a/tests/test_testing.py
+++ b/tests/test_testing.py
@@ -55,7 +55,7 @@ class TestDummyResource(unittest.TestCase):
return klass(name, parent, **kw)
def test__setitem__and__getitem__and__delitem__and__contains__and_get(
- self
+ self,
):
class Dummy:
pass
diff --git a/tests/test_traversal.py b/tests/test_traversal.py
index 188ee803c..fdb0bcbb7 100644
--- a/tests/test_traversal.py
+++ b/tests/test_traversal.py
@@ -1270,8 +1270,8 @@ class DummyContext(object):
class DummyRequest:
application_url = (
- 'http://example.com:5432'
- ) # app_url never ends with slash
+ 'http://example.com:5432' # app_url never ends with slash
+ )
matchdict = None
matched_route = None
diff --git a/tests/test_url.py b/tests/test_url.py
index 648f48d53..c5c0ca09f 100644
--- a/tests/test_url.py
+++ b/tests/test_url.py
@@ -940,7 +940,7 @@ class TestURLMethodsMixin(unittest.TestCase):
self.assertEqual(result, 'http://example.com:8080')
def test_partial_application_url_with_http_host_nondefault_port_https(
- self
+ self,
):
environ = {'wsgi.url_scheme': 'https', 'HTTP_HOST': 'example.com:4443'}
request = self._makeOne(environ)