Search code examples
pythonduck-typing

Pythonic way to verify parameter is a sequence but not string


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


Solution

  • 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')