diff --git a/wordpress_xmlrpc/base.py b/wordpress_xmlrpc/base.py index d2f4f83..eb1cdbd 100644 --- a/wordpress_xmlrpc/base.py +++ b/wordpress_xmlrpc/base.py @@ -1,11 +1,13 @@ import collections import sys +import urllib.parse from wordpress_xmlrpc.compat import xmlrpc_client, dict_type from wordpress_xmlrpc.exceptions import ServerConnectionError, UnsupportedXmlrpcMethodError, InvalidCredentialsError, XmlrpcDisabledError class Client(object): + """ Connection to a WordPress XML-RPC API endpoint. @@ -13,19 +15,34 @@ class Client(object): `XmlrpcMethod`-derived class to `Client`'s `call` method. """ - def __init__(self, url, username, password, blog_id=0, transport=None, verbose=False): + def __init__(self, url, username, password, blog_id=0, transport=None, verbose=False, safe_transport=None): self.url = url self.username = username self.password = password self.blog_id = blog_id + self.setup(transport, verbose, safe_transport) + + def setup(self, transport, verbose, safe_transport): try: - self.server = xmlrpc_client.ServerProxy(url, allow_none=True, transport=transport, - verbose=verbose) + self.server = xmlrpc_client.ServerProxy(self.url, allow_none=True, transport=transport, + verbose=verbose) self.supported_methods = self.server.mt.supportedMethods() except xmlrpc_client.ProtocolError: e = sys.exc_info()[1] - raise ServerConnectionError(repr(e)) + if e.errcode in [301, 302]: + try: + self.url = e.headers['location'] + except KeyError: + self.url = e.headers['Location'] + + protocol, _ = urllib.parse.splittype(self.url) + if protocol == 'https': + transport = safe_transport + + self.setup(transport, verbose, None) + else: + raise ServerConnectionError(repr(e)) def call(self, method): if method.method_name not in self.supported_methods: @@ -48,6 +65,7 @@ def call(self, method): class XmlrpcMethod(object): + """ Base class for XML-RPC methods. @@ -69,10 +87,12 @@ def __init__(self, *args, **kwargs): if self.optional_args: max_num_args = len(self.method_args) + len(self.optional_args) if not (len(self.method_args) <= len(args) <= max_num_args): - raise ValueError("Invalid number of parameters to %s" % self.method_name) + raise ValueError( + "Invalid number of parameters to %s" % self.method_name) else: if len(args) != len(self.method_args): - raise ValueError("Invalid number of parameters to %s" % self.method_name) + raise ValueError( + "Invalid number of parameters to %s" % self.method_name) for i, arg_name in enumerate(self.method_args): setattr(self, arg_name, args[i]) @@ -133,6 +153,7 @@ def process_result(self, raw_result): class AnonymousMethod(XmlrpcMethod): + """ An XML-RPC method for which no authentication is required. """ @@ -140,6 +161,7 @@ class AnonymousMethod(XmlrpcMethod): class AuthenticatedMethod(XmlrpcMethod): + """ An XML-RPC method for which user authentication is required.