Skip to content

Commit

Permalink
Merge pull request #2 from Ousret/patch-1
Browse files Browse the repository at this point in the history
First batch of bug fixes after initial release 1.0.0
  • Loading branch information
Ousret authored Mar 16, 2020
2 parents 6673204 + 3103493 commit 1c775c9
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 11 deletions.
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,18 @@ No matters your religion, IMAP4 or HTTP, you should not worries about accessing
<img src="https://user-images.githubusercontent.com/9326700/76709832-32513600-6702-11ea-81cd-b68a7e85abb2.gif" alt="using kiss-headers from python interpreter"/>
</p>

### Installation
## Your support

Please ⭐ this repository if this project helped you!

### ✨ Installation

Whatever you like, use `Pipenv` or `pip`, it simply work. We are expecting you to have python 3.6+ installed.
```sh
pip install kiss-headers
```

### Usage
### 🍰 Usage

`parse_it()` method take `bytes`, `str`, `fp` or `dict` and give you back a `Headers` object.

Expand All @@ -50,10 +54,10 @@ headers = parse_it(response.headers)
'Content-Type' in headers # output: True
'Content_type' in headers # output: True

headers.content_type # output : application/json
str(headers.content_type) # output : application/json
'application/json' in headers.content_type # output: True

headers.content_type.charset # output : utf-8
str(headers.content_type.charset) # output : utf-8
```

## 👤 Contributing
Expand Down
43 changes: 37 additions & 6 deletions kiss_headers/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ def __init__(self, head: str, content: str):
if '=' in member:
key, value = tuple(member.split('=', maxsplit=1))

# avoid confusing base64 look alike single value for (key, value)
if value.count('=') == len(value) or len(value) == 0:
self._not_valued_attrs.append(member)
continue

if key not in self._valued_attrs:
self._valued_attrs[key] = value
else:
Expand Down Expand Up @@ -83,7 +88,7 @@ def __iter__(self) -> Iterator[Tuple[str, Optional[str]]]:

def __eq__(self, other) -> bool:
if isinstance(other, str):
return self.content == other
return self.content == other or other in self._not_valued_attrs
if isinstance(other, Header):
return self.normalized_name == other.normalized_name and self.content == other.content
raise TypeError('Cannot compare type {type_} to an Header. Use str or Header.'.format(type_=type(other)))
Expand All @@ -95,7 +100,7 @@ def __repr__(self) -> str:
return "{head}: {content}".format(head=self._head, content=self._content)

def __dir__(self) -> Iterable[str]:
return super().__dir__() + list(self._valued_attrs.keys())
return super().__dir__() + list(self._valued_attrs_normalized.keys())

@property
def attrs(self) -> List[str]:
Expand All @@ -116,6 +121,9 @@ def get(self, attr: str) -> Optional[str]:
return self._valued_attrs[attr]

def __getitem__(self, item: str) -> Union[str, List[str]]:
"""
This method will allow you to retrieve attribute value using the bracket syntax, list-like.
"""
normalized_item = Header.normalize_name(item)

if item in self._valued_attrs:
Expand All @@ -126,13 +134,17 @@ def __getitem__(self, item: str) -> Union[str, List[str]]:
raise KeyError(
"'{item}' attribute is not defined within '{header}' header.".format(item=item, header=self.name))

if isinstance(value, str):
if value.startswith('"') and value.endswith('"'):
return value[1:-1]
# Unquote value if necessary
if isinstance(value, str) and value.startswith('"') and value.endswith('"'):
return value[1:-1]

return value

def __getattr__(self, item) -> str:
"""
All the magic happen here, this method should be invoked when trying to call (not declared) properties.
For instance, calling self.charset should end up here and be replaced by self['charset'].
"""
if item not in self._valued_attrs and Header.normalize_name(item) not in self._valued_attrs_normalized:
raise AttributeError("'{item}' attribute is not defined within '{header}' header.".format(item=item, header=self.name))

Expand Down Expand Up @@ -176,6 +188,9 @@ class Headers:
connection: Header
keep_alive: Header

x_cache: Header
via: Header

accept: Header
accept_charset: Header
accept_encoding: Header
Expand Down Expand Up @@ -222,6 +237,16 @@ def __iter__(self):
for header in self._headers:
yield header

def to_dict(self) -> Dict[str, str]:
"""
Provide a dict output of current headers
"""
return dict(
[
(header.name, header.content) for header in self
]
)

def __eq__(self, other: 'Headers') -> bool:
if len(other) != len(self):
return False
Expand All @@ -235,8 +260,14 @@ def __eq__(self, other: 'Headers') -> bool:
def __len__(self) -> int:
return len(self._headers)

def __str__(self):
return self.__repr__()

def __repr__(self) -> str:
return '\n'.join([header.__repr__() for header in self])

def __getitem__(self, item: str) -> Union[Header, List[Header]]:
item = item.lower().replace('-', '_')
item = Header.normalize_name(item)

if item not in self:
raise KeyError("'{item}' header is not defined in headers.".format(item=item))
Expand Down
2 changes: 1 addition & 1 deletion kiss_headers/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
Expose version
"""

__version__ = "1.0.0"
__version__ = "1.0.1"
VERSION = __version__.split('.')

0 comments on commit 1c775c9

Please sign in to comment.