diff options
| author | Alexis Metaireau <ametaireau@gmail.com> | 2010-07-23 19:35:34 +0200 |
|---|---|---|
| committer | Alexis Metaireau <ametaireau@gmail.com> | 2010-07-23 19:35:34 +0200 |
| commit | 797b84aa70934280d76f265626fff51d0be56933 (patch) | |
| tree | 0fc74d77e2a27b1e26c5129784c0b6f3d4197b67 /src | |
| parent | fe947f1432505e07931ce318baee6afa40ac8f5e (diff) | |
| download | disutils2-797b84aa70934280d76f265626fff51d0be56933.tar.gz | |
Add a way to search for some packages by their names, using the simple index.
Also made a decorator (with_mirror_support) to support the mirror switch if
error occurs.
Diffstat (limited to 'src')
| -rw-r--r-- | src/distutils2/index/simple.py | 53 | ||||
| -rw-r--r-- | src/distutils2/tests/pypiserver/project_list/simple/index.html | 5 | ||||
| -rw-r--r-- | src/distutils2/tests/test_index_simple.py | 9 |
3 files changed, 51 insertions, 16 deletions
diff --git a/src/distutils2/index/simple.py b/src/distutils2/index/simple.py index 15efee0..64ad4dc 100644 --- a/src/distutils2/index/simple.py +++ b/src/distutils2/index/simple.py @@ -55,6 +55,25 @@ def socket_timeout(timeout=SOCKET_TIMEOUT): 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 @@ class Crawler(IndexClient): # 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 @@ class Crawler(IndexClient): 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 index 0000000..b36d728 --- /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 index c4086a3..489b1e1 100644 --- a/src/distutils2/tests/test_index_simple.py +++ b/src/distutils2/tests/test_index_simple.py @@ -300,6 +300,15 @@ class SimpleCrawlerTestCase(support.TempdirManager, unittest.TestCase): 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) |
