Skip to content

Commit

Permalink
Merge pull request #218 from dstufft/python3
Browse files Browse the repository at this point in the history
Enable Warehouse to run on Python 3.3+, Python 2.7, and PyPy
  • Loading branch information
dstufft committed Mar 3, 2014
2 parents 38f5ec2 + facded5 commit 760d286
Show file tree
Hide file tree
Showing 14 changed files with 111 additions and 42 deletions.
3 changes: 3 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ omit =
# Migrations don't make sense to include in coverage
warehouse/migrations/versions/*
warehouse/migrations/env.py

# The compat module contains things that are only run on one Python version
warehouse/compat.py
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
language: python
python: 2.7
python: 3.3

addons:
postgresql: 9.3
Expand All @@ -9,8 +9,10 @@ env:
- WAREHOUSE_DATABASE_URL=postgresql://postgres@localhost/warehouse
matrix:
- TOXENV=py27
- TOXENV=py33
- TOXENV=pypy
- TOXENV=pep8
- TOXENV=py2pep8
- TOXENV=docs
- TOXENV=packaging

Expand Down
21 changes: 21 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,24 @@ universal = 1
ignore =
.travis.yml
tasks.py

[metadata]
requires-dist =
alembic
arrow
babel
elasticsearch
enum34
guard
Jinja2
PyYAML
raven
readme>=0.1.1
redis
six
SQLAlchemy
sqlalchemy-citext>=1.2.0
Werkzeug

psycopg2; platform_python_implementation == 'CPython'
psycopg2cffi; platform_python_implementation == 'PyPy'
43 changes: 26 additions & 17 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import fnmatch
import os
import platform

from setuptools import setup, find_packages

Expand All @@ -34,6 +35,30 @@ def recursive_glob(path, pattern, cutdirs=0):
matches.append(filepath)
return matches

# Note: Adjusting these requires adjusting setup.cfg as well
install_requires = [
"alembic",
"arrow",
"babel",
"elasticsearch",
"enum34",
"guard",
"Jinja2",
"PyYAML",
"raven",
"readme>=0.1.1",
"redis",
"six",
"SQLAlchemy",
"sqlalchemy-citext>=1.2.0",
"Werkzeug",
]

if platform.python_implementation() == "PyPy":
install_requires += ["psycopg2cffi"]
else:
install_requires += ["psycopg2"]


setup(
name=about["__title__"],
Expand Down Expand Up @@ -64,23 +89,7 @@ def recursive_glob(path, pattern, cutdirs=0):
"warehouse.migrations": ["*.mako", "versions/*.py"],
},

install_requires=[
"alembic",
"arrow",
"babel",
"elasticsearch",
"enum34",
"guard",
"Jinja2",
"psycopg2cffi",
"PyYAML",
"raven",
"readme>=0.1.1",
"redis",
"SQLAlchemy",
"sqlalchemy-citext>=1.2.0",
"Werkzeug",
],
install_requires=install_requires,

entry_points={
"console_scripts": [
Expand Down
8 changes: 4 additions & 4 deletions tests/legacy/test_pypi.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def test_daytime(monkeypatch):

resp = pypi.daytime(app, request)

assert resp.response[0] == '19700101T00:00:00\n'
assert resp.response[0] == b'19700101T00:00:00\n'


@pytest.mark.parametrize("callback", [None, 'yes'])
Expand Down Expand Up @@ -130,7 +130,7 @@ def test_json(monkeypatch, callback):
'"upload_time": "1970-01-01T00:00:00"}]}'
if callback:
expected = '/**/ %s(%s);' % (callback, expected)
assert resp.data == expected
assert resp.data == expected.encode("utf8")


def test_jsonp_invalid():
Expand Down Expand Up @@ -208,7 +208,7 @@ def test_rss(monkeypatch):
'summary': u'hai spam v2',
'created': u'now',
}]
assert resp.data == "<xml>dummy</xml>"
assert resp.data == b"<xml>dummy</xml>"


def test_packages_rss(monkeypatch):
Expand Down Expand Up @@ -261,7 +261,7 @@ def test_packages_rss(monkeypatch):
'summary': u'hai eggs!',
'created': u'now',
}]
assert resp.data == "<xml>dummy</xml>"
assert resp.data == b"<xml>dummy</xml>"


def test_rss_xml_template(monkeypatch):
Expand Down
2 changes: 1 addition & 1 deletion tests/legacy/test_xmlrpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def test_xmlrpc_handler(monkeypatch):
assert interface.list_packages.calls == [pretend.call()]

response_xml = Response.calls[0].args[0]
assert response_xml == '''<?xml version='1.0'?>
assert response_xml == b'''<?xml version='1.0'?>
<methodResponse>
<params>
<param>
Expand Down
2 changes: 1 addition & 1 deletion tests/test_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
{},
("https://secure.gravatar.com/avatar/d41d8cd98f00b204e9800998ecf8427e"
"?size=80"),
)
),
])
def test_gravatar_url(email, kwargs, expected):
assert gravatar_url(email, **kwargs) == expected
Expand Down
8 changes: 7 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tox]
envlist = py27,pypy,pep8,docs,packaging
envlist = py27,py33,pypy,py2pep8,pep8,docs,packaging

