Skip to content

Commit

Permalink
Make all compounds functions
Browse files Browse the repository at this point in the history
This changes the public interface but this is good:

This solves a naming issue (BatchPutItem was a function named like a
class to be consistent with BatchGetItemIterator. BatchGetItemIterator
was a class only because of an implementation detail)

Conceptually, it's always been clear that compounds receive the
connection as an argument and therefore were already *used as* functions.

Now they *are* functions.
  • Loading branch information
jacquev6 committed Apr 26, 2015
1 parent 8dda070 commit a1b58e4
Show file tree
Hide file tree
Showing 39 changed files with 294 additions and 350 deletions.
8 changes: 4 additions & 4 deletions LowVoltage/actions/batch_get_item.py
Expand Up @@ -17,7 +17,7 @@
Note that responses are in an undefined order.
See also the :class:`.BatchGetItemIterator` compound. And :ref:`actions-vs-compounds` in the user guide.
See also the :func:`.iterate_batch_get_item` compound. And :ref:`actions-vs-compounds` in the user guide.
"""

import LowVoltage as _lv
Expand Down Expand Up @@ -75,7 +75,7 @@ def unprocessed_keys(self):
"""
Keys that were not processed during this request. If not None, you should give this back to the constructor of a subsequent :class:`BatchGetItem`.
The :class:`.BatchGetItemIterator` compound processes those for you.
The :func:`.iterate_batch_get_item` compound processes those for you.
:type: ``None`` or exactly as returned by DynamoDB
"""
Expand Down Expand Up @@ -418,15 +418,15 @@ def test_get_unexisting_keys(self):
self.assertEqual(r.unprocessed_keys, {})

def test_get_without_unprocessed_keys(self):
_lv.BatchPutItem(self.connection, "Aaa", [{"h": unicode(i)} for i in range(100)])
_lv.batch_put_item(self.connection, "Aaa", [{"h": unicode(i)} for i in range(100)])

r = self.connection(_lv.BatchGetItem().table("Aaa").keys({"h": unicode(i)} for i in range(100)))

self.assertEqual(r.unprocessed_keys, {})
self.assertEqual(len(r.responses["Aaa"]), 100)

def test_get_with_unprocessed_keys(self):
_lv.BatchPutItem(self.connection, "Aaa", [{"h": unicode(i), "xs": "x" * 300000} for i in range(100)]) # 300kB items ensure a single BatchGetItem will return at most 55 items
_lv.batch_put_item(self.connection, "Aaa", [{"h": unicode(i), "xs": "x" * 300000} for i in range(100)]) # 300kB items ensure a single BatchGetItem will return at most 55 items

r1 = self.connection(_lv.BatchGetItem().table("Aaa").keys({"h": unicode(i)} for i in range(100)))

Expand Down
4 changes: 2 additions & 2 deletions LowVoltage/actions/batch_write_item.py
Expand Up @@ -10,7 +10,7 @@
... )
<LowVoltage.actions.batch_write_item.BatchWriteItemResponse ...>
See also the :func:`.BatchPutItem` and :func:`.BatchDeleteItem` compounds. And :ref:`actions-vs-compounds` in the user guide.
See also the :func:`.batch_put_item` and :func:`.batch_delete_item` compounds. And :ref:`actions-vs-compounds` in the user guide.
"""

