Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add mapping between classifiers and versions #4

Merged
merged 9 commits into from Nov 16, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions MANIFEST.in
@@ -0,0 +1,6 @@
include README.rst

recursive-include docs *
recursive-include Products *

global-exclude *.pyc
8 changes: 8 additions & 0 deletions Products/PloneSoftwareCenter/browser/configure.zcml
Expand Up @@ -172,4 +172,12 @@
file="fancyzoom.js" file="fancyzoom.js"
/> />


<!-- pypi view -->
<page
class=".pypi_view.PackageIndexView"
for="Products.PloneSoftwareCenter.interfaces.ISoftwareCenterContent"
name="pypi_view"
permission="zope2.View"
/>

</configure> </configure>
75 changes: 50 additions & 25 deletions Products/PloneSoftwareCenter/browser/pypi.py
Expand Up @@ -3,6 +3,7 @@
""" """
import re import re
import hashlib import hashlib
from decimal import Decimal, InvalidOperation


from AccessControl import getSecurityManager from AccessControl import getSecurityManager
from AccessControl import Unauthorized from AccessControl import Unauthorized
Expand All @@ -24,7 +25,7 @@


from zope.annotation.interfaces import IAnnotations from zope.annotation.interfaces import IAnnotations
from zope.component import queryUtility from zope.component import queryUtility
from zope.event import notify from zope.event import notify


safe_filenames = re.compile(r'.+?\.(exe|tar\.gz|bz2|egg|rpm|deb|zip|tgz)$', re.I) safe_filenames = re.compile(r'.+?\.(exe|tar\.gz|bz2|egg|rpm|deb|zip|tgz)$', re.I)


Expand All @@ -36,7 +37,7 @@
'contactAddress': 'author_email', 'contactAddress': 'author_email',
'homepage': 'home_page', 'homepage': 'home_page',
} }

