Skip to content
This repository was archived by the owner on May 30, 2020. It is now read-only.

Make it easier to run local version of PyPI. #536

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,19 @@ Then you can launch the server using the pypi.wsgi script::

PyPI will be available in your browser at http://localhost:8000

You can use the `--port` option to change the port, in particular some browsers
do not accept TLS connections except on port 443 and 8443. Alternatively you
can also set the environment variable
``PYPI_LEGACY_ALLOW_NO_TLS_FOR_TESTING_PURPOSE_ONLY`` to ``1`` for local
testing and have PyPI legacy accept non-TLS connections. Use this if you see
the following message when accessing your local PyPI:

.. :

Forbidden

Must access using HTTPS instead of HTTP

Database Setup
--------------

Expand Down
11 changes: 8 additions & 3 deletions pypi.wsgi
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def application(environ, start_response):
r = Request(environ, start_response)
webui.WebUI(r, environ).run()
return [r.wfile.getvalue()]
except Exception, e:
except Exception as e:
import traceback;traceback.print_exc()
return ['Ooops, there was a problem (%s)' % e]
#application=debug
Expand Down Expand Up @@ -152,7 +152,12 @@ def site_fake(app, environ, start_response):

if __name__ == '__main__':
# very simple wsgi server so we can play locally

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--port", help="port to listen on", type=int, default=8000)
args = parser.parse_args()
from wsgiref.simple_server import make_server
httpd = make_server('', 8000, partial(site_fake, application))
print "Serving on port 8000..."
httpd = make_server('', args.port, partial(site_fake, application))
print("Serving on port %s..." % args.port)
httpd.serve_forever()
10 changes: 5 additions & 5 deletions store.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
''' Implements a store of disutils PKG-INFO entries, keyed off name, version.
'''

from __future__ import print_function

import sys, os, re, time, hashlib, random, types, math, stat, errno
import logging, string, datetime, calendar, binascii, urllib, urllib2, cgi
import posixpath
from collections import defaultdict
import cPickle as pickle
try:
import psycopg2
except ImportError:
pass
import psycopg2
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I removed the except-pass anyway if fails later if one does not have psycopg2 working.

try:
import sqlite3
sqlite3_cursor = sqlite3.Cursor
Expand Down Expand Up @@ -2845,5 +2845,5 @@ def get_description_urls(html):
store.update_upload_times()
store.commit()
else:
print "UNKNOWN COMMAND", sys.argv[2]
print("UNKNOWN COMMAND", sys.argv[2])
store.close()
47 changes: 29 additions & 18 deletions webui.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# import defusedxml before anything else
from __future__ import print_function
import defusedxml
import defusedxml.xmlrpc
defusedxml.xmlrpc.monkey_patch()
Expand Down Expand Up @@ -257,14 +258,18 @@ def decode_form(form):
d[k] = transmute(v)
return d

if os.environ.get('PYPI_LEGACY_ALLOW_NO_TLS_FOR_TESTING_PURPOSE_ONLY', 'False') == '1':
def must_tls(fn):
return fn
else:

def must_tls(fn):
@functools.wraps(fn)
def wrapped(self, *args, **kwargs):
if self.env.get('HTTP_X_FORWARDED_PROTO') != 'https':
raise Forbidden("Must access using HTTPS instead of HTTP")
return fn(self, *args, **kwargs)
return wrapped
def must_tls(fn):
@functools.wraps(fn)
def wrapped(self, *args, **kwargs):
if self.env.get('HTTP_X_FORWARDED_PROTO') != 'https':
raise Forbidden("Must access using HTTPS instead of HTTP")
return fn(self, *args, **kwargs)
return wrapped


class MultiWriteFS(fs.multifs.MultiFS):
Expand Down Expand Up @@ -415,17 +420,20 @@ def __init__(self, handler, env):
self.usercookie = None
self.failed = None # error message if initialization already produced a failure

self.package_bucket = None
if self.config.database_aws_access_key_id and self.config.database_aws_secret_access_key:
self.s3conn = boto.s3.connect_to_region(
"us-west-2",
aws_access_key_id=self.config.database_aws_access_key_id,
aws_secret_access_key=self.config.database_aws_secret_access_key,
)

self.s3conn = boto.s3.connect_to_region(
"us-west-2",
aws_access_key_id=self.config.database_aws_access_key_id,
aws_secret_access_key=self.config.database_aws_secret_access_key,
)

self.package_bucket = self.s3conn.get_bucket(
self.config.database_files_bucket,
validate=False,
)
self.package_bucket = self.s3conn.get_bucket(
self.config.database_files_bucket,
validate=False,
)
else:
print("AWS database not fully configured. Getting the package files will be unavailable.", file=sys.stderr)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note that this is mostly indenting, so viewing the diff with ?w=1 might make things easier to review.


if self.config.database_docs_bucket is not None:
self.docs_fs = NoDirS3FS(
Expand All @@ -434,7 +442,10 @@ def __init__(self, handler, env):
aws_secret_key=self.config.database_aws_secret_access_key,
)
else:
self.docs_fs = fs.osfs.OSFS(self.config.database_docs_dir)
try:
self.docs_fs = fs.osfs.OSFS(self.config.database_docs_dir)
except Exception as e:
import pdb; pdb.set_trace()

# XMLRPC request or not?
if self.env.get('CONTENT_TYPE') != 'text/xml':
Expand Down