Runnable KeyValueArgType.tokenize doctest

This commit is contained in:
Jakub Roztocil 2019-09-17 09:07:12 +02:00
parent 0df4db7bb4
commit 37fa67cd3c
2 changed files with 29 additions and 25 deletions

View File

@ -2,6 +2,7 @@ import argparse
import getpass import getpass
import os import os
import sys import sys
from typing import Union, List
from httpie.cli.constants import SEPARATOR_CREDENTIALS from httpie.cli.constants import SEPARATOR_CREDENTIALS
from httpie.sessions import VALID_SESSION_NAME_PATTERN from httpie.sessions import VALID_SESSION_NAME_PATTERN
@ -39,11 +40,14 @@ class SessionNameValidator:
class Escaped(str): class Escaped(str):
"""Represents an escaped character.""" """Represents an escaped character."""
def __repr__(self):
return f"Escaped({repr(str(self))})"
class KeyValueArgType: class KeyValueArgType:
"""A key-value pair argument type used with `argparse`. """A key-value pair argument type used with `argparse`.
Parses a key-value arg and constructs a `KeyValuArge` instance. Parses a key-value arg and constructs a `KeyValueArg` instance.
Used for headers, form data, and other key-value pair types. Used for headers, form data, and other key-value pair types.
""" """
@ -65,29 +69,7 @@ class KeyValueArgType:
as well (r'\\'). as well (r'\\').
""" """
tokens = self.tokenize(string)
def tokenize(string):
r"""Tokenize `string`. There are only two token types - strings
and escaped characters:
tokenize(r'foo\=bar\\baz')
=> ['foo', Escaped('='), 'bar', Escaped('\\'), 'baz']
"""
tokens = ['']
characters = iter(string)
for char in characters:
if char == '\\':
char = next(characters, '')
if char not in self.special_characters:
tokens[-1] += '\\' + char
else:
tokens.extend([Escaped(char), ''])
else:
tokens[-1] += char
return tokens
tokens = tokenize(string)
# Sorting by length ensures that the longest one will be # Sorting by length ensures that the longest one will be
# chosen as it will overwrite any shorter ones starting # chosen as it will overwrite any shorter ones starting
@ -126,6 +108,28 @@ class KeyValueArgType:
return self.key_value_class( return self.key_value_class(
key=key, value=value, sep=sep, orig=string) key=key, value=value, sep=sep, orig=string)
def tokenize(self, s: str) -> List[Union[str, Escaped]]:
r"""Tokenize the raw arg string
There are only two token types - strings and escaped characters:
>>> KeyValueArgType('=').tokenize(r'foo\=bar\\baz')
['foo', Escaped('='), 'bar', Escaped('\\'), 'baz']
"""
tokens = ['']
characters = iter(s)
for char in characters:
if char == '\\':
char = next(characters, '')
if char not in self.special_characters:
tokens[-1] += '\\' + char
else:
tokens.extend([Escaped(char), ''])
else:
tokens[-1] += char
return tokens
class AuthCredentials(KeyValueArg): class AuthCredentials(KeyValueArg):
"""Represents parsed credentials.""" """Represents parsed credentials."""

View File

@ -140,7 +140,7 @@ def process_data_raw_json_embed_arg(arg: KeyValueArg) -> JSONType:
return value return value
def load_text_file(item) -> str: def load_text_file(item: KeyValueArg) -> str:
path = item.value path = item.value
try: try:
with open(os.path.expanduser(path), 'rb') as f: with open(os.path.expanduser(path), 'rb') as f: