I have a function that gets a list of DB tables as parameter, and returns a command string to be executed on these tables, e.g.:
pg_dump( file='/tmp/dump.sql',
tables=('stack', 'overflow'),
port=5434
name=europe)
Should return something like:
pg_dump -t stack -t overflow -f /tmp/dump.sql -p 5434 europe
This is done using tables_string='-t '+' -t '.join(tables)
.
The fun begins when the function is called with: tables=('stackoverflow')
(a string) instead of tables=('stackoverflow',)
(a tuple), which yields:
pg_dump -t s -t t -t a -t c -t k -t o -t v -t e -t r -t f -t l -t o -t w
-f /tmp/dump.sql -p 5434 europe
Because the string itself is being iterated.
This SO question suggests using asserts on the type, but I'm not sure it's Pythonic enough because it breaks the duck-type convention.
Any insights?
Adam
Asserting the type seems appropriate in this case - handling a common misuse that seems legal because of duck typing.
Another way to handle this common case would be to test for string and handle it correctly as a special case.
Finally, you could encourage passing the table names as positional parameters which would make this scenario less likely:
def pg_dump(*tables, **kwargs):
file = kwargs['file']
port = kwargs['port']
name = kwargs['name']
...
pg_dump('stack', 'overflow', file='/tmp/dump.sql', port=5434, name='europe')
You can use ABCs to assert that an object is iterable but not a string:
from types import StringType
from collections import Iterable
assert isinstance(x, Iterable) and not isinstance(x, StringType)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With