RELEASE_MAP = { RELEASE_MAP = {
'license': 'license', 'license': 'license',
# 'maturity': 'classifiers', # 'maturity': 'classifiers',
Expand Down Expand Up @@ -81,7 +82,7 @@ def _maybe_submit(self, project):
def _maybe_release(self, project, release): def _maybe_release(self, project, release):
"""Publishing the release, only of the project is published.""" """Publishing the release, only of the project is published."""
if not self._is_published(project): if not self._is_published(project):
return return
wf = self._get_portal_workflow() wf = self._get_portal_workflow()
if wf is None: if wf is None:
return return
Expand All @@ -94,13 +95,13 @@ def _maybe_release(self, project, release):
wf.doActionFor(release, 'release-alpha') wf.doActionFor(release, 'release-alpha')
elif bool(re.compile("([0-9]+(-)?b([0-9]*))").search(self.data['version'])): elif bool(re.compile("([0-9]+(-)?b([0-9]*))").search(self.data['version'])):
wf.doActionFor(release, 'release-beta') wf.doActionFor(release, 'release-beta')
elif bool(re.compile("([0-9]+(-)?rc([0-9]*))").search(self.data['version'])): elif bool(re.compile("([0-9]+(-)?rc([0-9]*))").search(self.data['version'])):
wf.doActionFor(release, 'release-candidate') wf.doActionFor(release, 'release-candidate')
else: else:
wf.doActionFor(release, 'release-final') wf.doActionFor(release, 'release-final')
except WorkflowException: except WorkflowException:
pass pass

def _validate_metadata(self, data): def _validate_metadata(self, data):
""" Validate the contents of the metadata. """ Validate the contents of the metadata.
""" """
Expand Down Expand Up @@ -145,7 +146,7 @@ def validate_version_predicates(col, sequence):


if data.has_key('classifiers'): if data.has_key('classifiers'):
data['classifiers'] = filter(filter_, data['classifiers']) data['classifiers'] = filter(filter_, data['classifiers'])

def _is_published(self, project): def _is_published(self, project):
"""returns true if not publised""" """returns true if not publised"""
wf = self._get_portal_workflow() wf = self._get_portal_workflow()
Expand All @@ -168,7 +169,7 @@ def _store_package(self, name, version, data):
return self.fail(str(e), 401) return self.fail(str(e), 401)


# Now, edit info # Now, edit info
self._edit_project(project, distutils_name=name, data=data, self._edit_project(project, distutils_name=name, data=data,
msg=msg) msg=msg)


# Submit project if not submitted yet. # Submit project if not submitted yet.
Expand All @@ -182,14 +183,14 @@ def _store_package(self, name, version, data):
if v in ('author_email',) and not value.startswith('mailto:'): if v in ('author_email',) and not value.startswith('mailto:'):
value = 'mailto:%s' % value value = 'mailto:%s' % value
release_data[k] = value release_data[k] = value

if not user.allowed(release.update): if not user.allowed(release.update):
return self.fail('Unauthorized', 401) return self.fail('Unauthorized', 401)


msg.append('Updated Release: %s' % version) msg.append('Updated Release: %s' % version)
release.update(**release_data) release.update(**release_data)



# Now, check if there's a 'download_url', then create a file # Now, check if there's a 'download_url', then create a file
# link # link
url = data.get('download_url') url = data.get('download_url')
Expand Down Expand Up @@ -221,19 +222,19 @@ def _store_package(self, name, version, data):


# notify we did add a file # notify we did add a file
notify(ObjectEditedEvent(rl)) notify(ObjectEditedEvent(rl))

# Make a release if not released yet. # Make a release if not released yet.
self._maybe_release(project, release) self._maybe_release(project, release)

return '\n'.join(msg) return '\n'.join(msg)

def _edit_project(self, project, distutils_name=None, def _edit_project(self, project, distutils_name=None,
data=None, msg=None): data=None, msg=None):
"""edit project infos""" """edit project infos"""
user = getSecurityManager().getUser() user = getSecurityManager().getUser()
if not user.allowed(project.update): if not user.allowed(project.update):
return self.fail('Unauthorized', 401) return self.fail('Unauthorized', 401)

if data is None: if data is None:
data = self.data data = self.data
project_data = {} project_data = {}
Expand Down Expand Up @@ -263,15 +264,15 @@ def _edit_project(self, project, distutils_name=None,
elif not (distutils_name == project.getDistutilsMainId()): elif not (distutils_name == project.getDistutilsMainId()):
secondary_ids = project.getDistutilsSecondaryIds() secondary_ids = project.getDistutilsSecondaryIds()
if distutils_name not in secondary_ids: if distutils_name not in secondary_ids:
secondary_ids = secondary_ids + (distutils_name,) secondary_ids = secondary_ids + (distutils_name,)
project.setDistutilsSecondaryIds(secondary_ids) project.setDistutilsSecondaryIds(secondary_ids)
else: else:
priority='m' priority='m'


# setting the title in case it is empty # setting the title in case it is empty
if project.Title() == '': if project.Title() == '':
project_data['title'] = distutils_name project_data['title'] = distutils_name

if priority == 'm': if priority == 'm':
project.update(**project_data) project.update(**project_data)


Expand All @@ -298,7 +299,7 @@ def _get_package(self, normalized_name, name, version, msg=None):
if project.getDistutilsMainId() == '': if project.getDistutilsMainId() == '':
project.setDistutilsMainId(normalized_name) project.setDistutilsMainId(normalized_name)
else: else:
# main id is taken, let's add it # main id is taken, let's add it
# as a secondary id # as a secondary id
secondids = project.getDistutilsSecondaryIds() secondids = project.getDistutilsSecondaryIds()
secondids = secondids + (normalized_name,) secondids = secondids + (normalized_name,)
Expand All @@ -315,7 +316,7 @@ def _get_package(self, normalized_name, name, version, msg=None):
else: else:
project_id = existing_projects[0] project_id = existing_projects[0]
project = sc[project_id] project = sc[project_id]

self._edit_project(project, msg=msg, distutils_name=name) self._edit_project(project, msg=msg, distutils_name=name)
versions = project.getVersionsVocab() versions = project.getVersionsVocab()
releases = project.getReleaseFolder() releases = project.getReleaseFolder()
Expand All @@ -327,7 +328,7 @@ def _get_package(self, normalized_name, name, version, msg=None):
i += 1 i += 1
cid = '%s-%d' (root_id, i) cid = '%s-%d' (root_id, i)


releases = project.injectFolder('PSCReleaseFolder', releases = project.injectFolder('PSCReleaseFolder',
id=cid) id=cid)


is_secondary = name != project.distutilsMainId is_secondary = name != project.distutilsMainId
Expand All @@ -347,8 +348,32 @@ def _get_package(self, normalized_name, name, version, msg=None):
(version, name)) (version, name))


release = releases._getOb(version) release = releases._getOb(version)
self._map_classifiers_to_compatibility(project, release)

return project, release return project, release


def _map_classifiers_to_compatibility(self, project, release):
versions = []
CLASSIFIER_BASE = 'Framework :: Plone :: '
supported_versions = [classifier[len(CLASSIFIER_BASE):] for classifier in \
self.request.form.get('classifiers', [])\
if classifier.startswith(CLASSIFIER_BASE)]

for supported_version in supported_versions:
try:
Decimal(supported_version)
except InvalidOperation:
continue
versions.append('Plone %s' % supported_version)

vocab = release.getCompatibilityVocab()
compats = []
for version in versions:
if version in vocab:
compats.append(version)
if compats:
release.setCompatibility(compats)

def _get_classifiers(self): def _get_classifiers(self):
"""returns current classifiers""" """returns current classifiers"""
sc = self.context sc = self.context
Expand Down Expand Up @@ -395,7 +420,7 @@ def verify(self, data=None):
""" """
if getSecurityManager().getUser() in (nobody,): if getSecurityManager().getUser() in (nobody,):
return self.fail('Unauthorized', 401) return self.fail('Unauthorized', 401)

if data is None: if data is None:
data = self.request.form data = self.request.form


Expand Down Expand Up @@ -433,7 +458,7 @@ def file_upload(self, data=None):
name, version) name, version)
except Unauthorized, e: except Unauthorized, e:
return self.fail(str(e), 401) return self.fail(str(e), 401)

