From python-checkins at python.org Sat Apr 2 19:13:09 2011 From: python-checkins at python.org (martin.von.loewis) Date: Sat, 2 Apr 2011 19:13:09 +0200 (CEST) Subject: [Pypi-checkins] r898 - trunk/pypi Message-ID: <3Q25kY5tTcz7LkN@mail.python.org> Author: martin.von.loewis Date: Sat Apr 2 19:13:09 2011 New Revision: 898 Modified: trunk/pypi/webui.py Log: Don't directly call display for single-item search results; redirect instead. Modified: trunk/pypi/webui.py ============================================================================== --- trunk/pypi/webui.py (original) +++ trunk/pypi/webui.py Sat Apr 2 19:13:09 2011 @@ -1527,9 +1527,7 @@ scores[k[0]] = v[0] if len(l) == 1: - self.form['name'] = l[0][-1]['name'] - self.form['version'] = l[0][-1]['version'] - return self.display() + raise RedirectTemporary, "%s/%s/%s" % (self.config.url,l[0][-1]['name'],l[0][-1]['version']) # sort and pull out just the record l.sort() From python-checkins at python.org Wed Apr 6 04:43:36 2011 From: python-checkins at python.org (richard) Date: Wed, 6 Apr 2011 04:43:36 +0200 (CEST) Subject: [Pypi-checkins] r899 - in trunk/pypi: . templates Message-ID: <3Q4BFN0pdvzRnt@mail.python.org> Author: richard Date: Wed Apr 6 04:43:35 2011 New Revision: 899 Added: trunk/pypi/templates/about.pt Modified: trunk/pypi/webui.py Log: add an About page Added: trunk/pypi/templates/about.pt ============================================================================== --- (empty file) +++ trunk/pypi/templates/about.pt Wed Apr 6 04:43:35 2011 @@ -0,0 +1,70 @@ + + + + + + +

About

+

+Welcome to pypi.python.org, the Python community's software hosting service. +

+ +

+Here you'll find a Python package to suit almost any need. +

+ +

+The project was started in 2002 by Richard Jones, +and has since grown to include the contributions of over a dozen Python +programmers, packages +and millions of downloads. +

+ +

+The Python Package Index (PyPI) is hosted by the Python Software Foundation (who run the python.org systems) but the project is community-run. Currently there's two maintainers, Richard and Martin von L?wis. +

+ +

+The index itself is written in Python but pre-dates modern Python web frameworks. + +

+ +

+To contact the admins, please +use the +Get help +or +Bug reports +links. +

+ +

To submit a package use +"python setup.py upload" +and to use a package from this index either +"pip install package" +or download, unpack and "python setup.py install" it. +

+ +

PyPI now provides a Mirror infrastructure to allow +users to continue downloading file even if pypi.python.org is unavailable.

+ +

+PyPI has also been known as The Python Cheese Shop (and indeed cheeseshop.python.org still works). +

+ +

And now for something completely different...

+

+Customer: Now then, some cheese please, my good man. +
+Owner: (lustily) Certainly, sir. What would you like? +
+Customer: Well, eh, how about a little red Leicester. +
+Owner: I'm, a-fraid we're fresh out of red Leicester, sir. +

+ +
+ Modified: trunk/pypi/webui.py ============================================================================== --- trunk/pypi/webui.py (original) +++ trunk/pypi/webui.py Wed Apr 6 04:43:35 2011 @@ -572,7 +572,7 @@ password_reset role role_form list_classifiers login logout files file_upload show_md5 doc_upload claim openid openid_return dropid rate comment addcomment delcomment clear_auth addkey delkey lasthour - json gae_file'''.split(): + json gae_file about'''.split(): getattr(self, action)() else: #raise NotFound, 'Unknown action %s' % action @@ -676,6 +676,9 @@ def home(self, nav_current='home'): self.write_template('home.pt', title='PyPI') + def about(self, nav_current='home'): + self.write_template('about.pt', title='About PyPI') + def rss(self): """Dump the last N days' updates as an RSS feed. """ From python-checkins at python.org Wed Apr 6 04:48:49 2011 From: python-checkins at python.org (richard) Date: Wed, 6 Apr 2011 04:48:49 +0200 (CEST) Subject: [Pypi-checkins] r900 - trunk/pypi/templates Message-ID: <3Q4BMP00QSzSj6@mail.python.org> Author: richard Date: Wed Apr 6 04:48:48 2011 New Revision: 900 Modified: trunk/pypi/templates/about.pt Log: tweaks Modified: trunk/pypi/templates/about.pt ============================================================================== --- trunk/pypi/templates/about.pt (original) +++ trunk/pypi/templates/about.pt Wed Apr 6 04:48:48 2011 @@ -17,19 +17,18 @@

-The project was started in 2002 by Richard Jones, +The project was started in 2002, and has since grown to include the contributions of over a dozen Python programmers, packages and millions of downloads.

-The Python Package Index (PyPI) is hosted by the Python Software Foundation (who run the python.org systems) but the project is community-run. Currently there's two maintainers, Richard and Martin von L?wis. +The Python Package Index (PyPI) is hosted by the Python Software Foundation (who run the python.org systems) but the project is community-run. Currently there's two maintainers, Richard Jones and Martin von L?wis.

-The index itself is written in Python but pre-dates modern Python web frameworks. - +The index itself is written in Python but pre-dates modern Python web frameworks (more detail).

From python-checkins at python.org Wed Apr 6 04:49:32 2011 From: python-checkins at python.org (richard) Date: Wed, 6 Apr 2011 04:49:32 +0200 (CEST) Subject: [Pypi-checkins] r901 - trunk/pypi/templates Message-ID: <3Q4BND511Sz7LjM@mail.python.org> Author: richard Date: Wed Apr 6 04:49:32 2011 New Revision: 901 Modified: trunk/pypi/templates/about.pt Log: tweaks Modified: trunk/pypi/templates/about.pt ============================================================================== --- trunk/pypi/templates/about.pt (original) +++ trunk/pypi/templates/about.pt Wed Apr 6 04:49:32 2011 @@ -25,13 +25,6 @@

The Python Package Index (PyPI) is hosted by the Python Software Foundation (who run the python.org systems) but the project is community-run. Currently there's two maintainers, Richard Jones and Martin von L?wis. -

- -

-The index itself is written in Python but pre-dates modern Python web frameworks (more detail). -

- -

To contact the admins, please use the Get help @@ -40,6 +33,10 @@ links.

+

+The index itself is written in Python but pre-dates modern Python web frameworks (more detail). +

+

