From dfa38728d43583df4391301c959bb23b6efcffb8 Mon Sep 17 00:00:00 2001 From: TAHRI Ahmed R Date: Mon, 16 Mar 2020 13:58:38 +0100 Subject: [PATCH 01/11] :bug: Avoid confusing base64 alike value for (key, value) --- kiss_headers/utils.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kiss_headers/utils.py b/kiss_headers/utils.py index c0a6d30..1f8cc17 100644 --- a/kiss_headers/utils.py +++ b/kiss_headers/utils.py @@ -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: From 773500c80fa432145d60fd1ca772d1a35fdc2b17 Mon Sep 17 00:00:00 2001 From: TAHRI Ahmed R Date: Mon, 16 Mar 2020 14:00:08 +0100 Subject: [PATCH 02/11] :bug: Say it is equal if item:str in adjective/attribute headers.header == 'application/json' may say it is false. So now it is true even if content has charset or whatnot. --- kiss_headers/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kiss_headers/utils.py b/kiss_headers/utils.py index 1f8cc17..dc42311 100644 --- a/kiss_headers/utils.py +++ b/kiss_headers/utils.py @@ -88,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 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))) From 123d1b8c3e5c48401b44492d5275797f9abfd7ce Mon Sep 17 00:00:00 2001 From: TAHRI Ahmed R Date: Mon, 16 Mar 2020 14:00:48 +0100 Subject: [PATCH 03/11] :bug: Fix __dir__ for Header class, output was not normalized on attrs --- kiss_headers/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kiss_headers/utils.py b/kiss_headers/utils.py index dc42311..2fe88cd 100644 --- a/kiss_headers/utils.py +++ b/kiss_headers/utils.py @@ -100,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]: From 776d482461547d4ff3c6e10400d2faa40d202273 Mon Sep 17 00:00:00 2001 From: TAHRI Ahmed R Date: Mon, 16 Mar 2020 14:01:36 +0100 Subject: [PATCH 04/11] :sparkle: Add to_dict() method in Headers class --- kiss_headers/utils.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/kiss_headers/utils.py b/kiss_headers/utils.py index 2fe88cd..b732289 100644 --- a/kiss_headers/utils.py +++ b/kiss_headers/utils.py @@ -227,6 +227,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 From 35e4e1806c986811bca474188e47ad425b7e5b86 Mon Sep 17 00:00:00 2001 From: TAHRI Ahmed R Date: Mon, 16 Mar 2020 14:02:28 +0100 Subject: [PATCH 05/11] :sparkle: Add __str__ and __repr__ to Headers class --- kiss_headers/utils.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kiss_headers/utils.py b/kiss_headers/utils.py index b732289..f0aa2a7 100644 --- a/kiss_headers/utils.py +++ b/kiss_headers/utils.py @@ -250,6 +250,12 @@ 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('-', '_') From 7171c91ba121c0858d57babfe1f7047630867cde Mon Sep 17 00:00:00 2001 From: TAHRI Ahmed R Date: Mon, 16 Mar 2020 14:03:10 +0100 Subject: [PATCH 06/11] :pencil: Add pydocs on getitem and getattr --- kiss_headers/utils.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kiss_headers/utils.py b/kiss_headers/utils.py index f0aa2a7..81644a6 100644 --- a/kiss_headers/utils.py +++ b/kiss_headers/utils.py @@ -121,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: @@ -138,6 +141,10 @@ def __getitem__(self, item: str) -> Union[str, List[str]]: 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)) From b6c0dfe6b3ca1141e6bd9d29f03f548b397b0294 Mon Sep 17 00:00:00 2001 From: TAHRI Ahmed R Date: Mon, 16 Mar 2020 14:03:40 +0100 Subject: [PATCH 07/11] :sparkle: Add x_cache and via hint completion for Headers --- kiss_headers/utils.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kiss_headers/utils.py b/kiss_headers/utils.py index 81644a6..e386f12 100644 --- a/kiss_headers/utils.py +++ b/kiss_headers/utils.py @@ -188,6 +188,9 @@ class Headers: connection: Header keep_alive: Header + x_cache: Header + via: Header + accept: Header accept_charset: Header accept_encoding: Header From 46f984915c6b79957f673820d960b1469f51886c Mon Sep 17 00:00:00 2001 From: TAHRI Ahmed R Date: Mon, 16 Mar 2020 14:04:15 +0100 Subject: [PATCH 08/11] :art: Minors styles revisions --- kiss_headers/utils.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kiss_headers/utils.py b/kiss_headers/utils.py index e386f12..aaf85ed 100644 --- a/kiss_headers/utils.py +++ b/kiss_headers/utils.py @@ -134,9 +134,9 @@ 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 @@ -267,7 +267,7 @@ 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)) From c3e8fcbb2ef5a48bab3a8f831b994a3e6691156d Mon Sep 17 00:00:00 2001 From: TAHRI Ahmed R Date: Mon, 16 Mar 2020 14:09:24 +0100 Subject: [PATCH 09/11] :bug: Minor fix in eq on Header class --- kiss_headers/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kiss_headers/utils.py b/kiss_headers/utils.py index aaf85ed..2bfccd8 100644 --- a/kiss_headers/utils.py +++ b/kiss_headers/utils.py @@ -88,7 +88,7 @@ def __iter__(self) -> Iterator[Tuple[str, Optional[str]]]: def __eq__(self, other) -> bool: if isinstance(other, str): - return self.content == other or other in self + 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))) From 2ef307d080a9f5fc065de06172ebc973ffce481b Mon Sep 17 00:00:00 2001 From: TAHRI Ahmed R Date: Mon, 16 Mar 2020 14:09:34 +0100 Subject: [PATCH 10/11] bump 1.0.1 --- kiss_headers/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kiss_headers/version.py b/kiss_headers/version.py index bc08299..0701c8f 100644 --- a/kiss_headers/version.py +++ b/kiss_headers/version.py @@ -2,5 +2,5 @@ Expose version """ -__version__ = "1.0.0" +__version__ = "1.0.1" VERSION = __version__.split('.') From 31034939e7c47f9a135af24a2f9f92cb85923abb Mon Sep 17 00:00:00 2001 From: TAHRI Ahmed R Date: Mon, 16 Mar 2020 14:10:00 +0100 Subject: [PATCH 11/11] :pencil: README.md update --- README.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0007aea..32a3d24 100644 --- a/README.md +++ b/README.md @@ -29,14 +29,18 @@ No matters your religion, IMAP4 or HTTP, you should not worries about accessing using kiss-headers from python interpreter

-### 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. @@ -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