Annotate plugins

This commit is contained in:
Jakub Roztocil 2019-08-31 18:33:54 +02:00
parent e8ef5a783f
commit b947d4826a
5 changed files with 57 additions and 38 deletions

View File

@ -1,6 +1,7 @@
import re import re
from typing import Optional, List
from httpie.plugins import plugin_manager from httpie.plugins import plugin_manager, ConverterPlugin
from httpie.context import Environment from httpie.context import Environment
@ -13,7 +14,8 @@ def is_valid_mime(mime):
class Conversion: class Conversion:
def get_converter(self, mime): @staticmethod
def get_converter(mime: str) -> Optional[ConverterPlugin]:
if is_valid_mime(mime): if is_valid_mime(mime):
for converter_class in plugin_manager.get_converters(): for converter_class in plugin_manager.get_converters():
if converter_class.supports(mime): if converter_class.supports(mime):
@ -23,7 +25,7 @@ class Conversion:
class Formatting: class Formatting:
"""A delegate class that invokes the actual processors.""" """A delegate class that invokes the actual processors."""
def __init__(self, groups, env=Environment(), **kwargs): def __init__(self, groups: List[str], env=Environment(), **kwargs):
""" """
:param groups: names of processor groups to be applied :param groups: names of processor groups to be applied
:param env: Environment :param env: Environment

View File