To submit a package use "python setup.py upload" and to use a package from this index either From python-checkins at python.org Wed Apr 6 20:32:53 2011 From: python-checkins at python.org (martin.von.loewis) Date: Wed, 6 Apr 2011 20:32:53 +0200 (CEST) Subject: [Pypi-checkins] r902 - trunk/pypi Message-ID: <3Q4bJj2CTVz7Lkw@mail.python.org> Author: martin.von.loewis Date: Wed Apr 6 20:32:52 2011 New Revision: 902 Modified: trunk/pypi/mirrors.txt Log: Update C IP address. Modified: trunk/pypi/mirrors.txt ============================================================================== --- trunk/pypi/mirrors.txt (original) +++ trunk/pypi/mirrors.txt Wed Apr 6 20:32:52 2011 @@ -1,4 +1,4 @@ b: 141.89.226.2, martin at v.loewis.de -c: h1606280.stratoserver.net, pypi at zopyx.com +c: 178.77.74.179, pypi at zopyx.com d: pypi.websushi.org, jezdez+pypi at enn.io From python-checkins at python.org Wed Apr 6 20:34:51 2011 From: python-checkins at python.org (martin.von.loewis) Date: Wed, 6 Apr 2011 20:34:51 +0200 (CEST) Subject: [Pypi-checkins] r903 - in trunk/pypi: . templates Message-ID: <3Q4bLz3p6Vz7Llg@mail.python.org> Author: martin.von.loewis Date: Wed Apr 6 20:34:51 2011 New Revision: 903 Removed: trunk/pypi/templates/comment.pt Modified: trunk/pypi/admin.py trunk/pypi/rpc.py trunk/pypi/store.py trunk/pypi/templates/display.pt trunk/pypi/templates/pkg_edit.pt trunk/pypi/webui.py Log: Remove rating feature. Modified: trunk/pypi/admin.py ============================================================================== --- trunk/pypi/admin.py (original) +++ trunk/pypi/admin.py Wed Apr 6 20:34:51 2011 @@ -97,15 +97,6 @@ print "Deleting", path shutil.rmtree(path) -def send_comments(store): - '''Send out comments to package owners. Normally, this will - be done automatically, but the very first comments had not been sent.''' - import webui - c = store.get_cursor() - c.execute("select name, version, user_name, message from ratings where message!=''") - for package, version, author, comment in c.fetchall(): - webui.comment_email(store, package, version, author, comment) - def merge_user(store, old, new): c = store.get_cursor() if not store.get_user(old): Modified: trunk/pypi/rpc.py ============================================================================== --- trunk/pypi/rpc.py (original) +++ trunk/pypi/rpc.py Wed Apr 6 20:34:51 2011 @@ -24,7 +24,6 @@ self.register_function(updated_releases) self.register_function(changelog) self.register_function(post_cheesecake_for_release) - self.register_function(ratings) self.register_introspection_functions() self.register_multicall_functions() @@ -120,16 +119,4 @@ store.save_cheesecake_score(name, version, score_data) store.commit() -def ratings(store, name, version, since): - ratings, comments = store.all_ratings(name, version, since) - for i, r in enumerate(ratings): - r = list(r) - r[3] = int(time.mktime(r[3].timetuple())) - ratings[i] = tuple(r) - for i, c in enumerate(comments): - c = list(c) - c[5] = int(time.mktime(c[5].timetuple())) - comments[i] = c - return ratings, comments - handle_request = RequestHandler() Modified: trunk/pypi/store.py ============================================================================== --- trunk/pypi/store.py (original) +++ trunk/pypi/store.py Wed Apr 6 20:34:51 2011 @@ -788,17 +788,6 @@ project_urls.append(project[0].split(',')) return project_urls - def get_package_comments(self, name): - cursor = self.get_cursor() - safe_execute(cursor, 'select comments from packages where name=%s', - [name]) - return cursor.fetchall()[0][0] - - def set_package_comments(self, name, value): - cursor = self.get_cursor() - safe_execute(cursor, 'update packages set comments=%s where name=%s', - [value, name]) - def get_unique(self, iterable): ''' Iterate over list of (name,version,date,summary) tuples and return list of unique (taking name and version into @@ -1082,168 +1071,6 @@ self.username, self.userip)) - def add_rating(self, name, version, rating, message): - '''Add a user rating of a release; message is optional''' - cursor = self.get_cursor() - safe_execute(cursor, '''insert into ratings (name, version, user_name, date, rating) - values(%s, %s, %s, current_timestamp, %s)''', (name, version, self.username, rating)) - if message: - safe_execute(cursor, '''insert into comments(rating, user_name, date, message, in_reply_to) - values(%s, %%s, current_timestamp, %%s, NULL)''' - % self.last_id('ratings'), - (self.username, message)) - safe_execute(cursor, '''insert into comments_journal(name, version, id, submitted_by, date, action) - values(%%s, %%s, %s, %%s, current_timestamp, %%s)''' - % self.last_id('comments'), - (name, version, self.username, 'add_rating %r' % message)) - - def copy_rating(self, name, fromversion, toversion): - '''Copy a user-s rating of package name from one version to another; - return the comment if any''' - cursor = self.get_cursor() - safe_execute(cursor, '''insert into ratings(name,version,user_name,date,rating) - select name,%s,user_name,current_timestamp,rating from ratings - where name=%s and version=%s and user_name=%s''', - (toversion, name, fromversion, self.username)) - # only copy comment, not follow-ups - safe_execute(cursor, 'select c.id from comments c, ratings r where c.rating=r.id and r.name=%s and r.version=%s', (name, fromversion)) - cid = cursor.fetchone() - if cid: - cid = cid[0] - safe_execute(cursor, '''insert into comments(rating, user_name, date, message, in_reply_to) - select %s, user_name, date, message, in_reply_to - from comments where id=%%s''' % self.last_id('ratings'), (cid,)) - safe_execute(cursor, '''insert into comments_journal(name, version, id, submitted_by, date, action) - values(%%s, %%s, %s, %%s, current_timestamp, %%s)''' % self.last_id('comments'), - (name, toversion, self.username, 'copied %s' % cid)) - - safe_execute(cursor, '''select message from comments - where id=%s''', (cid,)) - return cursor.fetchone()[0] - return None - - def remove_rating(self, name, version): - '''Remove a rating for the current user''' - cursor = self.get_cursor() - safe_execute(cursor, """insert into comments_journal(name, version, id, submitted_by, date, action) - select %s, %s, id, %s, current_timestamp, 'deleted' from ratings where user_name=%s and name=%s and version=%s""", - (name, version, self.username, self.username, name, version)) - safe_execute(cursor, "delete from ratings where user_name=%s and name=%s and version=%s", - (self.username, name, version)) - - _Rating=FastResultRow('id! date! user rating!') - _Comment=FastResultRow('id! rating! user date! message in_reply_to!') - def get_ratings(self, name, version): - '''Return ratings,messages for a release.''' - cursor = self.get_cursor() - safe_execute(cursor, '''select id, date, user_name, rating from ratings - where name=%s and version=%s order by date''', (name, version)) - res = cursor.fetchall() - safe_execute(cursor, '''select c.id, c.rating, c.user_name, c.date, c.message, c.in_reply_to from - ratings r, comments c where r.name=%s and r.version=%s and r.id=c.rating order by c.date''', (name, version)) - res2 = cursor.fetchall() - return Result(None, res, self._Rating), Result(None, res2, self._Comment) - - def get_comment(self, id): - '''Return a single comment.''' - cursor = self.get_cursor() - safe_execute(cursor, '''select id, rating, user_name, date, message, in_reply_to from - comments where id=%s''', (id,)) - res = cursor.fetchall() - if res: - return self._Comment(None, res[0]) - else: - return None - - def add_comment(self, msg, comment): - "Add a comment as a reply to msg. Return name and version" - cursor = self.get_cursor() - safe_execute(cursor, "select c.rating, r.name, r.version from comments c, ratings r where c.id=%s and c.rating=r.id", (msg,)) - rating, name, version = cursor.fetchone() - safe_execute(cursor, '''insert into comments(rating, user_name, date, message, in_reply_to) - values(%s,%s,current_timestamp,%s,%s)''', (rating, self.username, comment, msg)) - safe_execute(cursor, '''insert into comments_journal(name, version, id, submitted_by, date, action) - values(%%s, %%s, %s, %%s, current_timestamp, %%s)''' % self.last_id('comments'), - (name, version, self.username, 'add %s %r' % (msg, comment))) - return name, version - - def remove_comment(self, msg): - "Delete a comment and all its follow-ups." - cursor = self.get_cursor() - safe_execute(cursor, "select r.name, r.version from ratings r, comments c where c.id=%s and r.id=c.rating", (msg,)) - name, version = cursor.fetchone() - safe_execute(cursor, "delete from comments where id=%s", (msg,)) - safe_execute(cursor, '''insert into comments_journal(name, version, id, submitted_by, date, action) - values(%s, %s, %s, %s, current_timestamp, 'delete')''', (name, version, msg, self.username)) - - def has_package_comments(self, name): - "Return true if the package has any comments" - cursor = self.get_cursor() - safe_execute(cursor, """select r.name,count(*) from ratings r,comments c - where r.id=c.rating and r.name=%s group by(r.name)""", (name,)) - return len(cursor.fetchall()) > 0 - - def get_package_commenters(self, name): - "Return the email addresses of all commenters on a package." - cursor = self.get_cursor() - safe_execute(cursor, """select distinct(email) from ratings r,comments c,users u - where r.id=c.rating and r.name=%s and c.user_name=u.name""", (name,)) - return [r[0] for r in cursor.fetchall()] - - _AllRatings=FastResultRow('name version user_name date! rating! message') - def all_ratings(self, name, version, date): - '''Return all ratings since UTC timestamp. name and version may be None.''' - cursor = self.get_cursor() - date = time.strftime('%Y-%m-%d %H:%M:%S +0000', time.gmtime(date)) - if name: - if version: - safe_execute(cursor, '''select name, version, user_name, date, rating - from ratings where name=%s and version=%s and date > %s''', (name, version, date)) - ratings = cursor.fetchall() - safe_execute(cursor, '''select c.id, c.in_reply_to, r.name, r.version, - c.user_name, c.date, c.message - from ratings r, comments c where - r.name=%s and r.version=%s and r.id=c.rating and c.date > %s''', - (name, version, date)) - comments = cursor.fetchall() - else: - safe_execute(cursor, '''select name, version, user_name, date, rating - from ratings where name=%s and date > %s''', (name,date)) - ratings = cursor.fetchall() - safe_execute(cursor, '''select c.id, c.in_reply_to, r.name, r.version, - c.user_name, c.date, c.message - from ratings r, comments c where - r.name=%s and r.id=c.rating and c.date > %s''', - (name, date)) - comments = cursor.fetchall() - else: - safe_execute(cursor, '''select name, version, user_name, date, rating - from ratings where date > %s''', (date,)) - ratings = cursor.fetchall() - safe_execute(cursor, '''select c.id, c.in_reply_to, r.name, r.version, - c.user_name, c.date, c.message - from ratings r, comments c where - r.id=c.rating and c.date > %s''', (date,)) - comments = cursor.fetchall() - return ratings, comments - - def has_rating(self, name, version): - '''Check whether user has rated this release''' - cursor = self.get_cursor() - safe_execute(cursor, '''select count(*) from ratings - where user_name=%s and name=%s and version=%s''', (self.username, name, version)) - return cursor.fetchall()[0][0] - - def latest_rating(self, name): - '''Return the user-s latest rating on any release, or None.''' - cursor = self.get_cursor() - safe_execute(cursor, '''select version from ratings - where user_name=%s and name=%s order by date desc limit 1''', (self.username, name)) - res = cursor.fetchone() - if res: - res = res[0] - return res - def save_cheesecake_score(self, name, version, score_data): '''Save Cheesecake score for a release. ''' Deleted: /trunk/pypi/templates/comment.pt ============================================================================== --- /trunk/pypi/templates/comment.pt Wed Apr 6 20:34:51 2011 +++ (empty file) @@ -1,26 +0,0 @@ - - - - - - - - - -

The comment from said

-

Your reply: -

- - - -
- -
-

-

Note:If deletes the original message, your response to it will also get deleted.

- - Modified: trunk/pypi/templates/display.pt ============================================================================== --- trunk/pypi/templates/display.pt (original) +++ trunk/pypi/templates/display.pt Wed Apr 6 20:34:51 2011 @@ -244,72 +244,7 @@ -
-
-
- - - - -
-
-
-
- - - - - - - - - - - - - - -
Rate this release: 05 (best)
-
Review: (Please use the package's bug reporting channels
(trackers, mailing lists) for bug reports and requests for help
)
- - -
- -
-
- - - - - -
-
-
-
-

Log in to rate this package.

-
- -
- Package rating ( votes): - - -
    - -
  • - points: - votes -
  • -
    -
-

Ratings range from 0 to 5 (best).

-
- -
The package owner has disabled commenting on this package.
- -
-Package Comments: - -
+The rating feature has been removed. See catalog-sig for the discussion of this removal. Modified: trunk/pypi/templates/pkg_edit.pt ============================================================================== --- trunk/pypi/templates/pkg_edit.pt (original) +++ trunk/pypi/templates/pkg_edit.pt Wed Apr 6 20:34:51 2011 @@ -83,12 +83,6 @@ Auto-hide old releases
- Allow comments on releases - Allow comments on releases - - - (commenters will be notified about this change)

You can now host documentation at Modified: trunk/pypi/webui.py ============================================================================== --- trunk/pypi/webui.py (original) +++ trunk/pypi/webui.py Wed Apr 6 20:34:51 2011 @@ -115,32 +115,6 @@ reset for you.

''' + _prov -comment_message = '''Subject: New comment on %(package)s -From: PyPI operators <%(admin)s> -To: %(email)s -Reply-To: %(replyto)s - -[REPLIES TO THIS MESSAGE WILL NOT GO TO THE COMMENTER] -%(author)s has made the following comment on your package: - -%(comment)s - -You can read all comments on %(url)s. -''' - -rating_message = '''Subject: New rating on %(package)s -From: PyPI operators <%(admin)s> -To: %(email)s -Reply-To: %(replyto)s - -[REPLIES TO THIS MESSAGE WILL NOT GO TO THE COMMENTER] -%(author)s has rated your package as %(rating)s/5. Comment (optional): - -%(comment)s - -You can read all comments on %(url)s. -''' - chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' class Provider: @@ -169,31 +143,6 @@ else: PyPiPageTemplate = _PyPiPageTemplate -def comment_email(store, package, version, author, comment, rating, add_recipients): - emails = set() - recipients = [r['user_name'] for r in store.get_package_roles(package)] + add_recipients - for r in recipients: - email = store.get_user(r)['email'] - if email: - emails.add(email) - info = { - 'package': package, - 'admin': store.config.adminemail, - 'replyto': store.config.replyto, - 'author': author, - 'email': ','.join(emails), - 'comment': comment, - 'url': '%s/%s/%s' % (store.config.url, package, version), - 'rating': rating, - } - smtp = smtplib.SMTP(store.config.mailhost) - if rating is None: - message = comment_message % info - else: - message = rating_message % info - smtp.sendmail(store.config.adminemail, list(emails), message) - - class FileUpload: pass @@ -571,8 +520,7 @@ display register_form user_form forgotten_password_form user password_reset role role_form list_classifiers login logout files file_upload show_md5 doc_upload claim openid openid_return dropid - rate comment addcomment delcomment clear_auth addkey delkey lasthour - json gae_file about'''.split(): + clear_auth addkey delkey lasthour json gae_file about'''.split(): getattr(self, action)() else: #raise NotFound, 'Unknown action %s' % action @@ -1328,20 +1276,6 @@ latest_version_url = '%s/%s/%s' % (self.config.url, name, latest_version) - # Compute rating data - has_rated = self.loggedin and self.store.has_rating(name, version) - latest_rating = self.loggedin and self.store.latest_rating(name) - ratings, comments = self.store.get_ratings(name, version) - total = 0.0 - hcomments = [] # as a hierarchy - parent_comments = {} - tally = [0]*6 - rating_by_id = {} - for r in ratings: - rating_by_id[r['id']] = r - total += r['rating'] - tally[r['rating']] += 1 - # New metadata requires_dist = self.store.get_package_requires_dist(name, version) provides_dist = self.store.get_package_provides_dist(name, version) @@ -1349,51 +1283,6 @@ project_url = self.store.get_package_project_url(name, version) requires_external = self.store.get_package_requires_external(name, version) - for c in comments: - add = c, [] - parent_comments[c['id']] = add[1] - if c['in_reply_to']: - parent_comments[c['in_reply_to']].append(add) - else: - hcomments.append(add) - - def render_comments(comments, toplevel): - if not comments: - return [] - result = ["\n") - return result - comments = "".join(render_comments(hcomments, True)) - docs = '' for sub in [[], ['html']]: path = [self.config.database_docs_dir, name.encode('utf8')] + sub + ['index.html'] @@ -1410,14 +1299,8 @@ requires=values('requires'), provides=values('provides'), obsoletes=values('obsoletes'), - has_rated=has_rated, - latest_rating=latest_rating, files=files, docs=docs, - sum_ratings=total, - nr_ratings=len(ratings), - tally_ratings=tally, - comments=comments, categories=categories, is_py3k=is_py3k, roles=roles, @@ -1958,10 +1841,6 @@ value = self.form.has_key('autohide') self.store.set_package_autohide(name, value) - if self.form.has_key('submit_comments'): - value = self.form.has_key('comments') - self.store.set_package_comments(name, value) - # look up the current info about the releases releases = list(self.store.get_package_releases(name)) reldict = {} @@ -1989,104 +1868,8 @@ self.write_template('pkg_edit.pt', releases=releases, name=name, autohide=self.store.get_package_autohide(name), - comments=self.store.get_package_comments(name), title="Package '%s' Editing"%name) - def rate(self): - '''Add or delete a rating.''' - if not self.loggedin: - raise Unauthorised, "You need to login to rate" - - name = self.form.get('name', '') - version = self.form.get('version', '') - - if self.store.has_role('Owner', name) or self.store.has_role('Maintainer', name): - raise Forbidden, "You cannot rate your own packages" - - if not name or not version: - raise FormError, 'name and version required' - - if self.form.has_key('remove'): - if not self.store.has_rating(name, version): - raise Forbidden, "You did not rate that release" - self.store.remove_rating(name, version) - return self.display() - - if self.form.has_key('copy'): - if self.store.has_rating(name, version): - raise Forbidden, "You have already rated this release" - if not self.form.has_key('fromversion'): - raise FormError, "fromversion missing" - comment = self.store.copy_rating(name, self.form['fromversion'], version) - if comment: - comment_email(self.store, name, version, self.username, comment, - None, []) - return self.display() - if self.form.has_key('rate'): - if self.store.has_rating(name, version): - raise Forbidden, "You have already rated this release" - if not self.form.has_key('rating'): - raise FormError, "rating not provided" - message = self.form.get('comment', '').strip() - if message and not self.store.get_package_comments(name): - raise FormError, "package does not allow comments" - rating = self.form['rating'] - self.store.add_rating(name, version, rating, message) - comment_email(self.store, name, version, self.username, message, - rating, []) - return self.display() - - raise FormError, "Bad button" - - def comment(self): - 'Ask for a follow-up comment' - if not self.form.has_key('msg'): - raise FormError - comment = self.store.get_comment(self.form['msg']) - self.write_template('comment.pt', title='Reply to comment', - comment=comment) - - def addcomment(self): - 'Post a follow-up comment' - if not self.authenticated: - raise Unauthorised, "You need to be identified to post a comment" - if not self.form.has_key('msg') or not self.form.has_key('comment'): - raise FormError - msg = self.form['msg'] - comment = self.form['comment'] - orig = self.store.get_comment(msg) - if not orig: - raise FormError, "Invalid message" - if orig['user'] == self.username: - raise FormError, "You cannot respond to your own comments" - comment = comment.strip() - if not comment: - raise FormError, "You must fill in a comment" - - name, version = self.store.add_comment(msg, comment) - comment_email(self.store, name, version, self.username, comment, - None, [orig['user']]) - - return self.display(name=name, version=version) - - - def delcomment(self): - if not self.authenticated: - raise Unauthorised, \ - "You must be identified to delete a comment" - - if not self.form.has_key('msg'): - raise FormError - - msg = self.form['msg'] - comment = self.store.get_comment(msg) - if not comment: - raise FormError, "Invalid comment ID" - if comment['user'] != self.username or not comment['in_reply_to']: - raise FormError, "You cannot delete this comment" + comment['user'] - self.store.remove_comment(comment['id']) - return self.display() - def remove_pkg(self): ''' Remove a release or a whole package from the db. From python-checkins at python.org Thu Apr 7 15:19:49 2011 From: python-checkins at python.org (martin.von.loewis) Date: Thu, 7 Apr 2011 15:19:49 +0200 (CEST) Subject: [Pypi-checkins] r904 - trunk/pypi Message-ID: <3Q54K13m2Dz7LkH@mail.python.org> Author: martin.von.loewis Date: Thu Apr 7 15:19:49 2011 New Revision: 904 Modified: trunk/pypi/standalone.py trunk/pypi/webui.py Log: Support gzip encoding of simple pages. Modified: trunk/pypi/standalone.py ============================================================================== --- trunk/pypi/standalone.py (original) +++ trunk/pypi/standalone.py Thu Apr 7 15:19:49 2011 @@ -77,6 +77,9 @@ co = filter(None, self.headers.getheaders('cookie')) if co: env['HTTP_COOKIE'] = ', '.join(co) + ac = self.headers.getheader('accept-encoding') + if ac: + env['HTTP_ACCEPT_ENCODING'] = ac webui.WebUI(self, env).run() do_GET = do_POST = run Modified: trunk/pypi/webui.py ============================================================================== --- trunk/pypi/webui.py (original) +++ trunk/pypi/webui.py Thu Apr 7 15:19:49 2011 @@ -1,5 +1,5 @@ # system imports -import sys, os, urllib, cStringIO, traceback, cgi, binascii +import sys, os, urllib, cStringIO, traceback, cgi, binascii, gzip import time, random, smtplib, base64, email, types, urlparse import re, zipfile, logging, shutil, Cookie, subprocess, hashlib from zope.pagetemplate.pagetemplatefile import PageTemplateFile @@ -567,10 +567,36 @@ html = ''.join(html) return html + def get_accept_encoding(self, supported): + accept_encoding = self.env.get('HTTP_ACCEPT_ENCODING') + if not accept_encoding: + return None + accept_encoding = accept_encoding.split(',') + result = {} + for s in accept_encoding: + s = s.split(';') # gzip;q=0.6 + if len(s) == 1: + result[s[0].strip()] = 1.0 + else: + result[s[0].strip()] = float(s[1]) + best_prio = 0 + best_enc = None + for enc in supported: + if enc in result: + prio = result[enc] + elif '*' in result: + prio = result[enc] + else: + prio = 0 + if prio > best_prio: + best_prio, best_enc = prio, enc + return best_enc + def run_simple(self): path = self.env.get('PATH_INFO') if not path: raise Redirect, self.config.simple_script+'/' + accept_encoding = self.get_accept_encoding(('identity', 'gzip')) if path=='/': html = [] html.append("Simple Index") @@ -582,6 +608,14 @@ html.append("") html = ''.join(html) self.handler.send_response(200, 'OK') + if accept_encoding == 'gzip': + stream = cStringIO.StringIO() + # level 6 is supposedly what the gzip command line tool uses by default + f = gzip.GzipFile(mode='wb', fileobj=stream, compresslevel=6) + f.write(html) + f.close() + html = stream.getvalue() + self.handler.send_header('Content-encoding', 'gzip') self.handler.set_content_type('text/html; charset=utf-8') self.handler.send_header('Content-Length', str(len(html))) self.handler.end_headers() From python-checkins at python.org Thu Apr 7 15:25:20 2011 From: python-checkins at python.org (martin.von.loewis) Date: Thu, 7 Apr 2011 15:25:20 +0200 (CEST) Subject: [Pypi-checkins] r905 - trunk/pypi Message-ID: <3Q54RN3hK8z7Lkk@mail.python.org> Author: martin.von.loewis Date: Thu Apr 7 15:25:20 2011 New Revision: 905 Modified: trunk/pypi/webui.py Log: Compress individual pages as well. Modified: trunk/pypi/webui.py ============================================================================== --- trunk/pypi/webui.py (original) +++ trunk/pypi/webui.py Thu Apr 7 15:25:20 2011 @@ -610,7 +610,7 @@ self.handler.send_response(200, 'OK') if accept_encoding == 'gzip': stream = cStringIO.StringIO() - # level 6 is supposedly what the gzip command line tool uses by default + # level 6 is what the gzip command line tool uses by default f = gzip.GzipFile(mode='wb', fileobj=stream, compresslevel=6) f.write(html) f.close() @@ -629,6 +629,14 @@ if '/' not in path: html = self.simple_body(path) self.handler.send_response(200, 'OK') + if accept_encoding == 'gzip': + stream = cStringIO.StringIO() + # level 6 is what the gzip command line tool uses by default + f = gzip.GzipFile(mode='wb', fileobj=stream, compresslevel=6) + f.write(html) + f.close() + html = stream.getvalue() + self.handler.send_header('Content-encoding', 'gzip') self.handler.set_content_type('text/html; charset=utf-8') self.handler.send_header('Content-Length', str(len(html))) self.handler.end_headers() From python-checkins at python.org Fri Apr 8 02:46:27 2011 From: python-checkins at python.org (richard) Date: Fri, 8 Apr 2011 02:46:27 +0200 (CEST) Subject: [Pypi-checkins] r906 - trunk/pypi/templates Message-ID: <3Q5MYH3TKcz7LmK@mail.python.org> Author: richard Date: Fri Apr 8 02:46:27 2011 New Revision: 906 Modified: trunk/pypi/templates/index.pt Log: clarify "score" Modified: trunk/pypi/templates/index.pt ============================================================================== --- trunk/pypi/templates/index.pt (original) +++ trunk/pypi/templates/index.pt Fri Apr 8 02:46:27 2011 @@ -12,7 +12,7 @@
- + @@ -31,5 +31,8 @@
PackageScoreWeight* Description
+

