Skip to content

Commit c1d6222

Browse files
authored
Add upgrade guide to docs (#1197)
1 parent 5facc5d commit c1d6222

File tree

5 files changed

+201
-34
lines changed

5 files changed

+201
-34
lines changed

docs/index.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,7 @@ Topics
4646
contributing
4747
release_notes
4848
versioning
49-
upgrading_binary
50-
upgrading_unicodeset
49+
upgrading
5150

5251
API docs
5352
========

docs/release_notes.rst

Lines changed: 52 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
.. _release_notes:
2+
13
Release Notes
24
=============
35

@@ -102,8 +104,13 @@ v5.0.3
102104

103105
:date: 2021-02-14
104106

107+
This version has an unintentional breaking change:
108+
105109
* Propagate ``Model.serialize``'s ``null_check`` parameter to nested MapAttributes (:pr:`908`)
106110

111+
Previously null errors (persisting ``None`` into an attribute defined as ``null=False``)
112+
were ignored for attributes in map attributes that were nested in maps or lists. After upgrade,
113+
these will resulted in an :py:class:`~pynamodb.exceptions.AttributeNullError` being raised.
107114

108115
v5.0.2
109116
----------
@@ -128,22 +135,32 @@ v5.0.0
128135

129136
This is major release and contains breaking changes. Please read the notes below carefully.
130137

131-
**Polymorphism**
138+
Breaking changes
139+
================
132140

133-
This release introduces :ref:`polymorphism` support via :py:class:`DiscriminatorAttribute <pynamodb.attributes.DiscriminatorAttribute>`.
134-
Discriminator values are written to DynamoDB and used during deserialization to instantiate the desired class.
141+
* Python 2 is no longer supported. Python 3.6 or greater is now required.
142+
* :py:class:`~pynamodb.attributes.UnicodeAttribute` and :py:class:`~pynamodb.attributes.BinaryAttribute` now support empty values (:pr:`830`)
135143

136-
**UTCDateTimeAttribute**
144+
In previous versions, assigning an empty value to would be akin to assigning ``None``: if the attribute was defined with ``null=True`` then it would be omitted, otherwise an error would be raised.
137145

138-
The UTCDateTimeAttribute now strictly requires the date string format '%Y-%m-%dT%H:%M:%S.%f%z' to ensure proper ordering.
139-
PynamoDB has always written values with this format but previously would accept reading other formats.
140-
Items written using other formats must be rewritten before upgrading.
146+
As of May 2020, DynamoDB `supports <https://aws.amazon.com/about-aws/whats-new/2020/05/amazon-dynamodb-now-supports-empty-values-for-non-key-string-and-binary-attributes-in-dynamodb-tables/>`_ empty values for String and Binary attributes. This release of PynamoDB starts treating empty values like any other values. If existing code unintentionally assigns empty values to StringAttribute or BinaryAttribute, this may be a breaking change: for example, the code may rely on the fact that in previous versions empty strings would be "read back" as ``None`` values when reloaded from the database.
147+
* :py:class:`~pynamodb.attributes.UTCDateTimeAttribute` now strictly requires the date string format ``'%Y-%m-%dT%H:%M:%S.%f%z'`` to ensure proper ordering.
148+
PynamoDB has always written values with this format but previously would accept reading other formats.
149+
Items written using other formats must be rewritten before upgrading.
150+
* Table backup functionality (``Model.dump[s]`` and ``Model.load[s]``) has been removed.
151+
* ``Model.query`` no longer converts unsupported range key conditions into filter conditions.
152+
* Internal attribute type constants are replaced with their "short" DynamoDB version (:pr:`827`)
153+
* Remove ``ListAttribute.remove_indexes`` (added in v4.3.2) and document usage of remove for list elements (:pr:`838`)
154+
* Remove ``pynamodb.connection.util.pythonic`` (:pr:`753`) and (:pr:`865`)
155+
* Remove ``ModelContextManager`` class (:pr:`861`)
141156

142-
**UnicodeAttribute and BinaryAttribute**
157+
Features
158+
========
143159

144-
In previous versions, assigning an empty value to a :py:class:`UnicodeAttribute <pynamodb.attributes.UnicodeAttribute>` or :py:class:`BinaryAttribute <pynamodb.attributes.BinaryAttribute>` would be akin to assigning ``None``: if the attribute was defined with ``null=True`` then it would be omitted, otherwise an error would be raised.
160+
**Polymorphism**
145161

146-
As of May 2020, DynamoDB `supports <https://aws.amazon.com/about-aws/whats-new/2020/05/amazon-dynamodb-now-supports-empty-values-for-non-key-string-and-binary-attributes-in-dynamodb-tables/>`_ empty values for String and Binary attributes. This release of PynamoDB starts treating empty values like any other values. If existing code unintentionally assigns empty values to StringAttribute or BinaryAttribute, this may be a breaking change: for example, the code may rely on the fact that in previous versions empty strings would be "read back" as ``None`` values when reloaded from the database.
162+
This release introduces :ref:`polymorphism` support via :py:class:`DiscriminatorAttribute <pynamodb.attributes.DiscriminatorAttribute>`.
163+
Discriminator values are written to DynamoDB and used during deserialization to instantiate the desired class.
147164

148165
**Model Serialization**
149166

@@ -152,22 +169,11 @@ THe ``Model`` class now includes public methods for serializing and deserializin
152169

153170
Other changes in this release:
154171

155-
* Python 2 is no longer supported. Python 3.6 or greater is now required.
156-
* Table backup functionality (``Model.dump[s]`` and ``Model.load[s]``) has been removed.
157-
* ``Model.query`` no longer demotes invalid range key conditions to be filter conditions to avoid surprising behaviors:
158-
where what's intended to be a cheap and fast condition ends up being expensive and slow. Since filter conditions
159-
cannot contain range keys, this had limited utility to begin with, and would sometimes cause confusing
160-
"'filter_condition' cannot contain key attributes" errors.
161-
* Replace the internal attribute type constants with their "short" DynamoDB version (:pr:`827`)
162172
* Typed list attributes can now support any Attribute subclass (:pr:`833`)
163-
* Add support for empty values in Binary and String attributes (:pr:`830`)
164173
* Most API operation methods now accept a ``settings`` argument to customize settings of individual operations.
165174
This currently allow adding or overriding HTTP headers. (:pr:`887`)
166-
* Remove ``ListAttribute.remove_indexes`` (added in v4.3.2) and document usage of remove for list elements (:pr:`838`)
167175
* Add the attribute name to error messages when deserialization fails (:pr:`815`)
168176
* Add the table name to error messages for transactional operations (:pr:`835`)
169-
* Remove ``pynamodb.connection.util.pythonic`` (:pr:`753`) and (:pr:`865`)
170-
* Remove ``ModelContextManager`` class (:pr:`861`)
171177

172178
Contributors to this release:
173179

@@ -322,20 +328,34 @@ of all attributes including the key attributes.
322328
Support for `Legacy Conditional Parameters <https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.html>`_ has been
323329
removed. See a complete list of affected ``Model`` methods below:
324330

325-
* ``update_item``: removed in favor of ``update``.
326-
* ``rate_limited_scan``: removed in favor of ``scan`` and ``ResultIterator``.
331+
.. list-table::
332+
:widths: 10 90
333+
:header-rows: 1
334+
335+
* - Method
336+
- Changes
337+
* - ``update_item``
338+
- removed in favor of ``update``
339+
* - ``rate_limited_scan``
340+
- removed in favor of ``scan`` and ``ResultIterator``
341+
* - ``delete``
342+
- ``conditional_operator`` and ``**expected_values`` kwargs removed. Use ``condition`` instead.
343+
* - ``update``
344+
- ``attributes``, ``conditional_operator`` and ``**expected_values`` kwargs removed. Use ``actions`` and ``condition`` instead.
345+
* - ``save``
346+
- ``conditional_operator`` and ``**expected_values`` kwargs removed. Use ``condition`` instead.
347+
* - ``count``
348+
- ``**filters`` kwargs removed. Use ``range_key_condition``/``filter_condition`` instead.
349+
* - ``query``
350+
- ``conditional_operator`` and ``**filters`` kwargs removed. Use ``range_key_condition``/``filter_condition`` instead.
351+
* - ``scan``
352+
-
353+
- ``conditional_operator`` and ``**filters`` kwargs removed. Use ``filter_condition`` instead.
354+
- ``allow_rate_limited_scan_without_consumed_capacity`` was removed
327355

328-
+ Relatedly, the ``allow_rate_limited_scan_without_consumed_capacity`` option has been removed.
329-
* ``delete``: ``conditional_operator`` and ``**expected_values`` kwargs removed. Use ``condition`` instead.
330-
* ``update``: ``attributes``, ``conditional_operator`` and ``**expected_values`` kwargs removed. Use ``actions`` and ``condition`` instead.
331-
* ``save``: ``conditional_operator`` and ``**expected_values`` kwargs removed. Use ``condition`` instead.
332-
* ``count``: ``**filters`` kwargs removed. Use ``range_key_condition``/``filter_condition`` instead.
333-
* ``query``: ``conditional_operator`` and ``**filters`` kwargs removed. Use ``range_key_condition``/``filter_condition`` instead.
334-
* ``scan``: ``conditional_operator`` and ``**filters`` kwargs removed. Use ``filter_condition`` instead.
335356

336357
When upgrading, pay special attention to use of ``**filters`` and ``**expected_values``, as you'll need to check for arbitrary names that correspond to
337-
attribute names. Also keep an eye out for kwargs like ``user_id__eq=5`` or ``email__null=True``, which are no longer supported. If you're not already using
338-
``mypy`` to type check your code, it can help you catch cases like these.
358+
attribute names. Also keep an eye out for kwargs like ``user_id__eq=5`` or ``email__null=True``, which are no longer supported. A type check can help you catch cases like these.
339359

340360
New features in this release:
341361

docs/upgrading.rst

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
Upgrading
2+
=========
3+
4+
This file complements the :ref:`release notes <release_notes>`, focusing on helping safe upgrades of the library
5+
in production scenarios.
6+
7+
PynamoDB 5.x to 6.x
8+
-------------------
9+
10+
BinaryAttribute is no longer double base64-encoded
11+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12+
13+
See :ref:`upgrading_binary` for details.
14+
15+
PynamoDB 4.x to 5.x
16+
-------------------
17+
18+
Null checks enforced where they weren't previously
19+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20+
21+
Previously null errors (persisting ``None`` into an attribute defined as ``null=False``) were ignored inside **nested** map attributes, e.g.
22+
23+
.. code-block:: python
24+
25+
from pynamodb.models import Model
26+
from pynamodb.attributes import ListAttribute, MapAttribute, UnicodeAttribute
27+
28+
class Employee(MapAttribute):
29+
name = UnicodeAttribute(null=False)
30+
31+
class Team(Model):
32+
employees = ListAttribute(of=Employee)
33+
34+
35+
team = Team()
36+
team.employees = [Employee(name=None)]
37+
team.save() # this will raise now
38+
39+
40+
Now these will resulted in an :py:class:`~pynamodb.exceptions.AttributeNullError` being raised.
41+
42+
This was an unintentional breaking change introduced in 5.0.3.
43+
44+
Empty values are now meaningful
45+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
46+
47+
:py:class:`~pynamodb.attributes.UnicodeAttribute` and :py:class:`~pynamodb.attributes.BinaryAttribute` now support empty values (:pr:`830`)
48+
49+
In previous versions, assigning an empty value to would be akin to assigning ``None``: if the attribute was defined with ``null=True`` then it would be omitted, otherwise an error would be raised.
50+
DynamoDB `added support <https://aws.amazon.com/about-aws/whats-new/2020/05/amazon-dynamodb-now-supports-empty-values-for-non-key-string-and-binary-attributes-in-dynamodb-tables/>`_ empty values
51+
for String and Binary attributes. This release of PynamoDB starts treating empty values like any other values. If existing code unintentionally assigns empty values to StringAttribute or BinaryAttribute,
52+
this may be a breaking change: for example, the code may rely on the fact that in previous versions empty strings would be "read back" as ``None`` values when reloaded from the database.
53+
54+
No longer parsing date-time strings leniently
55+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
56+
57+
:py:class:`~pynamodb.attributes.UTCDateTimeAttribute` now strictly requires the date string format ``'%Y-%m-%dT%H:%M:%S.%f%z'`` to ensure proper ordering.
58+
PynamoDB has always written values with this format but previously would accept reading other formats.
59+
Items written using other formats must be rewritten before upgrading.
60+
61+
Removed functionality
62+
~~~~~~~~~~~~~~~~~~~~~
63+
64+
The following changes are breaking but are less likely to go unnoticed:
65+
66+
* Python 2 is no longer supported. Python 3.6 or greater is now required.
67+
* Table backup functionality (``Model.dump[s]`` and ``Model.load[s]``) has been removed.
68+
* ``Model.query`` no longer converts unsupported range key conditions into filter conditions.
69+
* Internal attribute type constants are replaced with their "short" DynamoDB version (:pr:`827`)
70+
* Remove ``ListAttribute.remove_indexes`` (added in v4.3.2) and document usage of remove for list elements (:pr:`838`)
71+
* Remove ``pynamodb.connection.util.pythonic`` (:pr:`753`) and (:pr:`865`)
72+
* Remove ``ModelContextManager`` class (:pr:`861`)
73+
74+
PynamoDB 3.x to 4.x
75+
-------------------
76+
77+
Requests Removal
78+
~~~~~~~~~~~~~~~~
79+
80+
Given that ``botocore`` has moved to using ``urllib3`` directly for making HTTP requests, we'll be doing the same (via ``botocore``). This means the following:
81+
82+
* The ``session_cls`` option is no longer supported.
83+
* The ``request_timeout_seconds`` parameter is no longer supported. ``connect_timeout_seconds`` and ``read_timeout_seconds`` are available instead.
84+
85+
+ Note that the timeouts for connection and read are now ``15`` and ``30`` seconds respectively. This represents a change from the previous ``60`` second combined ``requests`` timeout.
86+
* *Wrapped* exceptions (i.e ``exc.cause``) that were from ``requests.exceptions`` will now be comparable ones from ``botocore.exceptions`` instead.
87+
88+
Key attribute types must match table
89+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
90+
91+
The previous release would call `DescribeTable` to discover table metadata
92+
and would use the key types as defined in the DynamoDB table. This could obscure
93+
type mismatches e.g. where a table's hash key is a number (`N`) in DynamoDB,
94+
but defined in PynamoDB as a `UnicodeAttribute`.
95+
96+
With this release, we're always using the PynamoDB model's definition
97+
of all attributes including the key attributes.
98+
99+
Deprecation of old APIs
100+
~~~~~~~~~~~~~~~~~~~~~~~
101+
102+
Support for `Legacy Conditional Parameters <https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.html>`_ has been
103+
removed. See a complete list of affected ``Model`` methods below:
104+
105+
.. list-table::
106+
:widths: 10 90
107+
:header-rows: 1
108+
109+
* - Method
110+
- Changes
111+
* - ``update_item``
112+
- removed in favor of ``update``
113+
* - ``rate_limited_scan``
114+
- removed in favor of ``scan`` and ``ResultIterator``
115+
* - ``delete``
116+
- ``conditional_operator`` and ``**expected_values`` kwargs removed. Use ``condition`` instead.
117+
* - ``update``
118+
- ``attributes``, ``conditional_operator`` and ``**expected_values`` kwargs removed. Use ``actions`` and ``condition`` instead.
119+
* - ``save``
120+
- ``conditional_operator`` and ``**expected_values`` kwargs removed. Use ``condition`` instead.
121+
* - ``count``
122+
- ``**filters`` kwargs removed. Use ``range_key_condition``/``filter_condition`` instead.
123+
* - ``query``
124+
- ``conditional_operator`` and ``**filters`` kwargs removed. Use ``range_key_condition``/``filter_condition`` instead.
125+
* - ``scan``
126+
-
127+
- ``conditional_operator`` and ``**filters`` kwargs removed. Use ``filter_condition`` instead.
128+
- ``allow_rate_limited_scan_without_consumed_capacity`` was removed
129+
130+
131+
When upgrading, pay special attention to use of ``**filters`` and ``**expected_values``, as you'll need to check for arbitrary names that correspond to
132+
attribute names. Also keep an eye out for kwargs like ``user_id__eq=5`` or ``email__null=True``, which are no longer supported. A type check can help you catch cases like these.
133+
134+
PynamoDB 2.x to 3.x
135+
--------------------
136+
137+
Changes to UnicodeSetAttribute
138+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
139+
140+
See :ref:`upgrading_unicodeset` for details.

docs/upgrading_binary.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
:orphan:
2+
3+
.. _upgrading_binary:
4+
15
Upgrading Binary(Set)Attribute
26
==============================
37

docs/upgrading_unicodeset.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
:orphan:
2+
3+
.. _upgrading_unicodeset:
4+
15
Upgrading UnicodeSetAttribute
26
=============================
37

0 commit comments

Comments
 (0)