summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnssi Kääriäinen <akaariai@gmail.com>2012-10-03 18:53:40 +0300
committerAnssi Kääriäinen <akaariai@gmail.com>2012-10-10 01:15:29 +0300
commitb625e8272bd41714c838cfda3fb54e1f5177f009 (patch)
tree7edc4b667914e12eaf4b2d74c22cdcb4e024d83e
parenta8b1861fc4d0a48b4879af803bba094eef145017 (diff)
Moved F() '&' and '|' to .bitand() and .bitor()
Done for consistency with Q() expressions and QuerySet combining. This will allow usage of '&' and '|' as boolean logical operators in the future. Refs #16211.
-rw-r--r--django/db/models/expressions.py30
-rw-r--r--docs/releases/1.5.txt6
-rw-r--r--docs/topics/db/queries.txt12
-rw-r--r--tests/regressiontests/expressions_regress/tests.py18
4 files changed, 43 insertions, 23 deletions
diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py
index 639ef6ee10..30c44bacde 100644
--- a/django/db/models/expressions.py
+++ b/django/db/models/expressions.py
@@ -14,9 +14,11 @@ class ExpressionNode(tree.Node):
# because it can be used in strings that also
# have parameter substitution.
- # Bitwise operators
- AND = '&'
- OR = '|'
+ # Bitwise operators - note that these are generated by .bitand()
+ # and .bitor(), the '&' and '|' are reserved for boolean operator
+ # usage.
+ BITAND = '&'
+ BITOR = '|'
def __init__(self, children=None, connector=None, negated=False):
if children is not None and len(children) > 1 and connector is None:
@@ -66,10 +68,20 @@ class ExpressionNode(tree.Node):
return self._combine(other, self.MOD, False)
def __and__(self, other):
- return self._combine(other, self.AND, False)
+ raise NotImplementedError(
+ "Use .bitand() and .bitor() for bitwise logical operations."
+ )
+
+ def bitand(self, other):
+ return self._combine(other, self.BITAND, False)
def __or__(self, other):
- return self._combine(other, self.OR, False)
+ raise NotImplementedError(
+ "Use .bitand() and .bitor() for bitwise logical operations."
+ )
+
+ def bitor(self, other):
+ return self._combine(other, self.BITOR, False)
def __radd__(self, other):
return self._combine(other, self.ADD, True)
@@ -88,10 +100,14 @@ class ExpressionNode(tree.Node):
return self._combine(other, self.MOD, True)
def __rand__(self, other):
- return self._combine(other, self.AND, True)
+ raise NotImplementedError(
+ "Use .bitand() and .bitor() for bitwise logical operations."
+ )
def __ror__(self, other):
- return self._combine(other, self.OR, True)
+ raise NotImplementedError(
+ "Use .bitand() and .bitor() for bitwise logical operations."
+ )
def prepare_database_save(self, unused):
return self
diff --git a/docs/releases/1.5.txt b/docs/releases/1.5.txt
index 78ba77308b..263392fdc7 100644
--- a/docs/releases/1.5.txt
+++ b/docs/releases/1.5.txt
@@ -438,6 +438,12 @@ Miscellaneous
needs. The new default value is `0666` (octal) and the current umask value
is first masked out.
+* The :ref:`F() expressions <query-expressions>` supported bitwise operators by
+ ``&`` and ``|``. These operators are now available using ``.bitand()`` and
+ ``.bitor()`` instead. The removal of ``&`` and ``|`` was done to be consistent with
+ :ref:`Q() expressions <complex-lookups-with-q>` and ``QuerySet`` combining where
+ the operators are used as boolean AND and OR operators.
+
Features deprecated in 1.5
==========================
diff --git a/docs/topics/db/queries.txt b/docs/topics/db/queries.txt
index fa98c91739..543edf6280 100644
--- a/docs/topics/db/queries.txt
+++ b/docs/topics/db/queries.txt
@@ -640,6 +640,18 @@ that were modified more than 3 days after they were published::
>>> from datetime import timedelta
>>> Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))
+.. versionadded:: 1.5
+ ``.bitand()`` and ``.bitor()``
+
+The ``F()`` objects now support bitwise operations by ``.bitand()`` and
+``.bitor()``, for example::
+
+ >>> F('somefield').bitand(16)
+
+.. versionchanged:: 1.5
+ The previously undocumented operators ``&`` and ``|`` no longer produce
+ bitwise operations, use ``.bitand()`` and ``.bitor()`` instead.
+
The pk lookup shortcut
----------------------
diff --git a/tests/regressiontests/expressions_regress/tests.py b/tests/regressiontests/expressions_regress/tests.py
index 80ddfadbe7..06d97d2b32 100644
--- a/tests/regressiontests/expressions_regress/tests.py
+++ b/tests/regressiontests/expressions_regress/tests.py
@@ -128,7 +128,7 @@ class ExpressionOperatorTests(TestCase):
def test_lefthand_bitwise_and(self):
# LH Bitwise ands on integers
- Number.objects.filter(pk=self.n.pk).update(integer=F('integer') & 56)
+ Number.objects.filter(pk=self.n.pk).update(integer=F('integer').bitand(56))
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 40)
self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3))
@@ -136,7 +136,7 @@ class ExpressionOperatorTests(TestCase):
@skipUnlessDBFeature('supports_bitwise_or')
def test_lefthand_bitwise_or(self):
# LH Bitwise or on integers
- Number.objects.filter(pk=self.n.pk).update(integer=F('integer') | 48)
+ Number.objects.filter(pk=self.n.pk).update(integer=F('integer').bitor(48))
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 58)
self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3))
@@ -181,20 +181,6 @@ class ExpressionOperatorTests(TestCase):
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 27)
self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3))
- def test_right_hand_bitwise_and(self):
- # RH Bitwise ands on integers
- Number.objects.filter(pk=self.n.pk).update(integer=15 & F('integer'))
-
- self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 10)
- self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3))
-
- @skipUnlessDBFeature('supports_bitwise_or')
- def test_right_hand_bitwise_or(self):
- # RH Bitwise or on integers
- Number.objects.filter(pk=self.n.pk).update(integer=15 | F('integer'))
-
- self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 47)
- self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3))
class FTimeDeltaTests(TestCase):