summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTill Maas <opensource@till.name>2014-02-06 10:26:50 +0100
committerTill Maas <opensource@till.name>2014-02-06 10:26:50 +0100
commit7095cd04dd77a5d25d9a3f9bd235436e6b48d326 (patch)
treea19a66521c6a862eaf15a25b6620ad547d356e21
parent7b095614e12c6c427b6968261633b8808f9299ba (diff)
downloadcnucnu-7095cd04dd77a5d25d9a3f9bd235436e6b48d326.tar.gz
cnucnu-7095cd04dd77a5d25d9a3f9bd235436e6b48d326.tar.xz
cnucnu-7095cd04dd77a5d25d9a3f9bd235436e6b48d326.zip
Package_list: Refactor alias handling
- Use one dictionary to handle alias information - Use generic function to resolve aliases - Add basic test cases for aliases
-rwxr-xr-xcnucnu/package_list.py263
-rwxr-xr-xcnucnu/tests/aliases_test.py78
-rwxr-xr-xruntests.sh5
3 files changed, 211 insertions, 135 deletions
diff --git a/cnucnu/package_list.py b/cnucnu/package_list.py
index 83c662f..07bd723 100755
--- a/cnucnu/package_list.py
+++ b/cnucnu/package_list.py
@@ -46,6 +46,134 @@ from cnucnu.scm import SCM
from cnucnu.wiki import MediaWiki
+def restore_underscore(name):
+ return name.replace("-", "_")
+
+
+ALIASES = {
+ "CPAN-DEFAULT": {
+ "prefix": "perl-",
+ "url": "http://search.cpan.org/dist/{name}/",
+ },
+ "DEBIAN-DEFAULT": {
+ "url": "http://ftp.debian.org/debian/pool/main/{name[0]}/{name}/",
+ },
+ "DEFAULT": {
+ "regex":
+ r"(?i)" # ignore case
+ r"\b{name}[-_]" # word-boundary, name and dash/underscore
+ r"(?:(?:src|source)[-_])?" # optional src or source string
+ r"([^-/_\s]*?" #
+ r"\d"
+ r"[^-/_\s]*?)"
+ r"(?:[-_.](?:src|source|orig))?"
+ r"\.(?:[jt]ar|t[bglx]z|tbz2|zip)\b"
+ },
+ "DIR-LISTING-DEFAULT": {
+ "regex": 'href="([0-9][0-9.]*)/"'
+ },
+ "DRUPAL-DEFAULT": {
+ "prefix": ["drupal6-", "drupal7-"],
+ "regex": "(?s)Recommended releases.*?>{raw_name[6]}.x-([^<]*)",
+ "url": "http://drupal.org/project/{name}",
+ },
+ "FM-DEFAULT": {
+ "regex": '<a href="/projects/[^/]*/releases/[0-9]*">([^<]*)</a>',
+ "url": "http://freshmeat.net/projects/{name}",
+ },
+ "GNU-DEFAULT": {
+ "url": "http://ftp.gnu.org/gnu/{name}/"
+ },
+ "GNOME-DEFAULT": {
+ "url": "http://download.gnome.org/sources/{name}/*/",
+ },
+ "GOOGLE-DEFAULT": {
+ "url": "http://code.google.com/p/{name}/downloads/list"
+ },
+ "HACKAGE-DEFAULT": {
+ "prefix": "ghc-",
+ "url": "http://hackage.haskell.org/package/{name}",
+ },
+ "LP-DEFAULT": {
+ "url": "https://launchpad.net/{name}/+download"
+ },
+ "NPM-DEFAULT": {
+ "prefix": "nodejs-",
+ "regex": '"version":"([0-9.]*?)"',
+ "url": "http://registry.npmjs.org/{name}",
+ },
+ "PEAR-DEFAULT": {
+ "name_modifiers": [restore_underscore],
+ "prefix": "php-pear-",
+ "url": "http://pear.php.net/package/{name}/download",
+ },
+ "PECL-DEFAULT": {
+ "name_modifiers": [restore_underscore],
+ "prefix": "php-pecl-",
+ "url": "http://pecl.php.net/package/{name}/download",
+ },
+ "PYPI-DEFAULT": {
+ "url": "https://pypi.python.org/packages/source/{name[0]}/{name}/",
+ },
+ "RUBYGEMS-DEFAULT": {
+ "prefix": "rubygem-",
+ "regex":
+ '"gem_uri":"http:\/\/rubygems.org\/gems\/{name}-([0-9.]*?)\.gem"',
+ "url": "http://rubygems.org/api/v1/gems/{name}.json",
+ },
+ "SF-DEFAULT": {
+ "url": "http://sourceforge.net/api/file/index/project-name/{name}/"
+ "mtime/desc/limit/200/rss"
+ },
+}
+
+
+def unalias(name, value, what):
+ """ Unalias `value` for package `name`.
+ :param what: "regex" or "url"
+ :returns: Unaliased value
+ """
+
+ raw_name = name
+
+ # allow name override with e.g. DEFAULT:othername
+ if value and ":" in value:
+ alias, name_override = value.split(":", 1)
+ if alias in ALIASES.keys():
+ value = alias
+ name = name_override
+ else:
+ name_override = False
+
+ # Use while loop to allow to fall back to DEFAULT value
+ while value in ALIASES.keys():
+ if not name_override:
+ prefixes = ALIASES[value].get("prefix", [])
+ if isinstance(prefixes, basestring):
+ prefixes = [prefixes]
+ for prefix in prefixes:
+ if name.startswith(prefix):
+ name = name[len(prefix):]
+
+ name_modifiers = ALIASES[value].get("name_modifiers", [])
+ for modifier in name_modifiers:
+ name = modifier(name)
+
+ # Use DEFAULT regex if None is defined
+ value = ALIASES[value].get(what, "DEFAULT")
+ if what == "regex":
+ format_values = {"name": re.escape(name),
+ "raw_name": re.escape(raw_name)}
+ elif what == "url":
+ format_values = {"name": urllib.quote(name, safe=""),
+ "raw_name": urllib.quote(raw_name, safe="")}
+ else:
+ raise NotImplementedError("what needs ot be 'regex' or 'url'")
+
+ value = value.format(**format_values)
+ return value
+
+
class Repository:
def __init__(self, name="", path=""):
if not (name and path):
@@ -145,73 +273,7 @@ class Package(object):
def set_regex(self, regex):
self.raw_regex = regex
-
- name = self.name
- # allow name override with e.g. DEFAULT:othername
- if regex:
- name_override = re.match(r"^((?:FM-)?DEFAULT)(?::(.+))$", regex)
- if name_override:
- regex = name_override.group(1)
- name = name_override.group(2)
-
- # use DEFAULT regex but alter the name
- if regex == "CPAN-DEFAULT":
- # strip "perl-" prefix only if name was not overridden
- if not name_override and name.startswith("perl-"):
- name = name[len("perl-"):]
- regex = "DEFAULT"
- elif regex == "HACKAGE-DEFAULT":
- # strip "ghc-" prefix only if name was not overridden
- if not name_override and name.startswith("ghc-"):
- name = name[len("ghc-"):]
- regex = "DEFAULT"
- elif regex == "PEAR-DEFAULT":
- # strip "php-pear-" prefix only if name was not overridden
- if not name_override and name.startswith("php-pear-"):
- name = name[len("php-pear-"):].replace("-", "_")
- regex = "DEFAULT"
- elif regex == "PECL-DEFAULT":
- # strip "php-pecl-" prefix only if name was not overridden
- if not name_override and name.startswith("php-pecl-"):
- name = name[len("php-pecl-"):].replace("-", "_")
- regex = "DEFAULT"
- elif regex == "RUBYGEMS-DEFAULT":
- # strip "rubygem-" prefix only if name was not overridden
- if not name_override and name.startswith("rubygem-"):
- name = name[len("rubygem-"):]
- elif regex == "NPM-DEFAULT":
- # strip "nodejs-" prefix only if name was not overridden
- if not name_override and name.startswith("nodejs-"):
- name = name[len("nodejs-"):]
-
- # no elif here, because the previous regex aliases are only for name
- # altering
- if regex == "DEFAULT":
- regex = (
- r"(?i)" # ignore case
- r"\b%(name)s[-_]" # word-boundary, name and dash/underscore
- r"(?:(?:src|source)[-_])?" # optional src or source string
- r"([^-/_\s]*?" #
- r"\d"
- r"[^-/_\s]*?)"
- r"(?:[-_.](?:src|source|orig))?"
- r"\.(?:[jt]ar|t[bglx]z|tbz2|zip)\b" % {'name': re.escape(name)}
- )
- elif regex == "DRUPAL-DEFAULT":
- branch = name[6]
- regex = \
- "(?s)Recommended releases.*?>{0}.x-([^<]*)".format(branch)
- elif regex == "FM-DEFAULT":
- regex = '<a href="/projects/[^/]*/releases/[0-9]*">([^<]*)</a>'
- elif regex == "DIR-LISTING-DEFAULT":
- regex = 'href="([0-9][0-9.]*)/"'
- elif regex == "RUBYGEMS-DEFAULT":
- regex = \
- '"gem_uri":"http:\/\/rubygems.org\/gems\/%s-([0-9.]*?)\.gem"' \
- % re.escape(name)
- elif regex == "NPM-DEFAULT":
- regex = '"version":"([0-9.]*?)"'
-
+ regex = unalias(self.name, regex, "regex")
self.__regex = regex
self._invalidate_caches()
@@ -219,72 +281,7 @@ class Package(object):
def set_url(self, url):
self.raw_url = url
-
- name = self.name
- # allow name override with e.g. SF-DEFAULT:othername
- if url:
- name_override = re.match(
- r"^((?:SF|FM|GNU|CPAN|DRUPAL|HACKAGE|DEBIAN|GOOGLE|PEAR|PECL|"
- "PYPI|LP|GNOME|RUBYGEMS)-DEFAULT)(?::(.+))$", url)
- if name_override:
- url = name_override.group(1)
- name = name_override.group(2)
- name = urllib.quote(name, safe='')
- if url == "SF-DEFAULT":
- url = "http://sourceforge.net/api/file/index/project-name/%s/" \
- "mtime/desc/limit/200/rss" % name
- elif url == "FM-DEFAULT":
- url = "http://freshmeat.net/projects/%s" % name
- elif url == "GNU-DEFAULT":
- url = "http://ftp.gnu.org/gnu/%s/" % name
- elif url == "CPAN-DEFAULT":
- # strip "perl-" prefix only if name was not overridden
- if not name_override and name.startswith("perl-"):
- name = name[len("perl-"):]
- url = "http://search.cpan.org/dist/%s/" % name
- elif url == "DRUPAL-DEFAULT":
- if not name_override and (name.startswith("drupal7-") or
- name.startswith("drupal6-")):
- name = name[len("drupalX-"):]
- url = "http://drupal.org/project/{0}".format(name)
- elif url == "HACKAGE-DEFAULT":
- # strip "ghc-" prefix only if name was not overridden
- if not name_override and name.startswith("ghc-"):
- name = name[len("ghc-"):]
- url = "http://hackage.haskell.org/package/%s" % name
- elif url == "DEBIAN-DEFAULT":
- url = "http://ftp.debian.org/debian/pool/main/%s/%s/" % \
- (name[0], name)
- elif url == "GOOGLE-DEFAULT":
- url = "http://code.google.com/p/%s/downloads/list" % name
- elif url == "PYPI-DEFAULT":
- url = "https://pypi.python.org/packages/source/%s/%s/" % \
- (name[0], name)
- elif url == "PEAR-DEFAULT":
- # strip "php-pear-" prefix only if name was not overridden
- if not name_override and name.startswith("php-pear-"):
- name = name[len("php-pear-"):].replace("-", "_")
- url = "http://pear.php.net/package/%s/download" % name
- elif url == "PECL-DEFAULT":
- # strip "php-pecl-" prefix only if name was not overridden
- if not name_override and name.startswith("php-pecl-"):
- name = name[len("php-pecl-"):].replace("-", "_")
- url = "http://pecl.php.net/package/%s/download" % name
- elif url == "LP-DEFAULT":
- url = "https://launchpad.net/%s/+download" % name
- elif url == "GNOME-DEFAULT":
- url = "http://download.gnome.org/sources/%s/*/" % name
- elif url == "RUBYGEMS-DEFAULT":
- # strip "rubygem-" prefix only if name was not overridden
- if not name_override and name.startswith("rubygem-"):
- name = name[len("rubygem-"):]
- url = "http://rubygems.org/api/v1/gems/%s.json" % name
- elif url == "NPM-DEFAULT":
- # strip "nodejs-" prefix only if name was not overridden
- if not name_override and name.startswith("nodejs-"):
- name = name[len("nodejs-"):]
- url = "http://registry.npmjs.org/%s" % name
-
+ url = unalias(self.name, url, "url")
self.__url = url
self.html = None
diff --git a/cnucnu/tests/aliases_test.py b/cnucnu/tests/aliases_test.py
new file mode 100755
index 0000000..31d9e34
--- /dev/null
+++ b/cnucnu/tests/aliases_test.py
@@ -0,0 +1,78 @@
+#!/usr/bin/python -tt
+# vim: fileencoding=utf8 foldmethod=marker
+# {{{ License header: GPLv2+
+# This file is part of cnucnu.
+#
+# Cnucnu is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# Cnucnu is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cnucnu. If not, see <http://www.gnu.org/licenses/>.
+# }}}
+
+import unittest
+import sys
+sys.path.insert(0, '../..')
+
+from cnucnu.package_list import unalias, ALIASES
+
+
+class AliasTest(unittest.TestCase):
+ def testDefaultRegex(self):
+ regex = unalias("testname", "DEFAULT", "regex")
+ self.assertEqual(regex, ALIASES["DEFAULT"]["regex"].format(
+ name="testname"))
+
+ def testCPAN(self):
+ url = unalias("perl-test", "CPAN-DEFAULT", "url")
+ self.assertEqual(url, "http://search.cpan.org/dist/test/")
+
+ url = unalias("perl-test", "CPAN-DEFAULT:overridden-name", "url")
+ self.assertEqual(url, "http://search.cpan.org/dist/overridden-name/")
+
+ def testDebian(self):
+ url = unalias("testpackage", "DEBIAN-DEFAULT", "url")
+ self.assertEqual(
+ url,
+ "http://ftp.debian.org/debian/pool/main/t/testpackage/"
+ )
+
+ def testDrupalRegex(self):
+ regex = unalias("drupal6-testpackage", "DRUPAL-DEFAULT", "regex")
+ self.assertEqual(
+ regex,
+ "(?s)Recommended releases.*?>6.x-([^<]*)"
+ )
+
+ regex = unalias("drupal7-testpackage", "DRUPAL-DEFAULT", "regex")
+ self.assertEqual(
+ regex,
+ "(?s)Recommended releases.*?>7.x-([^<]*)"
+ )
+
+ def testDrupalUrl(self):
+ url = unalias("drupal6-testpkg", "DRUPAL-DEFAULT", "url")
+ self.assertEqual(
+ url,
+ "http://drupal.org/project/testpkg"
+ )
+
+ def testPHPPear(self):
+ url = unalias("php-pear-Test-Case", "PEAR-DEFAULT", "url")
+ self.assertEqual(
+ url,
+ "http://pear.php.net/package/Test_Case/download"
+ )
+
+
+if __name__ == "__main__":
+ suite = unittest.TestLoader().loadTestsFromTestCase(AliasTest)
+ unittest.TextTestRunner(verbosity=2).run(suite)
+ #unittest.main()
diff --git a/runtests.sh b/runtests.sh
index d51ee36..fb909b7 100755
--- a/runtests.sh
+++ b/runtests.sh
@@ -19,7 +19,8 @@
. setup-env.sh
-cnucnu/tests/package_list_test.py
-cnucnu/tests/mail_test.py
+cnucnu/tests/aliases_test.py
cnucnu/tests/config_test.py
cnucnu/tests/helper_test.py
+cnucnu/tests/mail_test.py
+cnucnu/tests/package_list_test.py