[Python-checkins] distutils2: Add a way to search for some packages by their names, using the simple index.

tarek.ziade python-checkins at python.org
Sun Aug 8 11:50:46 CEST 2010


tarek.ziade pushed 93ad7f1cf400 to distutils2:

http://hg.python.org/distutils2/rev/93ad7f1cf400
changeset:   456:93ad7f1cf400
user:        Alexis Metaireau <ametaireau at gmail.com>
date:        Fri Jul 23 19:35:34 2010 +0200
summary:     Add a way to search for some packages by their names, using the simple index.
files:       src/distutils2/index/simple.py, src/distutils2/tests/pypiserver/project_list/simple/index.html, src/distutils2/tests/test_index_simple.py

diff --git a/src/distutils2/index/simple.py b/src/distutils2/index/simple.py
--- a/src/distutils2/index/simple.py
+++ b/src/distutils2/index/simple.py
@@ -55,6 +55,25 @@
         return _socket_timeout
     return _socket_timeout
 
+def with_mirror_support():
+    """Decorator that makes the mirroring support easier"""
+    def wrapper(func):
+        def wrapped(self, *args, **kwargs):
+            try:
+                return func(self, *args, **kwargs)
+            except DownloadError:
+                # if an error occurs, try with the next index_url
+                if self._mirrors_tries >= self._mirrors_max_tries:
+                    try:
+                        self._switch_to_next_mirror()
+                    except KeyError:
+                       raise UnableToDownload("Tried all mirrors") 
+                else:
+                    self._mirrors_tries += 1
+                self._releases.clear()
+                return wrapped(self, *args, **kwargs)
+        return wrapped
+    return wrapper
 
 class Crawler(IndexClient):
     """Provides useful tools to request the Python Package Index simple API.
@@ -110,7 +129,20 @@
         # on one)
         self._processed_urls = []
         self._releases = {}
-  
+    
+    @with_mirror_support()
+    def search(self, name=None, **kwargs):
+        """Search the index for projects containing the given name"""
+        index = self._open_url(self.index_url)
+        
+        projectname = re.compile("""<a[^>]*>(.?[^<]*%s.?[^<]*)</a>""" % name,
+                                 flags=re.I)
+        matching_projects = []
+        for match in projectname.finditer(index.read()):
+           matching_projects.append(match.group(1))
+        
+        return matching_projects
+
     def _search_for_releases(self, requirements):
         """Search for distributions and return a ReleaseList object containing
         the results
@@ -275,26 +307,15 @@
             if self._is_browsable(url):
                 yield (url, False)
 
+    @with_mirror_support()
     def _process_index_page(self, name):
         """Find and process a PyPI page for the given project name.
 
         :param name: the name of the project to find the page
         """
-        try:
-            # Browse and index the content of the given PyPI page.
-            url = self.index_url + name + "/"
-            self._process_url(url, name)
-        except DownloadError:
-            # if an error occurs, try with the next index_url
-            if self._mirrors_tries >= self._mirrors_max_tries:
-                try:
-                    self._switch_to_next_mirror()
-                except KeyError:
-                   raise UnableToDownload("Tried all mirrors") 
-            else:
-                self._mirrors_tries += 1
-            self._releases.clear()
-            self._process_index_page(name)
+        # Browse and index the content of the given PyPI page.
+        url = self.index_url + name + "/"
+        self._process_url(url, name)
 
     @socket_timeout()
     def _open_url(self, url):
diff --git a/src/distutils2/tests/pypiserver/project_list/simple/index.html b/src/distutils2/tests/pypiserver/project_list/simple/index.html
new file mode 100644
--- /dev/null
+++ b/src/distutils2/tests/pypiserver/project_list/simple/index.html
@@ -0,0 +1,5 @@
+<a class="test" href="yeah">FooBar-bar</a>
+<a class="test" href="yeah">Foobar-baz</a>
+<a class="test" href="yeah">Baz-FooBar</a>
+<a class="test" href="yeah">Baz</a>
+<a class="test" href="yeah">Foo</a>
diff --git a/src/distutils2/tests/test_index_simple.py b/src/distutils2/tests/test_index_simple.py
--- a/src/distutils2/tests/test_index_simple.py
+++ b/src/distutils2/tests/test_index_simple.py
@@ -300,6 +300,15 @@
         self.assertIn('http://example.org/some/simpleurl', found_links)
         self.assertIn('http://example.org/some/download', found_links)
 
+    @use_pypi_server("project_list")
+    def test_search(self, server):
+        # we can search the index for some projects, on their names
+        # the case used no matters here
+        crawler = self._get_simple_crawler(server)
+        projects = crawler.search("Foobar")
+        self.assertListEqual(['FooBar-bar', 'Foobar-baz', 'Baz-FooBar'], 
+                             projects)
+
 def test_suite():
     return unittest.makeSuite(SimpleCrawlerTestCase)
 

--
Repository URL: http://hg.python.org/distutils2


More information about the Python-checkins mailing list