[testenv]
deps =
Expand All @@ -26,7 +26,13 @@ deps = check-manifest
commands =
check-manifest

[testenv:py2pep8]
basepython=python2.7
deps = flake8
commands = flake8 .

[testenv:pep8]
basepython=python3.3
deps = flake8
commands = flake8 .

Expand Down
6 changes: 2 additions & 4 deletions warehouse/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,15 @@
from __future__ import absolute_import, division, print_function
from __future__ import unicode_literals

import psycopg2cffi.compat

from warehouse.__about__ import (
__title__, __summary__, __uri__, __version__, __author__, __email__,
__license__, __copyright__, __build__,
)
from warehouse.compat import psycopg2_register

__all__ = [
"__title__", "__summary__", "__uri__", "__version__", "__author__",
"__email__", "__license__", "__copyright__", "__build__",
]


psycopg2cffi.compat.register()
psycopg2_register()
30 changes: 30 additions & 0 deletions warehouse/compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Copyright 2013 Donald Stufft
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# 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.
from __future__ import absolute_import, division, print_function
from __future__ import unicode_literals

# flake8: noqa

import platform

try:
from xmlrpc.server import SimpleXMLRPCDispatcher
except ImportError:
from SimpleXMLRPCServer import SimpleXMLRPCDispatcher


def psycopg2_register():
if platform.python_implementation() == "PyPy":
import psycopg2cffi.compat
psycopg2cffi.compat.register()
10 changes: 5 additions & 5 deletions warehouse/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
import hashlib
import json
import os.path
import urllib
import urlparse

from six.moves import urllib_parse

import warehouse

Expand All @@ -35,14 +35,14 @@ def gravatar_url(email, size=80):
if email is None:
email = ""

email_hash = hashlib.md5(email.strip().lower()).hexdigest()
email_hash = hashlib.md5(email.strip().lower().encode("utf8")).hexdigest()

url = "https://secure.gravatar.com/avatar/{}".format(email_hash)
params = {
"size": size,
}

return "?".join([url, urllib.urlencode(params)])
return "?".join([url, urllib_parse.urlencode(params)])


def static_url(app, filename):
Expand Down Expand Up @@ -70,4 +70,4 @@ def static_url(app, filename):
if basename is not None:
filename = os.path.join(os.path.dirname(filename), basename)

return urlparse.urljoin("/static/", filename)
return urllib_parse.urljoin("/static/", filename)
3 changes: 1 addition & 2 deletions warehouse/legacy/xmlrpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,10 @@
from __future__ import absolute_import, division, print_function
from __future__ import unicode_literals

from SimpleXMLRPCServer import SimpleXMLRPCDispatcher

import arrow
from werkzeug.exceptions import BadRequest

from warehouse.compat import SimpleXMLRPCDispatcher
from warehouse.http import Response


Expand Down
9 changes: 5 additions & 4 deletions warehouse/packaging/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@

import datetime
import os.path
import urlparse
import logging

from six.moves import urllib_parse

from warehouse import db
from warehouse.packaging.tables import ReleaseDependencyKind

Expand Down Expand Up @@ -199,7 +200,7 @@ def get_top_projects(self, num=None):
""",
lambda r: {
"filename": r["filename"],
"url": urlparse.urljoin(
"url": urllib_parse.urljoin(
"/".join([
"../../packages",
r["python_version"],
Expand Down Expand Up @@ -477,7 +478,7 @@ def search_by_classifier(self, selected_classifiers):
releases = []
with self.engine.connect() as conn:
for name, version in conn.execute(query):
releases.append((name.decode('utf-8'), version))
releases.append((name, version))

return releases

Expand All @@ -488,7 +489,7 @@ def get_documentation_url(self, project):
"index.html",
]
if os.path.exists(os.path.join(*path_parts)):
return urlparse.urljoin(
return urllib_parse.urljoin(
self.app.config.urls.documentation,
project
) + "/"
Expand Down
4 changes: 2 additions & 2 deletions warehouse/search/indexes.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def reindex(self, alias=True, keep_old=False):
# Generate an Index Name for Warehouse
index = "".join([
self._index,
binascii.hexlify(os.urandom(4)),
binascii.hexlify(os.urandom(4)).decode("ascii"),
])

# Create this index
Expand All @@ -67,7 +67,7 @@ def reindex(self, alias=True, keep_old=False):
def update_alias(self, alias, index, keep_old=False):
# Get the old index from ElasticSearch
try:
old_index = self.es.indices.get_alias(self._index).keys()[0]
old_index = list(self.es.indices.get_alias(self._index))[0]
except TransportError as exc:
if not exc.status_code == 404:
raise
Expand Down

0 comments on commit 760d286

Please sign in to comment.