Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Port http/ to Python 3 #3771

Merged
merged 22 commits into from
Sep 5, 2018
Merged
1 change: 1 addition & 0 deletions changelog.d/3771.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
http/ is now ported to Python 3.
5 changes: 3 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ ignore =
[pep8]
max-line-length = 90
# W503 requires that binary operators be at the end, not start, of lines. Erik
# doesn't like it. E203 is contrary to PEP8.
ignore = W503,E203
# doesn't like it. E203 is contrary to PEP8. E731 is silly.
ignore = W503,E203,E731
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are not doing anything against E731 (BTW: Do not assign lambda and use def instead)
So why do you want to add it here?


[flake8]
# note that flake8 inherits the "ignore" settings from "pep8" (because it uses
# pep8 to do those checks), but not the "max-line-length" setting
max-line-length = 90
ignore=W503,E203,E731
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

based on the comment above that is inherited from pep8 so this is duplicate

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I put E731 in pep8 it gets ignored (since it's pyflakes?), if I just put E731 in flake8 it stops ignoring the ones in pep8 :(

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although it is merged now, I meant that pep8 currently has the same line. So no "just E731". The whole line could be go away if I get it right.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hawkowl it would have been nice to fix the comment if you thought it was wrong :/.


[isort]
line_length = 89
Expand Down
13 changes: 7 additions & 6 deletions synapse/appservice/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
import urllib

from six.moves import urllib

from prometheus_client import Counter

Expand Down Expand Up @@ -98,7 +99,7 @@ def __init__(self, hs):
def query_user(self, service, user_id):
if service.url is None:
defer.returnValue(False)
uri = service.url + ("/users/%s" % urllib.quote(user_id))
uri = service.url + ("/users/%s" % urllib.parse.quote(user_id))
response = None
try:
response = yield self.get_json(uri, {
Expand All @@ -119,7 +120,7 @@ def query_user(self, service, user_id):
def query_alias(self, service, alias):
if service.url is None:
defer.returnValue(False)
uri = service.url + ("/rooms/%s" % urllib.quote(alias))
uri = service.url + ("/rooms/%s" % urllib.parse.quote(alias))
response = None
try:
response = yield self.get_json(uri, {
Expand Down Expand Up @@ -153,7 +154,7 @@ def query_3pe(self, service, kind, protocol, fields):
service.url,
APP_SERVICE_PREFIX,
kind,
urllib.quote(protocol)
urllib.parse.quote(protocol)
)
try:
response = yield self.get_json(uri, fields)
Expand Down Expand Up @@ -188,7 +189,7 @@ def _get():
uri = "%s%s/thirdparty/protocol/%s" % (
service.url,
APP_SERVICE_PREFIX,
urllib.quote(protocol)
urllib.parse.quote(protocol)
)
try:
info = yield self.get_json(uri, {})
Expand Down Expand Up @@ -228,7 +229,7 @@ def push_bulk(self, service, events, txn_id=None):
txn_id = str(txn_id)

uri = service.url + ("/transactions/%s" %
urllib.quote(txn_id))
urllib.parse.quote(txn_id))
try:
yield self.put_json(
uri=uri,
Expand Down
10 changes: 5 additions & 5 deletions synapse/federation/federation_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -838,9 +838,9 @@ def on_edu(self, edu_type, origin, content):
)

return self._send_edu(
edu_type=edu_type,
origin=origin,
content=content,
edu_type=edu_type,
origin=origin,
content=content,
)

def on_query(self, query_type, args):
Expand All @@ -851,6 +851,6 @@ def on_query(self, query_type, args):
return handler(args)

return self._get_query_client(
query_type=query_type,
args=args,
query_type=query_type,
args=args,
)
82 changes: 31 additions & 51 deletions synapse/http/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,25 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import logging
import urllib

from six import StringIO
from six import text_type
from six.moves import urllib

import treq
from canonicaljson import encode_canonical_json, json
from prometheus_client import Counter

from OpenSSL import SSL
from OpenSSL.SSL import VERIFY_NONE
from twisted.internet import defer, protocol, reactor, ssl, task
from twisted.internet import defer, protocol, reactor, ssl
from twisted.internet.endpoints import HostnameEndpoint, wrapClientTLS
from twisted.web._newclient import ResponseDone
from twisted.web.client import (
Agent,
BrowserLikeRedirectAgent,
ContentDecoderAgent,
FileBodyProducer as TwistedFileBodyProducer,
GzipDecoder,
HTTPConnectionPool,
PartialDownloadError,
Expand Down Expand Up @@ -83,18 +84,20 @@ def __init__(self, hs):
if hs.config.user_agent_suffix:
self.user_agent = "%s %s" % (self.user_agent, hs.config.user_agent_suffix,)

self.user_agent = self.user_agent.encode('ascii')

@defer.inlineCallbacks
def request(self, method, uri, *args, **kwargs):
def request(self, method, uri, data=b'', headers=None):
# A small wrapper around self.agent.request() so we can easily attach
# counters to it
outgoing_requests_counter.labels(method).inc()

# log request but strip `access_token` (AS requests for example include this)
logger.info("Sending request %s %s", method, redact_uri(uri))
logger.info("Sending request %s %s", method, redact_uri(uri.encode('ascii')))

try:
request_deferred = self.agent.request(
method, uri, *args, **kwargs
request_deferred = treq.request(
method, uri, agent=self.agent, data=data, headers=headers
)
add_timeout_to_deferred(
request_deferred, 60, self.hs.get_reactor(),
Expand All @@ -105,14 +108,14 @@ def request(self, method, uri, *args, **kwargs):
incoming_responses_counter.labels(method, response.code).inc()
logger.info(
"Received response to %s %s: %s",
method, redact_uri(uri), response.code
method, redact_uri(uri.encode('ascii')), response.code
)
defer.returnValue(response)
except Exception as e:
incoming_responses_counter.labels(method, "ERR").inc()
logger.info(
"Error sending request to %s %s: %s %s",
method, redact_uri(uri), type(e).__name__, e.message
method, redact_uri(uri.encode('ascii')), type(e).__name__, e.args[0]
)
raise

Expand All @@ -137,7 +140,8 @@ def post_urlencoded_get_json(self, uri, args={}, headers=None):
# TODO: Do we ever want to log message contents?
logger.debug("post_urlencoded_get_json args: %s", args)

query_bytes = urllib.urlencode(encode_urlencode_args(args), True)
query_bytes = urllib.parse.urlencode(
encode_urlencode_args(args), True).encode("utf8")

actual_headers = {
b"Content-Type": [b"application/x-www-form-urlencoded"],
Expand All @@ -148,15 +152,14 @@ def post_urlencoded_get_json(self, uri, args={}, headers=None):

response = yield self.request(
"POST",
uri.encode("ascii"),
uri,
headers=Headers(actual_headers),
bodyProducer=FileBodyProducer(StringIO(query_bytes))
data=query_bytes
)

body = yield make_deferred_yieldable(readBody(response))

if 200 <= response.code < 300:
defer.returnValue(json.loads(body))
body = yield make_deferred_yieldable(treq.json_content(response))
defer.returnValue(body)
else:
raise HttpResponseException(response.code, response.phrase, body)

Expand Down Expand Up @@ -191,9 +194,9 @@ def post_json_get_json(self, uri, post_json, headers=None):

response = yield self.request(
"POST",
uri.encode("ascii"),
uri,
headers=Headers(actual_headers),
bodyProducer=FileBodyProducer(StringIO(json_str))
data=json_str
)

body = yield make_deferred_yieldable(readBody(response))
Expand Down Expand Up @@ -248,7 +251,7 @@ def put_json(self, uri, json_body, args={}, headers=None):
ValueError: if the response was not JSON
"""
if len(args):
query_bytes = urllib.urlencode(args, True)
query_bytes = urllib.parse.urlencode(args, True)
uri = "%s?%s" % (uri, query_bytes)

json_str = encode_canonical_json(json_body)
Expand All @@ -262,9 +265,9 @@ def put_json(self, uri, json_body, args={}, headers=None):

response = yield self.request(
"PUT",
uri.encode("ascii"),
uri,
headers=Headers(actual_headers),
bodyProducer=FileBodyProducer(StringIO(json_str))
data=json_str
)

body = yield make_deferred_yieldable(readBody(response))
Expand Down Expand Up @@ -293,7 +296,7 @@ def get_raw(self, uri, args={}, headers=None):
HttpResponseException on a non-2xx HTTP response.
"""
if len(args):
query_bytes = urllib.urlencode(args, True)
query_bytes = urllib.parse.urlencode(args, True)
uri = "%s?%s" % (uri, query_bytes)

actual_headers = {
Expand All @@ -304,7 +307,7 @@ def get_raw(self, uri, args={}, headers=None):

response = yield self.request(
"GET",
uri.encode("ascii"),
uri,
headers=Headers(actual_headers),
)

Expand Down Expand Up @@ -339,7 +342,7 @@ def get_file(self, url, output_stream, max_size=None, headers=None):

response = yield self.request(
"GET",
url.encode("ascii"),
url,
headers=Headers(actual_headers),
)

Expand Down Expand Up @@ -434,12 +437,12 @@ class CaptchaServerHttpClient(SimpleHttpClient):

@defer.inlineCallbacks
def post_urlencoded_get_raw(self, url, args={}):
query_bytes = urllib.urlencode(encode_urlencode_args(args), True)
query_bytes = urllib.parse.urlencode(encode_urlencode_args(args), True)

response = yield self.request(
"POST",
url.encode("ascii"),
bodyProducer=FileBodyProducer(StringIO(query_bytes)),
url,
data=query_bytes,
headers=Headers({
b"Content-Type": [b"application/x-www-form-urlencoded"],
b"User-Agent": [self.user_agent],
Expand Down Expand Up @@ -510,7 +513,7 @@ def encode_urlencode_args(args):


def encode_urlencode_arg(arg):
if isinstance(arg, unicode):
if isinstance(arg, text_type):
return arg.encode('utf-8')
elif isinstance(arg, list):
return [encode_urlencode_arg(i) for i in arg]
Expand Down Expand Up @@ -542,26 +545,3 @@ def getContext(self, hostname=None, port=None):

def creatorForNetloc(self, hostname, port):
return self


class FileBodyProducer(TwistedFileBodyProducer):
"""Workaround for https://twistedmatrix.com/trac/ticket/8473

We override the pauseProducing and resumeProducing methods in twisted's
FileBodyProducer so that they do not raise exceptions if the task has
already completed.
"""

def pauseProducing(self):
try:
super(FileBodyProducer, self).pauseProducing()
except task.TaskDone:
# task has already completed
pass

def resumeProducing(self):
try:
super(FileBodyProducer, self).resumeProducing()
except task.NotPaused:
# task was not paused (probably because it had already completed)
pass
Loading