@ -1,6 +1,6 @@
""" """
WARNING: The plugin API is still work in progress and will WARNING: The plugin API is still work in progress and will
probably be completely reworked by v1.0.0. probably be completely reworked in the future.
""" """
from httpie.plugins.base import ( from httpie.plugins.base import (
@ -15,8 +15,10 @@ from httpie.output.formatters.colors import ColorFormatter
plugin_manager = PluginManager() plugin_manager = PluginManager()
plugin_manager.register(BasicAuthPlugin, plugin_manager.register(
DigestAuthPlugin) BasicAuthPlugin,
plugin_manager.register(HeadersFormatter, DigestAuthPlugin,
JSONFormatter, HeadersFormatter,
ColorFormatter) JSONFormatter,
ColorFormatter,
)

View File

@ -75,7 +75,7 @@ class TransportPlugin(BasePlugin):
raise NotImplementedError() raise NotImplementedError()
class ConverterPlugin: class ConverterPlugin(BasePlugin):
def __init__(self, mime): def __init__(self, mime):
self.mime = mime self.mime = mime
@ -88,7 +88,7 @@ class ConverterPlugin:
raise NotImplementedError raise NotImplementedError
class FormatterPlugin: class FormatterPlugin(BasePlugin):
def __init__(self, **kwargs): def __init__(self, **kwargs):
""" """
@ -100,7 +100,7 @@ class FormatterPlugin:
self.enabled = True self.enabled = True
self.kwargs = kwargs self.kwargs = kwargs
def format_headers(self, headers): def format_headers(self, headers: str) -> str:
"""Return processed `headers` """Return processed `headers`
:param headers: The headers as text. :param headers: The headers as text.
@ -108,7 +108,7 @@ class FormatterPlugin:
""" """
return headers return headers
def format_body(self, content, mime): def format_body(self, content: str, mime: str) -> str:
"""Return processed `content`. """Return processed `content`.
:param mime: E.g., 'application/atom+xml'. :param mime: E.g., 'application/atom+xml'.

View File

@ -7,37 +7,38 @@ from httpie.plugins.base import AuthPlugin
# noinspection PyAbstractClass # noinspection PyAbstractClass
class BuiltinAuthPlugin(AuthPlugin): class BuiltinAuthPlugin(AuthPlugin):
package_name = '(builtin)' package_name = '(builtin)'
class HTTPBasicAuth(requests.auth.HTTPBasicAuth): class HTTPBasicAuth(requests.auth.HTTPBasicAuth):
def __call__(self, r): def __call__(
self,
request: requests.PreparedRequest
) -> requests.PreparedRequest:
""" """
Override username/password serialization to allow unicode. Override username/password serialization to allow unicode.
See https://github.com/jakubroztocil/httpie/issues/212 See https://github.com/jakubroztocil/httpie/issues/212
""" """
r.headers['Authorization'] = type(self).make_header( request.headers['Authorization'] = type(self).make_header(
self.username, self.password).encode('latin1') self.username, self.password).encode('latin1')
return r return request
@staticmethod @staticmethod
def make_header(username, password): def make_header(username: str, password: str) -> str:
credentials = u'%s:%s' % (username, password) credentials = u'%s:%s' % (username, password)
token = b64encode(credentials.encode('utf8')).strip().decode('latin1') token = b64encode(credentials.encode('utf8')).strip().decode('latin1')
return 'Basic %s' % token return 'Basic %s' % token
class BasicAuthPlugin(BuiltinAuthPlugin): class BasicAuthPlugin(BuiltinAuthPlugin):
name = 'Basic HTTP auth' name = 'Basic HTTP auth'
auth_type = 'basic' auth_type = 'basic'
# noinspection PyMethodOverriding # noinspection PyMethodOverriding
def get_auth(self, username, password): def get_auth(self, username: str, password: str) -> HTTPBasicAuth:
return HTTPBasicAuth(username, password) return HTTPBasicAuth(username, password)
@ -47,5 +48,9 @@ class DigestAuthPlugin(BuiltinAuthPlugin):
auth_type = 'digest' auth_type = 'digest'
# noinspection PyMethodOverriding # noinspection PyMethodOverriding
def get_auth(self, username, password): def get_auth(
self,
username: str,
password: str
) -> requests.auth.HTTPDigestAuth:
return requests.auth.HTTPDigestAuth(username, password) return requests.auth.HTTPDigestAuth(username, password)

View File

@ -1,7 +1,9 @@
from itertools import groupby from itertools import groupby
from typing import Type, Iterable, List, Dict
from pkg_resources import iter_entry_points from pkg_resources import iter_entry_points
from httpie.plugins import AuthPlugin, FormatterPlugin, ConverterPlugin from httpie.plugins import AuthPlugin, FormatterPlugin, ConverterPlugin
from httpie.plugins.base import TransportPlugin from httpie.plugins.base import TransportPlugin, BasePlugin
ENTRY_POINT_NAMES = [ ENTRY_POINT_NAMES = [
@ -20,11 +22,11 @@ class PluginManager:
def __iter__(self): def __iter__(self):
return iter(self._plugins) return iter(self._plugins)
def register(self, *plugins): def register(self, *plugins: Type[BasePlugin]):
for plugin in plugins: for plugin in plugins:
self._plugins.append(plugin) self._plugins.append(plugin)
def unregister(self, plugin): def unregister(self, plugin: BasePlugin):
self._plugins.remove(plugin) self._plugins.remove(plugin)
def load_installed_plugins(self): def load_installed_plugins(self):
@ -35,21 +37,25 @@ class PluginManager:
self.register(entry_point.load()) self.register(entry_point.load())
# Auth # Auth
def get_auth_plugins(self): def get_auth_plugins(self) -> List[Type[AuthPlugin]]:
return [plugin for plugin in self if issubclass(plugin, AuthPlugin)] return [plugin for plugin in self if issubclass(plugin, AuthPlugin)]
def get_auth_plugin_mapping(self): def get_auth_plugin_mapping(self) -> Dict[str, Type[AuthPlugin]]:
return {plugin.auth_type: plugin for plugin in self.get_auth_plugins()} return {
plugin.auth_type: plugin for plugin in self.get_auth_plugins()
}
def get_auth_plugin(self, auth_type): def get_auth_plugin(self, auth_type: str) -> Type[AuthPlugin]:
return self.get_auth_plugin_mapping()[auth_type] return self.get_auth_plugin_mapping()[auth_type]
# Output processing # Output processing
def get_formatters(self): def get_formatters(self) -> List[Type[FormatterPlugin]]:
return [plugin for plugin in self return [
if issubclass(plugin, FormatterPlugin)] plugin for plugin in self
if issubclass(plugin, FormatterPlugin)
]
def get_formatters_grouped(self): def get_formatters_grouped(self) -> Dict[str, List[Type[FormatterPlugin]]]:
groups = {} groups = {}
for group_name, group in groupby( for group_name, group in groupby(
self.get_formatters(), self.get_formatters(),
@ -57,11 +63,15 @@ class PluginManager:
groups[group_name] = list(group) groups[group_name] = list(group)
return groups return groups
def get_converters(self): def get_converters(self) -> List[Type[ConverterPlugin]]:
return [plugin for plugin in self return [
if issubclass(plugin, ConverterPlugin)] plugin for plugin in self
if issubclass(plugin, ConverterPlugin)
]
# Adapters # Adapters
def get_transport_plugins(self): def get_transport_plugins(self) -> List[Type[TransportPlugin]]:
return [plugin for plugin in self return [
if issubclass(plugin, TransportPlugin)] plugin for plugin in self
if issubclass(plugin, TransportPlugin)
]