import LowVoltage as _lv
Expand Down Expand Up @@ -65,7 +65,7 @@ def unprocessed_items(self):
"""
Items that were not processed during this request. If not None, you should give this back to the constructor of a subsequent :class:`BatchWriteItem`.
The :func:`.BatchPutItem` and :func:`.BatchDeleteItem` compounds process those for you.
The :func:`.batch_put_item` and :func:`.batch_delete_item` compounds process those for you.
:type: ``None`` or exactly as returned by DynamoDB
"""
Expand Down
18 changes: 9 additions & 9 deletions LowVoltage/actions/create_table.py
Expand Up @@ -22,22 +22,22 @@
>>> r.table_description.table_status
u'CREATING'
Note that you can use the :func:`.WaitForTableActivation` compound to poll the table status until it's usable. See :ref:`actions-vs-compounds` in the user guide.
Note that you can use the :func:`.wait_for_table_activation` compound to poll the table status until it's usable. See :ref:`actions-vs-compounds` in the user guide.
.. testcleanup::
WaitForTableActivation(connection, table)
WaitForTableActivation(connection, table2)
WaitForTableActivation(connection, table3)
WaitForTableActivation(connection, table4)
wait_for_table_activation(connection, table)
wait_for_table_activation(connection, table2)
wait_for_table_activation(connection, table3)
wait_for_table_activation(connection, table4)
connection(DeleteTable(table))
connection(DeleteTable(table2))
connection(DeleteTable(table3))
connection(DeleteTable(table4))
WaitForTableDeletion(connection, table)
WaitForTableDeletion(connection, table2)
WaitForTableDeletion(connection, table3)
WaitForTableDeletion(connection, table4)
wait_for_table_deletion(connection, table)
wait_for_table_deletion(connection, table2)
wait_for_table_deletion(connection, table3)
wait_for_table_deletion(connection, table4)
"""

import datetime
Expand Down
6 changes: 3 additions & 3 deletions LowVoltage/actions/delete_table.py
Expand Up @@ -9,19 +9,19 @@
table = "LowVoltage.Tests.Doc.DeleteTable.1"
connection(CreateTable(table).hash_key("h", STRING).provisioned_throughput(1, 1))
WaitForTableActivation(connection, table)
wait_for_table_activation(connection, table)
>>> r = connection(DeleteTable(table))
>>> r
<LowVoltage.actions.delete_table.DeleteTableResponse object at ...>
>>> r.table_description.table_status
u'DELETING'
Note that you can use the :func:`.WaitForTableDeletion` compound to poll the table status until it's deleted. See :ref:`actions-vs-compounds` in the user guide.
Note that you can use the :func:`.wait_for_table_deletion` compound to poll the table status until it's deleted. See :ref:`actions-vs-compounds` in the user guide.
.. testcleanup::
WaitForTableDeletion(connection, table)
wait_for_table_deletion(connection, table)
"""

