Skip to content

Instantly share code, notes, and snippets.

@henriquebastos
Last active August 29, 2015 14:05
Show Gist options
  • Save henriquebastos/9b491152ffc35790dd1a to your computer and use it in GitHub Desktop.
Save henriquebastos/9b491152ffc35790dd1a to your computer and use it in GitHub Desktop.
CSV helper for python-decouple
"""
Example:
>>> csv = Csv()
>>> csv('127.0.0.1, .localhost, .herokuapp.com')
['127.0.0.1', '.localhost', '.herokuapp.com']
>>> csv = Csv(int)
>>> csv('1,2,3,4,5')
[1, 2, 3, 4, 5]
>>> csv = Csv(cast=lambda s: s.upper(), delimiter='\t', strip=' %*')
>>> csv('%virtual_env%\t *important stuff*\t trailing spaces ')
['VIRTUAL_ENV', 'IMPORTANT STUFF', 'TRAILING SPACES']
"""
def __init__(self, cast=text_type, delimiter=', \t\r\n', strip=string.whitespace):
"""
Parameters:
cast -- callable that transforms the item just before it's added to the list.
delimiter -- string of delimiters chars passed to shlex.
strip -- string of non-relevant characters to be passed to str.strip after the split.
"""
self.cast = cast
self.delimiter = delimiter
self.strip = strip
def __call__(self, value):
"""The actual transformation"""
transform = lambda s: self.cast(s.strip(self.strip))
splitter = shlex(value, posix=True)
splitter.whitespace = self.delimiter
splitter.whitespace_split = True
return [transform(s) for s in splitter]
@osantana
Copy link

Tem um problema com quoted parse... rolaria algo como foo,"bar,baz", "qux" -> ["foo", "bar,baz", "qux"]
seria melhor o def __init__(..., strip=string.whitespace): (que é o default do str.strip())

@osantana
Copy link

Pode ser interessante usar o módulo shlex para isso.

>>> splitter = shlex.shlex("""foo, bar, 'baz,qux',doo""", posix=True)
>>> splitter.whitespace = ","
>>> splitter.whitespace_split = True
>>> print [part.strip(string.whitespace) for part in splitter]
['foo', 'bar', 'baz,qux', 'doo']

@henriquebastos
Copy link
Author

Muito maneiro, @osantana! Fiz uma nova versão com o shlex e acho q ficou redondo.

Extrapolei uns testes para garantir o quoted parse e funcionou legal.

csv = Csv()
assert ['foo', 'bar, baz', 'qux'] == csv(""" foo ,'bar, baz', 'qux'""")
assert ['foo', 'bar, baz', 'qux'] == csv(''' foo ,"bar, baz", "qux"''')
assert ['foo', "'bar, baz'", "'qux"] == csv(''' foo ,"'bar, baz'", "'qux"''')
assert ['foo', '"bar, baz"', '"qux'] == csv(""" foo ,'"bar, baz"', '"qux'""")

@henriquebastos
Copy link
Author

Só acho que agora tem uma interseção indesejada entre o delimiter e o strip... acho que o delimiter padrão deve ser só o , mesmo.

@osantana
Copy link

Também acho que usar só ',' seja melhor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment