Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions httoop/codecs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Module containing various codecs which are
common used in combination with HTTP.
"""

from __future__ import annotations

import inspect
Expand All @@ -14,11 +15,7 @@
CODECS = {}
types = (application, audio, example, image, message, model, multipart, text, video)

__all__ = [
'CODECS', 'Codec',
'application', 'audio', 'example', 'image',
'message', 'model', 'multipart', 'text', 'video'
]
__all__ = ['CODECS', 'Codec', 'application', 'audio', 'example', 'image', 'message', 'model', 'multipart', 'text', 'video']


def lookup(encoding: str, raise_errors: bool = True) -> Any:
Expand Down
4 changes: 2 additions & 2 deletions httoop/date.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
from typing import Any

from httoop.exceptions import InvalidDate
from httoop.meta import HTTPSemantic
from httoop.meta import Semantic
from httoop.util import _


__all__ = ['Date']


class Date(metaclass=HTTPSemantic):
class Date(Semantic):
"""
A HTTP Date string.

Expand Down
29 changes: 7 additions & 22 deletions httoop/header/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,16 @@
.. seealso:: :rfc:`2616#section-14`
"""

# FIXME: python3?
# TODO: add a MAXIMUM of 500 headers?

import inspect

from httoop.header import (
auth,
cache,
conditional,
messaging,
range, # pylint: disable=W0622
security,
semantics,
)
from httoop.header.element import HEADER, HeaderElement, HeaderType
from httoop.header import auth, cache, conditional, messaging, ranges, security
from httoop.header.element import HEADER, HeaderElement
from httoop.header.headers import Headers
from httoop.header.messaging import Server, UserAgent


__all__ = ['Headers', 'Server', 'UserAgent']

types = (semantics, messaging, conditional, range, cache, auth, security)

for _, member in (member for type_ in types for member in inspect.getmembers(type_, inspect.isclass)):
if isinstance(member, HeaderType) and member is not HeaderElement and not _.startswith('_'):
HEADER[member.__name__] = member
globals()[_] = member
__all__.append(_)
__all__ = ['Headers', 'Server', 'UserAgent', 'auth', 'cache', 'conditional', 'messaging', 'ranges', 'security', 'HeaderElement']
for member in HEADER.values():
name = member.__name__
__all__.append(name)
globals()[name] = member
20 changes: 10 additions & 10 deletions httoop/header/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,28 @@ class Authorization(AuthRequestElement):
is_request_header = True


class ProxyAuthenticate(_ListElement, _HopByHopElement, AuthResponseElement):
__name__ = 'Proxy-Authenticate'
class ProxyAuthenticate(_ListElement, _HopByHopElement, AuthResponseElement, name='Proxy-Authenticate'):

is_response_header = True


class ProxyAuthorization(_HopByHopElement, AuthRequestElement):
__name__ = 'Proxy-Authorization'
class ProxyAuthorization(_HopByHopElement, AuthRequestElement, name='Proxy-Authorization'):

is_request_header = True


class WWWAuthenticate(_ListElement, AuthResponseElement):
__name__ = 'WWW-Authenticate'
class WWWAuthenticate(_ListElement, AuthResponseElement, name='WWW-Authenticate'):

is_response_header = True


class AuthenticationInfo(AuthInfoElement):
__name__ = 'Authentication-Info'
class AuthenticationInfo(AuthInfoElement, name='Authentication-Info'):

is_response_header = True


class ProxyAuthenticationInfo(_HopByHopElement, AuthInfoElement):
__name__ = 'Proxy-Authentication-Info'
class ProxyAuthenticationInfo(_HopByHopElement, AuthInfoElement, name='Proxy-Authentication-Info'):

is_response_header = True


Expand Down
3 changes: 1 addition & 2 deletions httoop/header/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ class Age(HeaderElement):
is_response_header = True


class CacheControl(HeaderElement):
__name__ = 'Cache-Control'
class CacheControl(HeaderElement, name='Cache-Control'):

is_request_header = True
is_response_header = True
Expand Down
20 changes: 10 additions & 10 deletions httoop/header/conditional.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,26 +61,26 @@ def __eq__(self, other: object) -> bool:
return other.value in {self.value, '*'}


class LastModified(_DateComparable, HeaderElement):
__name__ = 'Last-Modified'
class LastModified(_DateComparable, HeaderElement, name='Last-Modified'):

is_response_header = True


class IfMatch(_MatchElement, HeaderElement):
__name__ = 'If-Match'
class IfMatch(_MatchElement, HeaderElement, name='If-Match'):

is_request_header = True


class IfModifiedSince(_DateComparable, HeaderElement):
__name__ = 'If-Modified-Since'
class IfModifiedSince(_DateComparable, HeaderElement, name='If-Modified-Since'):

is_request_header = True


class IfNoneMatch(_MatchElement, HeaderElement):
__name__ = 'If-None-Match'
class IfNoneMatch(_MatchElement, HeaderElement, name='If-None-Match'):

is_request_header = True


class IfUnmodifiedSince(_DateComparable, HeaderElement):
__name__ = 'If-Unmodified-Since'
class IfUnmodifiedSince(_DateComparable, HeaderElement, name='If-Unmodified-Since'):

is_request_header = True
24 changes: 12 additions & 12 deletions httoop/header/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,10 @@
HEADER = CaseInsensitiveDict()


class HeaderType(type):

def __new__(cls: type, name: str, bases: Any, dict_: dict[str, Any]) -> Any:
__all__.append(name)
name = dict_.get('__name__', name)
return super().__new__(cls, name, bases, dict_)


class HeaderElement(metaclass=HeaderType):
class HeaderElement:
"""An element (with parameters) from an HTTP header's element list."""

name = ''
priority = None
is_request_header = False
is_response_header = False
Expand All @@ -55,6 +48,13 @@ def __init__(self, value: str, params: Any | None = None) -> None:
self.params = ByteUnicodeDict(params or {})
self.sanitize()

def __init_subclass__(cls, name=None, **kwargs):
super().__init_subclass__(**kwargs)
name = name or cls.__name__
if name != 'HeaderElement' and not name.startswith('_'):
HEADER[name] = cls
cls.name = name

def sanitize(self) -> None:
pass

Expand Down Expand Up @@ -101,7 +101,7 @@ def parseparam(cls, atom: bytes) -> tuple[bytes, bytes, bool]:
try:
val, quoted = cls.unescape_param(val.strip())
except InvalidHeader:
raise InvalidHeader(_('Unquoted parameter %r in %r containing TSPECIALS: %r'), key, cls.__name__, val)
raise InvalidHeader(_('Unquoted parameter %r in %r containing TSPECIALS: %r'), key, cls.name, val)
return cls.unescape_key(key), val, quoted

@classmethod
Expand All @@ -114,7 +114,7 @@ def unescape_param(cls, value: bytes) -> tuple[bytes, bool]:
if quoted:
value = re.sub(b'\\\\(?!\\\\)', b'', value[1:-1])
elif cls.RE_TSPECIALS.search(value):
raise InvalidHeader(_('Unquoted parameter in %r containing TSPECIALS: %r'), cls.__name__, value)
raise InvalidHeader(_('Unquoted parameter in %r containing TSPECIALS: %r'), cls.name, value)
return value, quoted

@classmethod
Expand Down Expand Up @@ -248,7 +248,7 @@ def encode_rfc2047(cls, value: str) -> bytes:

def __repr__(self) -> str:
params = f', {self.params!r}' if self.params else ''
return f'<{self.__class__.__name__}({self.value!r}{params})>'
return f'<{self.name}({self.value!r}{params})>'


class MimeType:
Expand Down
8 changes: 4 additions & 4 deletions httoop/header/headers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

from httoop.exceptions import InvalidHeader
from httoop.header.element import HEADER, HeaderElement
from httoop.meta import HTTPSemantic
from httoop.meta import Semantic
from httoop.util import CaseInsensitiveDict, _, to_unicode


class Headers(CaseInsensitiveDict, metaclass=HTTPSemantic):
class Headers(CaseInsensitiveDict, Semantic):

__slots__ = ()

Expand Down Expand Up @@ -45,7 +45,7 @@ def formatkey(cls, key: bytes | str) -> str:
if cls.HEADER_RE.search(key.encode('utf-8')):
raise InvalidHeader(_('Invalid header name: %r'), key)
try:
return to_unicode(HEADER[key].__name__)
return to_unicode(HEADER[key].name)
except KeyError:
return key

Expand Down Expand Up @@ -156,7 +156,7 @@ def __encoded_items(self):
for key, values in self.items():
Element = HEADER.get(key, HeaderElement)
if Element is not HeaderElement:
key = Element.__name__
key = Element.name
key = key.encode('ascii', 'ignore')
if Element.list_element:
for value in Element.split(values):
Expand Down
Loading
Loading