*: occurrence of search term weighted by +field (name, summary, keywords, description, author, maintainer)

+ From python-checkins at python.org Fri Apr 8 03:12:43 2011 From: python-checkins at python.org (richard) Date: Fri, 8 Apr 2011 03:12:43 +0200 (CEST) Subject: [Pypi-checkins] r907 - in trunk/pypi: . templates Message-ID: <3Q5N7b1nw8z7Lnk@mail.python.org> Author: richard Date: Fri Apr 8 03:12:43 2011 New Revision: 907 Modified: trunk/pypi/pypi.css trunk/pypi/templates/standard_template.pt Log: fix the mega-padding in the user-action box Modified: trunk/pypi/pypi.css ============================================================================== --- trunk/pypi/pypi.css (original) +++ trunk/pypi/pypi.css Fri Apr 8 03:12:43 2011 @@ -279,4 +279,8 @@ margin-top:3px; } - +#document-navigation ul +{ + /* bit too squeezy with the default large padding */ + margin: 0px; +} Modified: trunk/pypi/templates/standard_template.pt ============================================================================== --- trunk/pypi/templates/standard_template.pt (original) +++ trunk/pypi/templates/standard_template.pt Fri Apr 8 03:12:43 2011 @@ -11,7 +11,6 @@ <meta tal:attributes="content data/keywords" /> <meta tal:attributes="content data/description" /> - <link rel="stylesheet" tal:attributes="href string:${app/config/pydotorg}css/pypi.css" type="text/css"/> <link rel="alternate" type="application/rss+xml" title="RSS: 30 latest updates" href="http://www.python.org/pypi?:action=rss"/> <link media="screen" tal:attributes="href string:${app/config/pydotorg}styles/screen-switcher-default.css" type="text/css" id="screen-switcher-stylesheet" rel="stylesheet" /> <link media="screen" tal:attributes="href string:${app/config/pydotorg}styles/netscape4.css" type="text/css" rel="stylesheet" /> @@ -20,6 +19,9 @@ <link media="screen" tal:attributes="href string:${app/config/pydotorg}styles/defaultfonts.css" type="text/css" rel="alternate stylesheet" title="default fonts" /> <link rel="stylesheet" media="screen" href="/css/docutils.css" type="text/css"/> + <!-- allow pypi to override the standard pydotorg/docutils/etc. styles --> + <link rel="stylesheet" tal:attributes="href string:${app/config/pydotorg}css/pypi.css" type="text/css"/> + <metal:slot define-slot="head" /> <style type="text/css"> From python-checkins at python.org Fri Apr 8 08:18:32 2011 From: python-checkins at python.org (richard) Date: Fri, 8 Apr 2011 08:18:32 +0200 (CEST) Subject: [Pypi-checkins] r908 - trunk/pypi/templates Message-ID: <3Q5VwS1Z0tz7LmK@mail.python.org> Author: richard Date: Fri Apr 8 08:18:31 2011 New Revision: 908 Modified: trunk/pypi/templates/about.pt trunk/pypi/templates/home.pt Log: new home page format Modified: trunk/pypi/templates/about.pt ============================================================================== --- trunk/pypi/templates/about.pt (original) +++ trunk/pypi/templates/about.pt Fri Apr 8 08:18:31 2011 @@ -37,13 +37,21 @@ The index itself is written in Python but pre-dates modern Python web frameworks (<a href="http://wiki.python.org/moin/CheeseShopDev">more detail</a>). </p> -<p>To submit a package use +<p> +To submit a package use "<a href="http://wiki.python.org/moin/CheeseShopTutorial">python setup.py upload</a>" and to use a package from this index either "<a href="http://pip.openplans.org/">pip</a> install <i>package</i>" or download, unpack and "python setup.py install" it. </p> +<p> +Security: GPG and SSH ... XXX details? +</p> + +<p>You can access the data in PyPI from a program using either the per-package +JSON data or the XML-RPC interface.</p> + <p>PyPI now provides a <a href="/mirrors">Mirror infrastructure</a> to allow users to continue downloading file even if pypi.python.org is unavailable.</p> Modified: trunk/pypi/templates/home.pt ============================================================================== --- trunk/pypi/templates/home.pt (original) +++ trunk/pypi/templates/home.pt Fri Apr 8 08:18:31 2011 @@ -7,40 +7,67 @@ <metal:fill fill-slot="body"> <p>The Python Package Index is a repository of software for the Python programming language. There are currently -<strong tal:content="app/store/count_packages" /> -packages here. To contact the PyPI admins, please -use the +<strong tal:content="app/store/count_packages">12343</strong> +packages here. +<br> +To contact the PyPI admins, please use the <a href="http://sourceforge.net/tracker/?group_id=66150&atid=513504">Get help</a> or <a href="http://sourceforge.net/tracker/?group_id=66150&atid=513503">Bug reports</a> links. </p> -<p>To submit a package use -"<a href="http://wiki.python.org/moin/CheeseShopTutorial">python setup.py upload</a>" -and to use a package from this index either -"<a href="http://pip.openplans.org/">pip</a> install <i>package</i>" -or download, unpack and "python setup.py install" it.</p> - - <form tal:attributes="action app/url_path" id="searchform" - method="get" name="searchform"> - <input type="hidden" name=":action" value="search" /> - <div id="search"> - <input class="input-text" id="term" name="term" /> - <input class="input-button" type="submit" name="submit" - value="search" id="submit" /> - </div> - </form> -<ul> -<li><a tal:attributes="href python:app.link_action('browse')">Browse the -tree of packages</a></li> -<li><a tal:attributes="href python:app.link_action('submit_form')">Submit package information</a> -(note that you must <a tal:attributes="href python:app.link_action('register_form')"> -register to submit</a>)</li> -</ul> +<br clear="right"> + +<div id="document-navigation" style="width: 30%; float: left; display: inline;"> +<b>Get Packages</b> +<p style="margin-top: 0px; margin-left: 2px; margin-bottom: 4px;"> +To use a package from this index either +"<a href="http://www.pip-installer.org/en/latest/installing.html" class="vt-p">pip</a> install <i>package</i>" +or download, unpack and "python setup.py install" it. +<a href="http://pypi.python.org/pypi?%3Aaction=browse" class="vt-p">Browse the +tree of all packages</a>. Or just search using the box above. +</p> + +<!-- + <form id="searchform" method="get" name="searchform" action="./files/page.html" + style="margin-top: 0px; margin-left: 2px; margin-bottom: 4px;"> + <input type="hidden" name=":action" value="search"> + <div id="search"> + <input class="input-text" id="term" name="term" style="width: 70%"> + <input class="input-button" type="submit" name="submit" value="search" id="submit"> + </div> + </form> +--> +</div> + +<div id="document-navigation" style="width: 30%; float: left; display: inline;"> +<b>Package Authors</b> +<p style="margin-top: 0px; margin-left: 2px; margin-bottom: 4px;"> +To submit a package use +"<a href="http://wiki.python.org/moin/CheeseShopTutorial" class="vt-p">python setup.py upload</a>". +The index also hosts documentation. You may also submit a package using +<a href="/pypi/pypissh">SSH</a> or a +<a href="http://pypi.python.org/pypi?%3Aaction=submit_form" class="vt-p">web form</a>. +You must <a href="http://pypi.python.org/pypi?%3Aaction=register_form" class="vt-p"> +login to submit</a>. +</p> +</div> + +<div id="document-navigation" style="width: 30%; float: left; display: inline;"> +<b>Infrastructure</b> +<p style="margin-top: 0px; margin-left: 2px; margin-bottom: 4px;"> +To interoperate with the index +use the +<a href="http://wiki.python.org/moin/PyPiJson">JSON</a>, +<a href="http://wiki.python.org/moin/PyPiXmlRpc">XML-RPC</a> or +<a href="http://www.python.org/dev/peps/pep-0301/">HTTP</a> +interfaces. +Use the <a href="http://pypi.python.org/mirrors" class="vt-p">mirror infrastructure</a> to to download even if the primary site is unavailable. +</p> +</div> -<p>PyPI now provides a <a href="/mirrors">Mirror infrastructure</a> to allow -users to continue downloading file even if pypi.python.org is unavailable.</p> +<br clear="both"> <table class="list"> <tr><th>Updated</th><th>Package</th><th>Description</th></tr> From python-checkins at python.org Fri Apr 8 08:29:44 2011 From: python-checkins at python.org (richard) Date: Fri, 8 Apr 2011 08:29:44 +0200 (CEST) Subject: [Pypi-checkins] r909 - in trunk/pypi: . templates Message-ID: <3Q5W9N0Bv4z7Ljd@mail.python.org> Author: richard Date: Fri Apr 8 08:29:43 2011 New Revision: 909 Modified: trunk/pypi/templates/home.pt trunk/pypi/webui.py Log: fix XML; use clearer title; disabled content-disposition as it seems nicer without these days Modified: trunk/pypi/templates/home.pt ============================================================================== --- trunk/pypi/templates/home.pt (original) +++ trunk/pypi/templates/home.pt Fri Apr 8 08:29:43 2011 @@ -9,7 +9,7 @@ programming language. There are currently <strong tal:content="app/store/count_packages">12343</strong> packages here. -<br> +<br /> To contact the PyPI admins, please use the <a href="http://sourceforge.net/tracker/?group_id=66150&atid=513504">Get help</a> or @@ -17,7 +17,7 @@ links. </p> -<br clear="right"> +<br clear="right" /> <div id="document-navigation" style="width: 30%; float: left; display: inline;"> <b>Get Packages</b> @@ -67,7 +67,7 @@ </p> </div> -<br clear="both"> +<br clear="both" /> <table class="list"> <tr><th>Updated</th><th>Package</th><th>Description</th></tr> Modified: trunk/pypi/webui.py ============================================================================== --- trunk/pypi/webui.py (original) +++ trunk/pypi/webui.py Fri Apr 8 08:29:43 2011 @@ -664,7 +664,7 @@ self.wfile.write(sig) def home(self, nav_current='home'): - self.write_template('home.pt', title='PyPI') + self.write_template('home.pt', title='PyPI - the Python Package Index') def about(self, nav_current='home'): self.write_template('about.pt', title='About PyPI') @@ -1096,8 +1096,8 @@ self.handler.set_content_type('application/json; charset="UTF-8"') filename = '%s-%s.json'%(name.encode('ascii', 'replace'), version.encode('ascii', 'replace')) - self.handler.send_header('Content-Disposition', - 'attachment; filename=%s'%filename) +# self.handler.send_header('Content-Disposition', +# 'attachment; filename=%s'%filename) self.handler.end_headers() # write the JSONP extra crap if necessary s = json.dumps(d) From python-checkins at python.org Fri Apr 8 08:46:50 2011 From: python-checkins at python.org (richard) Date: Fri, 8 Apr 2011 08:46:50 +0200 (CEST) Subject: [Pypi-checkins] r910 - trunk/pypi/templates Message-ID: <3Q5WY657Gbz7LmK@mail.python.org> Author: richard Date: Fri Apr 8 08:46:50 2011 New Revision: 910 Modified: trunk/pypi/templates/home.pt Log: nicer content padding Modified: trunk/pypi/templates/home.pt ============================================================================== --- trunk/pypi/templates/home.pt (original) +++ trunk/pypi/templates/home.pt Fri Apr 8 08:46:50 2011 @@ -19,9 +19,9 @@ <br clear="right" /> -<div id="document-navigation" style="width: 30%; float: left; display: inline;"> +<div id="document-navigation" style="margin-left: 0px; width: 30%; float: left; display: inline; padding: 4px;"> <b>Get Packages</b> -<p style="margin-top: 0px; margin-left: 2px; margin-bottom: 4px;"> +<p> To use a package from this index either "<a href="http://www.pip-installer.org/en/latest/installing.html" class="vt-p">pip</a> install <i>package</i>" or download, unpack and "python setup.py install" it. @@ -41,9 +41,9 @@ --> </div> -<div id="document-navigation" style="width: 30%; float: left; display: inline;"> +<div id="document-navigation" style="width: 30%; float: left; display: inline; padding: 4px;"> <b>Package Authors</b> -<p style="margin-top: 0px; margin-left: 2px; margin-bottom: 4px;"> +<p> To submit a package use "<a href="http://wiki.python.org/moin/CheeseShopTutorial" class="vt-p">python setup.py upload</a>". The index also hosts documentation. You may also submit a package using @@ -54,9 +54,9 @@ </p> </div> -<div id="document-navigation" style="width: 30%; float: left; display: inline;"> +<div id="document-navigation" style="margin-right: 0px; width: 30%; float: left; display: inline; padding: 4px;"> <b>Infrastructure</b> -<p style="margin-top: 0px; margin-left: 2px; margin-bottom: 4px;"> +<p> To interoperate with the index use the <a href="http://wiki.python.org/moin/PyPiJson">JSON</a>, From python-checkins at python.org Fri Apr 8 08:48:53 2011 From: python-checkins at python.org (richard) Date: Fri, 8 Apr 2011 08:48:53 +0200 (CEST) Subject: [Pypi-checkins] r911 - trunk/pypi/templates Message-ID: <3Q5WbT1bB8z7Lkc@mail.python.org> Author: richard Date: Fri Apr 8 08:48:53 2011 New Revision: 911 Modified: trunk/pypi/templates/home.pt Log: remove bottom margin Modified: trunk/pypi/templates/home.pt ============================================================================== --- trunk/pypi/templates/home.pt (original) +++ trunk/pypi/templates/home.pt Fri Apr 8 08:48:53 2011 @@ -21,7 +21,7 @@ <div id="document-navigation" style="margin-left: 0px; width: 30%; float: left; display: inline; padding: 4px;"> <b>Get Packages</b> -<p> +<p style="margin-bottom: 0px"> To use a package from this index either "<a href="http://www.pip-installer.org/en/latest/installing.html" class="vt-p">pip</a> install <i>package</i>" or download, unpack and "python setup.py install" it. @@ -43,7 +43,7 @@ <div id="document-navigation" style="width: 30%; float: left; display: inline; padding: 4px;"> <b>Package Authors</b> -<p> +<p style="margin-bottom: 0px"> To submit a package use "<a href="http://wiki.python.org/moin/CheeseShopTutorial" class="vt-p">python setup.py upload</a>". The index also hosts documentation. You may also submit a package using @@ -56,7 +56,7 @@ <div id="document-navigation" style="margin-right: 0px; width: 30%; float: left; display: inline; padding: 4px;"> <b>Infrastructure</b> -<p> +<p style="margin-bottom: 0px"> To interoperate with the index use the <a href="http://wiki.python.org/moin/PyPiJson">JSON</a>, From python-checkins at python.org Fri Apr 8 09:01:46 2011 From: python-checkins at python.org (richard) Date: Fri, 8 Apr 2011 09:01:46 +0200 (CEST) Subject: [Pypi-checkins] r912 - trunk/pypi/templates Message-ID: <3Q5WtL4Tl8z7LkS@mail.python.org> Author: richard Date: Fri Apr 8 09:01:46 2011 New Revision: 912 Modified: trunk/pypi/templates/home.pt Log: typo Modified: trunk/pypi/templates/home.pt ============================================================================== --- trunk/pypi/templates/home.pt (original) +++ trunk/pypi/templates/home.pt Fri Apr 8 09:01:46 2011 @@ -63,7 +63,7 @@ <a href="http://wiki.python.org/moin/PyPiXmlRpc">XML-RPC</a> or <a href="http://www.python.org/dev/peps/pep-0301/">HTTP</a> interfaces. -Use the <a href="http://pypi.python.org/mirrors" class="vt-p">mirror infrastructure</a> to to download even if the primary site is unavailable. +Use the <a href="http://pypi.python.org/mirrors" class="vt-p">mirror infrastructure</a> to download even if the primary site is unavailable. </p> </div> From python-checkins at python.org Fri Apr 8 10:21:01 2011 From: python-checkins at python.org (richard) Date: Fri, 8 Apr 2011 10:21:01 +0200 (CEST) Subject: [Pypi-checkins] r913 - trunk/pypi/templates Message-ID: <3Q5Ydn3PSzz7Ljv@mail.python.org> Author: richard Date: Fri Apr 8 10:21:01 2011 New Revision: 913 Modified: trunk/pypi/templates/home.pt Log: add explicit pip download link; add documentation upload help link; add tutorial link; other tweaks Modified: trunk/pypi/templates/home.pt ============================================================================== --- trunk/pypi/templates/home.pt (original) +++ trunk/pypi/templates/home.pt Fri Apr 8 10:21:01 2011 @@ -24,9 +24,10 @@ <p style="margin-bottom: 0px"> To use a package from this index either "<a href="http://www.pip-installer.org/en/latest/installing.html" class="vt-p">pip</a> install <i>package</i>" +(<a href="http://www.pip-installer.org/en/latest/installing.html">get pip</a>) or download, unpack and "python setup.py install" it. -<a href="http://pypi.python.org/pypi?%3Aaction=browse" class="vt-p">Browse the -tree of all packages</a>. Or just search using the box above. +<a href="http://pypi.python.org/pypi?%3Aaction=browse" class="vt-p">Browse all packages</a> +or use the search box above. </p> <!-- @@ -45,12 +46,13 @@ <b>Package Authors</b> <p style="margin-bottom: 0px"> To submit a package use -"<a href="http://wiki.python.org/moin/CheeseShopTutorial" class="vt-p">python setup.py upload</a>". -The index also hosts documentation. You may also submit a package using -<a href="/pypi/pypissh">SSH</a> or a +"<a href="http://wiki.python.org/moin/CheeseShopTutorial" class="vt-p">python setup.py upload</a>" +(full <a href="http://wiki.python.org/moin/CheeseShopTutorial">tutorial</a>). +The index also <a href="http://wiki.python.org/moin/PyPiHostingDocumentation">hosts documentation</a>. +You may submit packages using +<a href="/pypi/pypissh">SSH</a> or the <a href="http://pypi.python.org/pypi?%3Aaction=submit_form" class="vt-p">web form</a>. -You must <a href="http://pypi.python.org/pypi?%3Aaction=register_form" class="vt-p"> -login to submit</a>. +You must <a href="http://pypi.python.org/pypi?%3Aaction=register_form" class="vt-p">register</a>. </p> </div> From python-checkins at python.org Fri Apr 8 11:47:15 2011 From: python-checkins at python.org (martin.von.loewis) Date: Fri, 8 Apr 2011 11:47:15 +0200 (CEST) Subject: [Pypi-checkins] r914 - trunk/pypi/templates Message-ID: <3Q5bYH16vPzMn6@mail.python.org> Author: martin.von.loewis Date: Fri Apr 8 11:47:14 2011 New Revision: 914 Modified: trunk/pypi/templates/display.pt trunk/pypi/templates/mirrors.pt Log: Add more mirrors. Modified: trunk/pypi/templates/display.pt ============================================================================== --- trunk/pypi/templates/display.pt (original) +++ trunk/pypi/templates/display.pt Fri Apr 8 11:47:14 2011 @@ -260,5 +260,9 @@ </tr> </table> +<b>Status of Python 3 support</b><br/> +<iframe tal:attributes="src +string:http://py3ksupport.appspot.com/pypi/${data/name}" width="800" height="500"/> + </metal:fill> </html> Modified: trunk/pypi/templates/mirrors.pt ============================================================================== --- trunk/pypi/templates/mirrors.pt (original) +++ trunk/pypi/templates/mirrors.pt Fri Apr 8 11:47:14 2011 @@ -15,6 +15,8 @@ <li><a href="http://b.pypi.python.org/">b.pypi.python.org</a></li> <li><a href="http://c.pypi.python.org/">c.pypi.python.org</a></li> <li><a href="http://d.pypi.python.org/">d.pypi.python.org</a></li> + <li><a href="http://e.pypi.python.org/">e.pypi.python.org</a></li> + <li><a href="http://f.pypi.python.org/">f.pypi.python.org</a></li> </ul> <p>More mirrors may get added over time; you can use the DNS CNAME record From python-checkins at python.org Fri Apr 8 11:47:53 2011 From: python-checkins at python.org (martin.von.loewis) Date: Fri, 8 Apr 2011 11:47:53 +0200 (CEST) Subject: [Pypi-checkins] r915 - trunk/pypi Message-ID: <3Q5bZ13mQJzMn6@mail.python.org> Author: martin.von.loewis Date: Fri Apr 8 11:47:53 2011 New Revision: 915 Modified: trunk/pypi/mirrors.txt Log: b is appengine, e is what used to be b, f is new. Modified: trunk/pypi/mirrors.txt ============================================================================== --- trunk/pypi/mirrors.txt (original) +++ trunk/pypi/mirrors.txt Fri Apr 8 11:47:53 2011 @@ -1,4 +1,5 @@ -b: 141.89.226.2, martin at v.loewis.de +b: appengine, martin at v.loewis.de c: 178.77.74.179, pypi at zopyx.com d: pypi.websushi.org, jezdez+pypi at enn.io - +e: 141.89.226.2, martin at v.loewis.de +f: services02.fe.rzob.gocept.net, support at gocept.com From python-checkins at python.org Sun Apr 10 20:26:01 2011 From: python-checkins at python.org (martin.von.loewis) Date: Sun, 10 Apr 2011 20:26:01 +0200 (CEST) Subject: [Pypi-checkins] r916 - trunk/pypi/templates Message-ID: <3Q72yx4y0Mz7Llp@mail.python.org> Author: martin.von.loewis Date: Sun Apr 10 20:26:01 2011 New Revision: 916 Modified: trunk/pypi/templates/display.pt Log: Remove py3ksupport again. Modified: trunk/pypi/templates/display.pt ============================================================================== --- trunk/pypi/templates/display.pt (original) +++ trunk/pypi/templates/display.pt Sun Apr 10 20:26:01 2011 @@ -260,9 +260,5 @@ </tr> </table> -<b>Status of Python 3 support</b><br/> -<iframe tal:attributes="src -string:http://py3ksupport.appspot.com/pypi/${data/name}" width="800" height="500"/> - </metal:fill> </html> From python-checkins at python.org Tue Apr 12 08:21:20 2011 From: python-checkins at python.org (richard) Date: Tue, 12 Apr 2011 08:21:20 +0200 (CEST) Subject: [Pypi-checkins] r917 - trunk/pypi Message-ID: <3Q7ynr3GHBz7Ljs@mail.python.org> Author: richard Date: Tue Apr 12 08:21:20 2011 New Revision: 917 Modified: trunk/pypi/pypi.css Log: commit those CSS changes I made Modified: trunk/pypi/pypi.css ============================================================================== --- trunk/pypi/pypi.css (original) +++ trunk/pypi/pypi.css Tue Apr 12 08:21:20 2011 @@ -279,8 +279,20 @@ margin-top:3px; } -#document-navigation ul -{ +#document-navigation ul { /* bit too squeezy with the default large padding */ margin: 0px; } + +#document-navigation a { + /* bit too squeezy with the default large padding */ + border-bottom: none; +} + +#document-navigation a:link { + text-decoration: underline; +} + +#document-navigation a:visited { + text-decoration: underline; +} From python-checkins at python.org Tue Apr 12 08:21:29 2011 From: python-checkins at python.org (richard) Date: Tue, 12 Apr 2011 08:21:29 +0200 (CEST) Subject: [Pypi-checkins] r918 - trunk/pypi Message-ID: <3Q7yp159DDz7Ljs@mail.python.org> Author: richard Date: Tue Apr 12 08:21:29 2011 New Revision: 918 Modified: trunk/pypi/webui.py Log: handle the q= bit Modified: trunk/pypi/webui.py ============================================================================== --- trunk/pypi/webui.py (original) +++ trunk/pypi/webui.py Tue Apr 12 08:21:29 2011 @@ -577,8 +577,11 @@ s = s.split(';') # gzip;q=0.6 if len(s) == 1: result[s[0].strip()] = 1.0 + elif s[1].startswith('q='): + result[s[0].strip()] = float(s[1][2:]) else: - result[s[0].strip()] = float(s[1]) + # not the correct format + result[s[0].strip()] = 1.0 best_prio = 0 best_enc = None for enc in supported: From python-checkins at python.org Wed Apr 20 02:09:37 2011 From: python-checkins at python.org (richard) Date: Wed, 20 Apr 2011 02:09:37 +0200 (CEST) Subject: [Pypi-checkins] r919 - trunk/pypi Message-ID: <3QDk9F3wWqz7Lmn@mail.python.org> Author: richard Date: Wed Apr 20 02:09:37 2011 New Revision: 919 Modified: trunk/pypi/config.ini.template trunk/pypi/store.py trunk/pypi/webui.py Log: prettify JSON output; try inline to maybe fix FF4 behaviour (thanks anatoly techtonik) Modified: trunk/pypi/config.ini.template ============================================================================== --- trunk/pypi/config.ini.template (original) +++ trunk/pypi/config.ini.template Wed Apr 20 02:09:37 2011 @@ -15,6 +15,7 @@ simple_script = /simple files_url = http://localhost/pypi_files rss_file = /tmp/pypi_rss.xml +packages_rss_file = /tmp/pypi_packages_rss.xml debug_mode = yes cheesecake_password = secret privkey = privkey Modified: trunk/pypi/store.py ============================================================================== --- trunk/pypi/store.py (original) +++ trunk/pypi/store.py Wed Apr 20 02:09:37 2011 @@ -844,6 +844,40 @@ def changelog_last_hour(self): return self.changelog(int(time.time())-3600) + _Latest_Packages = FastResultRow('name version submitted_date! summary') + def latest_packages(self, num=40): + '''Fetch "number" latest packages registered, youngest to oldest. + ''' + cursor = self.get_cursor() + # After the limited query below, we still have to do + # filtering. Assume that doubling the number of records + # we look for will still allow for sufficient room for + # filtering out unneeded records. If this was wrong, + # try again without limit. + limit = ' limit %s' % (2*num) + # This query is designed to run from the journals_latest_releases + # index, doing a reverse index scan, then lookups in the releases + # table to find the description and whether the package is hidden. + # Postgres will only do that if the number of expected results + # is "small". + statement = ''' + select j.name, j.version, j.submitted_date, r.summary + from (select name,version,submitted_date from journals + where version is not null and action='create' + order by submitted_date desc %s) j, releases r + where j.name=r.name and j.version=r.version + and not r._pypi_hidden order by j.submitted_date desc''' + #print ' '.join((statement % limit).split()) + safe_execute(cursor, statement % limit) + result = Result(None, self.get_unique(cursor.fetchall())[:num], + self._Latest_Releases) + if len(result) == num: + return result + # try again without limit + safe_execute(cursor, statement % '') + return Result(None, self.get_unique(cursor.fetchall())[:num], + self._Latest_Releases) + _Latest_Releases = FastResultRow('name version submitted_date! summary') def latest_releases(self, num=40): ''' Fetch "number" latest releases, youngest to oldest. Modified: trunk/pypi/webui.py ============================================================================== --- trunk/pypi/webui.py (original) +++ trunk/pypi/webui.py Wed Apr 20 02:09:37 2011 @@ -1097,13 +1097,14 @@ url['upload_time'] = url['upload_time'].strftime('%Y-%m-%dT%H:%M:%S') self.handler.send_response(200, "OK") self.handler.set_content_type('application/json; charset="UTF-8"') - filename = '%s-%s.json'%(name.encode('ascii', 'replace'), - version.encode('ascii', 'replace')) -# self.handler.send_header('Content-Disposition', -# 'attachment; filename=%s'%filename) + #filename = '%s-%s.json'%(name.encode('ascii', 'replace'), + # version.encode('ascii', 'replace')) + #self.handler.send_header('Content-Disposition', + # 'attachment; filename=%s'%filename) + self.handler.send_header('Content-Disposition', 'inline') self.handler.end_headers() # write the JSONP extra crap if necessary - s = json.dumps(d) + s = json.dumps(d, indent=4) callback = self.form.get('callback') if callback: s = '%s(%s)' % (callback, s) From python-checkins at python.org Wed Apr 27 17:38:18 2011 From: python-checkins at python.org (martin.von.loewis) Date: Wed, 27 Apr 2011 17:38:18 +0200 (CEST) Subject: [Pypi-checkins] r920 - trunk/pypi Message-ID: <3QKQRZ3Sd8z7LjP@mail.python.org> Author: martin.von.loewis Date: Wed Apr 27 17:38:18 2011 New Revision: 920 Modified: trunk/pypi/admin.py trunk/pypi/config.ini.template trunk/pypi/config.py trunk/pypi/store.py trunk/pypi/webui.py Log: Add key rotations support. Modified: trunk/pypi/admin.py ============================================================================== --- trunk/pypi/admin.py (original) +++ trunk/pypi/admin.py Wed Apr 27 17:38:18 2011 @@ -97,6 +97,34 @@ print "Deleting", path shutil.rmtree(path) +def keyrotate(config, store): + '''Rotate server key''' + key_dir = config.key_dir + prefixes = (os.path.join(key_dir, 'privkey'), os.path.join(key_dir,'pubkey')) + def rename_if_exists(oldsuffix, newsuffix): + for p in prefixes: + if os.path.exists(p+oldsuffix): + os.rename(p+oldsuffix, p+newsuffix) + # 1. generate new new key + os.system('openssl dsaparam -out /tmp/param 2048') + os.system('openssl gendsa -out %s/privkey.newnew /tmp/param' % key_dir) + os.system('openssl dsa -in %s/privkey.newnew -pubout -out %s/pubkey.newnew' % (key_dir, key_dir)) + os.unlink('/tmp/param') + # 2. delete old old key + for p in prefixes: + if os.path.exists(p+'.old'): + os.unlink(p+'.old') + # 3. rotate current key -> old key + rename_if_exists('', '.old') + # 4. rotate new key -> current key + rename_if_exists('.new', '') + # 5. rotate new new key -> new key + rename_if_exists('.newnew', '.new') + # 6. restart web server + os.system('/usr/sbin/apache2ctl graceful') + # 7. log rotation + store.log_keyrotate() + def merge_user(store, old, new): c = store.get_cursor() if not store.get_user(old): @@ -176,6 +204,8 @@ merge_user(*args) elif command == 'nuke_nested_lists': nuke_nested_lists(*args) + elif command == 'keyrotate': + keyrotate(config, *args) else: print "unknown command '%s'!"%command st.changed() Modified: trunk/pypi/config.ini.template ============================================================================== --- trunk/pypi/config.ini.template (original) +++ trunk/pypi/config.ini.template Wed Apr 27 17:38:18 2011 @@ -18,7 +18,7 @@ packages_rss_file = /tmp/pypi_packages_rss.xml debug_mode = yes cheesecake_password = secret -privkey = privkey +key_dir = . simple_sign_script = /serversig [logging] Modified: trunk/pypi/config.py ============================================================================== --- trunk/pypi/config.py (original) +++ trunk/pypi/config.py Wed Apr 27 17:38:18 2011 @@ -32,7 +32,7 @@ self.rss_file = c.get('webui', 'rss_file') self.debug_mode = c.get('webui', 'debug_mode') self.cheesecake_password = c.get('webui', 'cheesecake_password') - self.privkey = c.get('webui', 'privkey') + self.key_dir = c.get('webui', 'key_dir') self.simple_sign_script = c.get('webui', 'simple_sign_script') if c.has_option('webui', 'sshkeys_update'): self.sshkeys_update = c.get('webui', 'sshkeys_update') Modified: trunk/pypi/store.py ============================================================================== --- trunk/pypi/store.py (original) +++ trunk/pypi/store.py Wed Apr 27 17:38:18 2011 @@ -1815,6 +1815,16 @@ cursor = self.get_cursor() safe_execute(cursor, 'delete from openids where id=%s', (openid,)) + def log_keyrotate(self): + cursor = self.get_cursor() + date = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime()) + safe_execute(cursor, '''insert into journals ( + name, version, action, submitted_date, submitted_by, + submitted_from) values (%s, %s, %s, %s, %s, %s)''', + ('', '', 'keyrotate ', date, + None, None)) + + # # Handle the underlying database # Modified: trunk/pypi/webui.py ============================================================================== --- trunk/pypi/webui.py (original) +++ trunk/pypi/webui.py Wed Apr 27 17:38:18 2011 @@ -656,7 +656,7 @@ raise NotFound, path html = self.simple_body(path) if not self.privkey: - self.privkey = DSA.load_key(self.config.privkey) + self.privkey = DSA.load_key(os.path.join(self.config.privkey, 'privkey')) md = EVP.MessageDigest('sha1') md.update(html) digest = md.final() From python-checkins at python.org Wed Apr 27 21:41:08 2011 From: python-checkins at python.org (martin.von.loewis) Date: Wed, 27 Apr 2011 21:41:08 +0200 (CEST) Subject: [Pypi-checkins] r921 - trunk/pypi Message-ID: <3QKWqm5cZTz7LlM@mail.python.org> Author: martin.von.loewis Date: Wed Apr 27 21:41:08 2011 New Revision: 921 Modified: trunk/pypi/webui.py Log: Fix typo. Modified: trunk/pypi/webui.py ============================================================================== --- trunk/pypi/webui.py (original) +++ trunk/pypi/webui.py Wed Apr 27 21:41:08 2011 @@ -656,7 +656,7 @@ raise NotFound, path html = self.simple_body(path) if not self.privkey: - self.privkey = DSA.load_key(os.path.join(self.config.privkey, 'privkey')) + self.privkey = DSA.load_key(os.path.join(self.config.key_dir, 'privkey')) md = EVP.MessageDigest('sha1') md.update(html) digest = md.final()