# Submit project if not submitted yet. # Submit project if not submitted yet.
self._maybe_submit(project) self._maybe_submit(project)


Expand Down Expand Up @@ -461,9 +486,9 @@ def file_upload(self, data=None):
# XXX optimize for memory # XXX optimize for memory
content = content.read() content = content.read()


# nothing over 5M please # nothing over 100M please
size = len(content) size = len(content)
if size > 5*1024*1024: if size > 100*1024*1024:
err = 'Invalid file size: %s' % size err = 'Invalid file size: %s' % size
return self.fail(err) return self.fail(err)


Expand Down Expand Up @@ -502,7 +527,7 @@ def file_upload(self, data=None):
self._setPlatform(rf, filename) self._setPlatform(rf, filename)
# notify # notify
notify(ObjectEditedEvent(rf)) notify(ObjectEditedEvent(rf))

# Make a release if not released yet. # Make a release if not released yet.
self._maybe_release(project, release) self._maybe_release(project, release)


Expand Down Expand Up @@ -530,8 +555,8 @@ def normalizeName(self, text):
# Remove Products, as applicable # Remove Products, as applicable
if text.startswith('Products.'): if text.startswith('Products.'):
text = text[9:] text = text[9:]

# Convert to lowercase # Convert to lowercase
text = text.lower() text = text.lower()

return queryUtility(IFileNameNormalizer).normalize(text) return queryUtility(IFileNameNormalizer).normalize(text)
9 changes: 9 additions & 0 deletions Products/PloneSoftwareCenter/browser/pypi_view.pt
@@ -0,0 +1,9 @@
<div metal:use-macro="here/main_template/macros/master">

<div metal:fill-slot="main">

<h1>PyPI View</h1>

</div>

</div>
13 changes: 13 additions & 0 deletions Products/PloneSoftwareCenter/browser/pypi_view.py
@@ -0,0 +1,13 @@
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from zope.publisher.browser import BrowserPage


class PackageIndexView(BrowserPage):
"""
Display Plone releases from PyPI
"""

template = ViewPageTemplateFile('pypi_view.pt')

def __call__(self):
return self.template()
Expand Up @@ -22,6 +22,7 @@
<element value="plonesoftwarecenter_view"/> <element value="plonesoftwarecenter_view"/>
<element value="plonesoftwarecenter_ploneorg"/> <element value="plonesoftwarecenter_ploneorg"/>
<element value="psc_view_ploneorg"/> <element value="psc_view_ploneorg"/>
<element value="pypi_view"/>
</property> </property>
<property name="default_view_fallback">False</property> <property name="default_view_fallback">False</property>
<alias from="(Default)" to="(dynamic view)"/> <alias from="(Default)" to="(dynamic view)"/>
Expand Down
9 changes: 8 additions & 1 deletion docs/HISTORY.txt
@@ -1,7 +1,13 @@
Changelog Changelog
========= =========


1.6.4 (unreleased) 1.6.5 (unreleased)
------------------

- Nothing changed yet.


1.6.4 (2012-09-27)
------------------ ------------------
- Default content and output format added to the StringField installation_instructions in content/root.py [andreasma] - Default content and output format added to the StringField installation_instructions in content/root.py [andreasma]
- Change to psc_project_view.pt: more than one license will be displayed, if there is not only one for a release [andreasma] - Change to psc_project_view.pt: more than one license will be displayed, if there is not only one for a release [andreasma]
Expand All @@ -11,6 +17,7 @@ Changelog
- Update classifiers [toutpt] - Update classifiers [toutpt]
- Update TROVE.txt [toutpt] - Update TROVE.txt [toutpt]
- Update default available versions of Plone [toutpt] - Update default available versions of Plone [toutpt]
- Add mapping between classifiers and Plone release version when release using pypi api [toutpt]


1.6.3 (2011-06-19) 1.6.3 (2011-06-19)
------------------ ------------------
Expand Down
2 changes: 1 addition & 1 deletion setup.py
@@ -1,7 +1,7 @@
import os import os
from setuptools import setup, find_packages from setuptools import setup, find_packages


version = '1.6.3' version = '1.6.5.dev0'




def read(*rnames): def read(*rnames):
Expand Down