import datetime
Expand Down
6 changes: 3 additions & 3 deletions LowVoltage/actions/list_tables.py
Expand Up @@ -11,7 +11,7 @@
>>> r.table_names
[u'LowVoltage.Tests.Doc.1', u'LowVoltage.Tests.Doc.2']
See also the :class:`.ListTablesIterator` compound. And :ref:`actions-vs-compounds` in the user guide.
See also the :func:`.iterate_list_tables` compound. And :ref:`actions-vs-compounds` in the user guide.
"""

import LowVoltage as _lv
Expand Down Expand Up @@ -40,7 +40,7 @@ def last_evaluated_table_name(self):
The name of the last table that was considered during the request.
If not None, you should give it to :meth:`~ListTables.exclusive_start_table_name` in a subsequent :class:`ListTables`.
The :class:`.ListTablesIterator` compound does that for you.
The :func:`.iterate_list_tables` compound does that for you.
:type: ``None`` or string
"""
Expand Down Expand Up @@ -95,7 +95,7 @@ def exclusive_start_table_name(self, table_name):
Set ExclusiveStartTableName. The response will contains tables that are after this one.
Typically the :attr:`~ListTablesResponse.last_evaluated_table_name` of a previous response.
The :class:`.ListTablesIterator` compound does that for you.
The :func:`.iterate_list_tables` compound does that for you.
>>> connection(
... ListTables()
Expand Down
6 changes: 3 additions & 3 deletions LowVoltage/actions/query.py
Expand Up @@ -13,7 +13,7 @@
>>> connection(Query(table2).key_eq("h", 42)).items
[{u'h': 42, u'r1': 0, u'r2': 10}, {u'h': 42, u'r1': 1, u'r2': 9}, {u'h': 42, u'r1': 2, u'r2': 8}, {u'h': 42, u'r1': 3, u'r2': 7}, {u'h': 42, u'r1': 4, u'r2': 6}, {u'h': 42, u'r1': 5, u'r2': 5}, {u'h': 42, u'r1': 6}, {u'h': 42, u'r1': 7}, {u'h': 42, u'r1': 8}, {u'h': 42, u'r1': 9}]
See also the :class:`.QueryIterator` compound. And :ref:`actions-vs-compounds` in the user guide.
See also the :func:`.iterate_query` compound. And :ref:`actions-vs-compounds` in the user guide.
"""

import LowVoltage as _lv
Expand Down Expand Up @@ -91,7 +91,7 @@ def last_evaluated_key(self):
"""
The key of the last item evaluated by the query. If not None, it should be given to :meth:`~Query.exclusive_start_key` is a subsequent :class:`Query`.
The :class:`.QueryIterator` compound does that for you.
The :func:`.iterate_query` compound does that for you.
:type: ``None`` or dict
"""
Expand Down Expand Up @@ -245,7 +245,7 @@ def key_between(self, name, lo, hi):
@proxy("Query")
def exclusive_start_key(self, key):
"""
The :class:`.QueryIterator` compound does that for you.
The :func:`.iterate_query` compound does that for you.
>>> r = connection(
... Query(table2)
Expand Down
8 changes: 4 additions & 4 deletions LowVoltage/actions/scan.py
Expand Up @@ -15,7 +15,7 @@
Note that items are returned in an undefined order.
See also the :class:`.ScanIterator` compound. And :ref:`actions-vs-compounds` in the user guide.
See also the :func:`.iterate_scan` compound. And :ref:`actions-vs-compounds` in the user guide.
"""

import LowVoltage as _lv
Expand Down Expand Up @@ -92,7 +92,7 @@ def last_evaluated_key(self):
"""
The key of the last item evaluated by the scan. If not None, it should be given to :meth:`~Scan.exclusive_start_key` is a subsequent :class:`Scan`.
The :class:`.ScanIterator` compound does that for you.
The :func:`.iterate_scan` compound does that for you.
:type: ``None`` or dict
"""
Expand Down Expand Up @@ -151,7 +151,7 @@ def segment(self, segment, total_segments):
Items will be partitioned in ``total_segments`` segments of approximately the same size,
ans only the items of the ``segment``-th segment will be returned in this request.
:meth:`.ScanIterator.parallelize` does that for you.
:func:`.parallelize_scan` does that for you.
>>> connection(
... Scan(table)
Expand All @@ -172,7 +172,7 @@ def segment(self, segment, total_segments):
@proxy("Scan")
def exclusive_start_key(self, key):
"""
The :class:`.ScanIterator` compound does that for you.
The :func:`.iterate_scan` compound does that for you.
>>> r = connection(
... Scan(table)
Expand Down
28 changes: 14 additions & 14 deletions LowVoltage/actions/update_table.py
Expand Up @@ -21,10 +21,10 @@
.global_secondary_index("gsi").hash_key("hh", STRING).range_key("rr", NUMBER).provisioned_throughput(1, 1).project_all()
)
connection(CreateTable(table4).hash_key("h", STRING).provisioned_throughput(1, 1))
WaitForTableActivation(connection, table)
WaitForTableActivation(connection, table2)
WaitForTableActivation(connection, table3)
WaitForTableActivation(connection, table4)
wait_for_table_activation(connection, table)
wait_for_table_activation(connection, table2)
wait_for_table_activation(connection, table3)
wait_for_table_activation(connection, table4)
>>> r = connection(
... UpdateTable(table)
Expand All @@ -35,22 +35,22 @@
>>> r.table_description.table_status
u'UPDATING'
Note that you can use the :func:`.WaitForTableActivation` compound to poll the table status until it's updated. See :ref:`actions-vs-compounds` in the user guide.
Note that you can use the :func:`.wait_for_table_activation` compound to poll the table status until it's updated. See :ref:`actions-vs-compounds` in the user guide.
.. testcleanup::
WaitForTableActivation(connection, table)
WaitForTableActivation(connection, table2)
WaitForTableActivation(connection, table3)
WaitForTableActivation(connection, table4)
wait_for_table_activation(connection, table)
wait_for_table_activation(connection, table2)
wait_for_table_activation(connection, table3)
wait_for_table_activation(connection, table4)
connection(DeleteTable(table))
connection(DeleteTable(table2))
connection(DeleteTable(table3))
connection(DeleteTable(table4))
WaitForTableDeletion(connection, table)
WaitForTableDeletion(connection, table2)
WaitForTableDeletion(connection, table3)
WaitForTableDeletion(connection, table4)
wait_for_table_deletion(connection, table)
wait_for_table_deletion(connection, table2)
wait_for_table_deletion(connection, table3)
wait_for_table_deletion(connection, table4)
"""

import datetime
Expand Down Expand Up @@ -582,7 +582,7 @@ def test_delete_and_create_gsi(self):
r = self.connection(_lv.UpdateTable("Aaa").delete_global_secondary_index("the_gsi"))
self.assertEqual(r.table_description.global_secondary_indexes[0].index_status, "DELETING")

_lv.WaitForTableActivation(self.connection, "Aaa")
_lv.wait_for_table_activation(self.connection, "Aaa")

r = self.connection(_lv.DescribeTable("Aaa"))
self.assertEqual(r.table.global_secondary_indexes, None)
Expand Down
16 changes: 8 additions & 8 deletions LowVoltage/compounds/__init__.py
Expand Up @@ -2,11 +2,11 @@

# Copyright 2014-2015 Vincent Jacques <vincent@vincent-jacques.net>

from .batch_delete_item import BatchDeleteItem
from .batch_get_item_iterator import BatchGetItemIterator
from .batch_put_item import BatchPutItem
from .list_tables_iterator import ListTablesIterator
from .query_iterator import QueryIterator
from .scan_iterator import ScanIterator
from .wait_for_table_activation import WaitForTableActivation
from .wait_for_table_deletion import WaitForTableDeletion
from .batch_delete_item import batch_delete_item
from .iterate_batch_get_item import iterate_batch_get_item
from .batch_put_item import batch_put_item
from .iterate_list_tables import iterate_list_tables
from .iterate_query import iterate_query
from .iterate_scan import iterate_scan, parallelize_scan
from .wait_for_table_activation import wait_for_table_activation
from .wait_for_table_deletion import wait_for_table_deletion
22 changes: 11 additions & 11 deletions LowVoltage/compounds/batch_delete_item.py
Expand Up @@ -8,12 +8,12 @@


@variadic(dict)
def BatchDeleteItem(connection, table, keys):
def batch_delete_item(connection, table, keys):
"""
Make as many :class:`.BatchWriteItem` actions as needed to delete all specified keys.
Including processing :attr:`.BatchWriteItemResponse.unprocessed_items`.
>>> BatchDeleteItem(
>>> batch_delete_item(
... connection,
... table,
... {"h": 0},
Expand All @@ -30,7 +30,7 @@ def BatchDeleteItem(connection, table, keys):
if isinstance(r.unprocessed_items, dict) and table in r.unprocessed_items:
unprocessed_items += r.unprocessed_items[table]

# @todo Maybe wait a bit before retrying unprocessed items? Same in BatchPutItem and BatchGetItemIterator.
# @todo Maybe wait a bit before retrying unprocessed items? Same in batch_put_item and iterate_batch_get_item.
# @todo In the first loop, maybe wait a bit before next request if we get unprocessed items? Might not be a good idea.

while len(unprocessed_items) != 0:
Expand All @@ -46,7 +46,7 @@ def setUp(self):
self.connection = self.mocks.create("connection")

def test_no_keys(self):
BatchDeleteItem(self.connection.object, "Aaa", [])
batch_delete_item(self.connection.object, "Aaa", [])

def test_one_page(self):
self.connection.expect._call_.withArguments(
Expand All @@ -55,7 +55,7 @@ def test_one_page(self):
_lv.BatchWriteItemResponse()
)

BatchDeleteItem(self.connection.object, "Aaa", {"h": u"a"}, {"h": u"b"})
batch_delete_item(self.connection.object, "Aaa", {"h": u"a"}, {"h": u"b"})

def test_several_pages(self):
self.connection.expect._call_.withArguments(
Expand All @@ -74,7 +74,7 @@ def test_several_pages(self):
_lv.BatchWriteItemResponse()
)

BatchDeleteItem(self.connection.object, "Aaa", ({"h": i} for i in range(60)))
batch_delete_item(self.connection.object, "Aaa", ({"h": i} for i in range(60)))

def test_one_unprocessed_item(self):
self.connection.expect._call_.withArguments(
Expand All @@ -88,7 +88,7 @@ def test_one_unprocessed_item(self):
_lv.BatchWriteItemResponse()
)

BatchDeleteItem(self.connection.object, "Aaa", {"h": u"a"}, {"h": u"b"})
batch_delete_item(self.connection.object, "Aaa", {"h": u"a"}, {"h": u"b"})

def test_several_pages_of_unprocessed_item(self):
self.connection.expect._call_.withArguments(
Expand All @@ -112,7 +112,7 @@ def test_several_pages_of_unprocessed_item(self):
_lv.BatchWriteItemResponse()
)

BatchDeleteItem(self.connection.object, "Aaa", [{"h": i} for i in range(35)])
batch_delete_item(self.connection.object, "Aaa", [{"h": i} for i in range(35)])


class BatchDeleteItemLocalIntegTests(_tst.LocalIntegTestsWithTableH):
Expand All @@ -121,8 +121,8 @@ def key(self, i):

def setUp(self):
super(BatchDeleteItemLocalIntegTests, self).setUp()
_lv.BatchPutItem(self.connection, "Aaa", [{"h": self.key(i)} for i in range(100)])
_lv.batch_put_item(self.connection, "Aaa", [{"h": self.key(i)} for i in range(100)])

def test(self):
_lv.BatchDeleteItem(self.connection, "Aaa", [{"h": self.key(i)} for i in range(100)])
self.assertEqual([], list(_lv.ScanIterator(self.connection, _lv.Scan("Aaa"))))
_lv.batch_delete_item(self.connection, "Aaa", [{"h": self.key(i)} for i in range(100)])
self.assertEqual([], list(_lv.iterate_scan(self.connection, _lv.Scan("Aaa"))))

0 comments on commit a1b58e4

Please sign in to comment.