Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

File listing and download is now working

  • Loading branch information...
commit c63584c2d3826e90d46424a2217ed2606a661176 1 parent efa5556
@exhuma authored
View
1  .gitignore
@@ -6,3 +6,4 @@ env
manage.py
files
distribute-*.tar.gz
+build
View
14 db_repo/versions/003_Add_filename_column.py
@@ -0,0 +1,14 @@
+from sqlalchemy import *
+from migrate import *
+
+
+def upgrade(migrate_engine):
+ meta = MetaData(bind=migrate_engine)
+ files = Table('file', meta, autoload=True)
+ filename = Column('filename', Unicode)
+ filename.create(files)
+
+def downgrade(migrate_engine):
+ meta = MetaData(bind=migrate_engine)
+ files = Table('file', meta, autoload=True)
+ files.c.filename.drop()
View
2  mypi/__init__.py
@@ -1 +1 @@
-__version__="0.1dev2"
+__version__="0.1"
View
33 mypi/db.py
@@ -4,6 +4,7 @@
create_engine,
Column,
String,
+ Unicode,
Integer,
ForeignKey,
PrimaryKeyConstraint,
@@ -86,6 +87,17 @@ def get_or_add(self, session, email, name):
return proj
@classmethod
+ def get(self, session, email, name):
+ """
+ Return a project reference
+ """
+ q = session.query(Project)
+ q = q.filter(Project.author_email == email)
+ q = q.filter(Project.name == name)
+ proj = q.first()
+ return proj
+
+ @classmethod
def all(self, session):
"""
Return a list of projects
@@ -115,6 +127,8 @@ class Release(Base):
{}
)
+ files = relationship('File')
+
project = Column(String)
license = Column(String)
metadata_version = Column(String)
@@ -222,11 +236,12 @@ class File(Base):
comment = Column(String)
filetype = Column(String)
pyversion = Column(String)
+ filename = Column(Unicode)
protcol_version = Column(Integer)
@classmethod
- def add(self, session, data):
+ def add(self, session, data, filename):
# ensure the release exists
rel = Release.get(session, data['author_email'], data['name'], data['version'])
@@ -234,7 +249,8 @@ def add(self, session, data):
raise ValueError("Release for this file does not exist yet! "
"Please register it first!")
- file = File(data["name"], data["author_email"], data["version"], data["md5_digest"])
+ file = File(data["name"], data["author_email"], data["version"],
+ filename, data["md5_digest"])
file.comment = data["comment"]
file.filetype = data["filetype"]
@@ -243,10 +259,21 @@ def add(self, session, data):
session.add(file)
- def __init__(self, project, author_email, version, md5_digest):
+ @classmethod
+ def find(self, session, project, md5):
+ """
+ Finds a file by project and MD5-digest
+ """
+ q = session.query(File)
+ q = q.filter(File.project == project)
+ q = q.filter(File.md5_digest == md5)
+ return q.first()
+
+ def __init__(self, project, author_email, version, filename, md5_digest):
self.project = project
self.author_email = author_email
self.version = version
+ self.filename = filename
self.md5_digest = md5_digest
def __eq__(self, other):
View
34 mypi/server.py
@@ -1,15 +1,13 @@
from os.path import join, exists
from os import makedirs
-from flask import Flask, g, abort, render_template
+from flask import Flask, g, abort, render_template, send_from_directory
from werkzeug.utils import secure_filename
from mypi import db as model
app = Flask(__name__)
-app.config['UPLOAD_FOLDER'] = "files"
-
@app.before_request
def before_request():
app.logger.debug("Before Request")
@@ -21,6 +19,7 @@ def teardown_request(exception):
g.db.close()
@app.route("/", methods=['GET'])
+@app.route("/project")
def hello():
projects = model.Project.all(g.db)
return render_template("project_list.html", projects=projects)
@@ -38,17 +37,42 @@ def post():
return abort(501, description="Action %s is not yet implemented" % frm[":action"])
+@app.route("/project/<author_email>/<name>")
+def project(author_email, name):
+ """
+ Display the Project details
+ """
+ proj = model.Project.get(g.db, author_email, name)
+ if not proj:
+ abort(404, description = "No such project")
+
+ return render_template("project.html", project=proj)
+
+@app.route("/download/<project>/<md5>")
+def download(project, md5):
+ file = model.File.find(g.db, project, md5)
+ if not file:
+ return abort(404, description="File not found")
+
+ folder = join(
+ app.config['UPLOAD_FOLDER'],
+ file.author_email.replace("@", "_at_"),
+ project)
+
+ return send_from_directory(
+ folder, file.filename, as_attachment=True)
+
def _do_file_upload(data):
from flask import request
file = request.files['content']
filename = secure_filename(file.filename)
try:
- model.File.add(g.db, data)
+ model.File.add(g.db, data, filename)
except ValueError, exc:
abort(409, description=str(exc))
author_path = data['author_email'].replace('@', '_at_')
- target_dir = join(app.config.get("UPLOAD_FOLDER", "files"), author_path, data['name'])
+ target_dir = join(app.config["UPLOAD_FOLDER"], author_path, data['name'])
if not exists(target_dir):
makedirs(target_dir)
file.save(join(target_dir, filename))
View
58 mypi/templates/project.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>Project: {{project.name}}</title>
+</head>
+<body>
+
+ <h1>{{project.name}}</h1>
+ <h2>{{project.author_email}}</h2>
+ <pre>{{project.description}}</pre>
+
+ <h2>Releases</h2>
+ <table>
+ <thead>
+ <tr>
+ <th>Version</th>
+ <th>Platform</th>
+ <th>License</th>
+ <th>Author</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for rel in project.releases %}
+ <tr>
+ <td>{{ rel.version }}</td>
+ <td>{{ rel.platform }}</td>
+ <td>{{ rel.license }}</td>
+ <td>{{ rel.author }}</td>
+ </tr>
+ <tr>
+ <td colspan="4">
+ <table>
+ <thead>
+ <th colspan="2">File</th>
+ <th>Python Version</th>
+ <th>MD5</th>
+ <th>Comment</th>
+ </thead>
+ <tbody>
+ {% for file in rel.files %}
+ <tr>
+ <td><a href="{{url_for('download', project=project.name, md5=file.md5_digest) }}">{{ file.filename }}</a></td>
+ <td>{{ file.filetype}}</td>
+ <td>{{ file.pyversion }}</td>
+ <td>{{ file.md5_digest }}</td>
+ <td>{{ file.comment }}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+</body>
+</html>
View
39 mypi/templates/project_list.html
@@ -1,24 +1,17 @@
-<html>
- <body>
- <table>
- <tbody>
- {% for p in projects %}
- <tr><th>{{p.name}}</th></tr>
- <tr>
- <td>
- <table>
- <tbody>
- {% for r in p.releases %}
- <tr>
- <td>{{r.version}}</td>
- </tr>
- {% endfor %}
- </tbody>
- </table>
- </td>
- </tr>
- {% endfor %}
- </tbody>
- </table>
- </body>
+<!DOCTYPE HTML>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>Private Package Index</title>
+</head>
+<body>
+
+ <ul>
+ {% for p in projects %}
+ <li><a href="{{url_for('project', name=p.name, author_email=p.author_email)}}">{{p.name}}</a></li>
+ {% endfor %}
+ </ul>
+
+
+</body>
</html>
View
2  runserver.py
@@ -1,7 +1,9 @@
from mypi.db import rebind
from mypi.server import app
+from os.path import abspath
rebind('sqlite:///app.db', True)
app.debug = True
+app.config['UPLOAD_FOLDER'] = abspath('files')
app.run(host="0.0.0.0", port=8080)
Please sign in to comment.
Something went wrong with that request. Please try again.