diff --git a/ChangeLog.md b/ChangeLog.md index 6ec5e57..f6b88ab 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -24,6 +24,23 @@ Upcoming Unscheduled ----------- + +* Support reusing TCP connections, and "pipelining" of requests, a la + RFC 2068, Sect 8.1, L2377 + + - The user must ask for pipelining, and supply a callback function + to be called after a response is received. + - Rename Client.request() -> Client.addRequest() (or such) + - Have Client.addRequest() check whether a persistent connection is + wanted, and save the entire request in a Client.pendingRequests + list in that case + - Create a new Client.sendRequests() method which the user may call + to send all requests up the pipeline. (It should work even if the + server does not support pipelining) + - Call the user-supplied callback whenever a request is received. + There are some concurrency issues here, and we may elect to call + the callback only after *all* requests are received. + * Create a script to pack the basic module and any given set of service-specific classes as one file. I still like the idea that a given API (e.g. Facebook) could be packed into a single file, and @@ -82,6 +99,10 @@ v2.0 - Use `application/octet-stream` for unknown media type - Spell 'GitHub' correctly +* Parse Content-Type header correctly; make a dict of the + parameters (Content.ctypeParameters) available to the media-type + handlers + v1.3 ---- A stable branch, with a lot of bug fixes! (Thanks to all who diff --git a/agithub/GitHub.py b/agithub/GitHub.py index 32cdf07..6a8d49b 100644 --- a/agithub/GitHub.py +++ b/agithub/GitHub.py @@ -51,8 +51,8 @@ def generateAuthHeader(self, username=None, password=None, token=None): if token is not None: if password is not None: raise TypeError( - "You cannot use both password and oauth token " - "authenication" + "You cannot use both password and OAuth token " + "authentication" ) return 'Token %s' % token elif username is not None: diff --git a/agithub/base.py b/agithub/base.py index 555a1c6..386d4d7 100644 --- a/agithub/base.py +++ b/agithub/base.py @@ -3,6 +3,8 @@ import json from functools import partial, update_wrapper +import xml.dom.minidom + import sys if sys.version_info[0:2] > (3, 0): from http.client import HTTPConnection, HTTPSConnection @@ -134,18 +136,12 @@ def setConnectionProperties(self, prop): "Expected ConnectionProperties object" ) + self.default_headers = _default_headers.copy() if prop.extra_headers is not None: prop.filterEmptyHeaders() - self.default_headers = _default_headers.copy() self.default_headers.update(prop.extra_headers) self.prop = prop - # Enforce case restrictions on self.default_headers - tmp_dict = {} - for k, v in self.default_headers.items(): - tmp_dict[k.lower()] = v - self.default_headers = tmp_dict - def head(self, url, headers=None, **params): headers = headers or {} url += self.urlencode(params) @@ -223,7 +219,7 @@ def _fix_headers(self, headers): # Add default headers (if unspecified) for k, v in self.default_headers.items(): if k not in headers: - headers[k] = v + headers[k.lower()] = v return headers def urlencode(self, params): @@ -315,7 +311,7 @@ def decode_body(self): def processBody(self): """ - Retrieve the body of the response, encoding it into a usuable + Retrieve the body of the response, encoding it into a usable form based on the media-type (mime-type) """ handlerName = self.mangled_mtype() @@ -347,8 +343,24 @@ def application_json(self): text_javascript = application_json # XXX: This isn't technically correct, but we'll hope for the best. # Patches welcome! - # Insert new media-type handlers here + def application_xml(self): + self.decode_body() + + try: + pybody = xml.dom.minidom.parseString(self.body) + except Exception: #TODO: What kind of exceptions? + pybody = self.body + + return pybody + + + text_xml = application_xml + # The difference between text/xml and application/xml is whether it + # is human-readable or not. For our purposes, there is no + # difference. RFC 3023, L270. + + # Insert new Response media-type handlers here class RequestBody(Body): """ diff --git a/agithub/test.py b/agithub/test.py index c4fe612..5d101c0 100755 --- a/agithub/test.py +++ b/agithub/test.py @@ -44,21 +44,14 @@ def doTestsFor(self, api): raise ValueError('Bad test result ' + (res)) print( - '\n' - ' Results\n' - '--------------------------------------\n' - 'Tests Run: ', - len(results), - '\n' - ' Passed: ', - passes, - '\n' - ' Failed: ', - fails, - '\n' - ' Skipped: ', - skips - ) + '\n' + ' Results\n' + '--------------------------------------\n' + 'Tests Run: ', len(results), '\n' + ' Passed: ', passes, '\n' + ' Failed: ', fails, '\n' + ' Skipped: ', skips + ) def runTest(self, test, api): """Run a single test with the given API session"""