aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPJ Eby <distutils-sig@python.org>2005-10-19 03:00:35 +0000
committerPJ Eby <distutils-sig@python.org>2005-10-19 03:00:35 +0000
commit272fed819ba188ac5d6c0ceb9de6d7a8cb543a18 (patch)
tree53446d778b3cd6ac08470faa5ff28c168d406b40
parent741f1742fee6d55a6a278ff44215aaf0959381c5 (diff)
downloadexternal_python_setuptools-272fed819ba188ac5d6c0ceb9de6d7a8cb543a18.tar.gz
external_python_setuptools-272fed819ba188ac5d6c0ceb9de6d7a8cb543a18.tar.bz2
external_python_setuptools-272fed819ba188ac5d6c0ceb9de6d7a8cb543a18.zip
Added "--allow-hosts" option to restrict downloading and spidering to
a specified list of server glob patterns. --HG-- branch : setuptools extra : convert_revision : svn%3A6015fed2-1504-0410-9fe1-9d1591cc4771/sandbox/trunk/setuptools%4041266
-rwxr-xr-xEasyInstall.txt22
-rwxr-xr-xsetuptools/command/easy_install.py18
-rwxr-xr-xsetuptools/package_index.py44
3 files changed, 52 insertions, 32 deletions
diff --git a/EasyInstall.txt b/EasyInstall.txt
index 3efc80f1..9709adfe 100755
--- a/EasyInstall.txt
+++ b/EasyInstall.txt
@@ -692,6 +692,26 @@ Command-Line Options
tools that wrap eggs in a platform-specific packaging system. (We don't
recommend that you use it for anything else.)
+``--allow-hosts=PATTERNS, -H PATTERNS`` (New in 0.6a6)
+ Restrict downloading and spidering to hosts matching the specified glob
+ patterns. E.g. ``-H *.python.org`` restricts web access so that only
+ packages listed and downloadable from machines in the ``python.org``
+ domain. The glob patterns must match the *entire* user/host/port section of
+ the target URL(s). For example, ``*.python.org`` will NOT accept a URL
+ like ``http://python.org/foo`` or ``http://www.python.org:8080/``.
+ Multiple patterns can be specified by separting them with commas. The
+ default pattern is ``*``, which matches anything.
+
+ In general, this option is mainly useful for blocking EasyInstall's web
+ access altogether (e.g. ``-Hlocalhost``), or to restrict it to an intranet
+ or other trusted site. EasyInstall will do the best it can to satisfy
+ dependencies given your host restrictions, but of course can fail if it
+ can't find suitable packages. EasyInstall displays all blocked URLs, so
+ that you can adjust your ``--allow-hosts`` setting if it is more strict
+ than you intended. Some sites may wish to define a restrictive default
+ setting for this option in their `configuration files`_, and then manually
+ override the setting on the command line as needed.
+
Non-Root Installation
---------------------
@@ -850,7 +870,7 @@ Known Issues
that makes the PYTHONPATH-based approach work with .pth files, so that you
can get the full EasyInstall feature set on such installations.
- * Added ``--no-deps`` option.
+ * Added ``--no-deps`` and ``--allow-hosts`` options.
* Improved Windows ``.exe`` script wrappers so that the script can have the
same name as a module without confusing Python.
diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py
index c076a5fd..ad19a732 100755
--- a/setuptools/command/easy_install.py
+++ b/setuptools/command/easy_install.py
@@ -43,7 +43,6 @@ class easy_install(Command):
"""Manage a download/build/install process"""
description = "Find/get/install Python packages"
-
command_consumes_arguments = True
user_options = [
@@ -71,6 +70,7 @@ class easy_install(Command):
('site-dirs=','S',"list of directories where .pth files work"),
('editable', 'e', "Install specified packages in editable form"),
('no-deps', 'N', "don't install dependencies"),
+ ('allow-hosts=', 'H', "pattern(s) that hostnames must match"),
]
boolean_options = [
'zip-ok', 'multi-version', 'exclude-scripts', 'upgrade', 'always-copy',
@@ -89,7 +89,7 @@ class easy_install(Command):
self.args = None
self.optimize = self.record = None
self.upgrade = self.always_copy = self.multi_version = None
- self.editable = self.no_deps = None
+ self.editable = self.no_deps = self.allow_hosts = None
self.root = None
# Options not specifiable via command line
@@ -177,9 +177,15 @@ class easy_install(Command):
for path_item in self.install_dir, normalize_path(self.script_dir):
if path_item not in self.shadow_path:
self.shadow_path.insert(0, path_item)
+
+ if self.allow_hosts is not None:
+ hosts = [s.strip() for s in self.allow_hosts.split(',')]
+ else:
+ hosts = ['*']
+
if self.package_index is None:
self.package_index = self.create_index(
- self.index_url, search_path = self.shadow_path
+ self.index_url, search_path = self.shadow_path, hosts=hosts
)
self.local_index = Environment(self.shadow_path)
@@ -202,7 +208,6 @@ class easy_install(Command):
"Can't use both --delete-conflicting and "
"--ignore-conflicts-at-my-risk at the same time"
)
-
if self.editable and not self.build_directory:
raise DistutilsArgError(
"Must specify a build directory (-b) when using --editable"
@@ -239,11 +244,6 @@ class easy_install(Command):
log.set_verbosity(self.distribution.verbose)
-
-
-
-
-
def install_egg_scripts(self, dist):
"""Write all the scripts for `dist`, unless scripts are excluded"""
diff --git a/setuptools/package_index.py b/setuptools/package_index.py
index f5b322b0..76d53d11 100755
--- a/setuptools/package_index.py
+++ b/setuptools/package_index.py
@@ -5,11 +5,11 @@ from pkg_resources import *
from distutils import log
from distutils.errors import DistutilsError
from md5 import md5
+from fnmatch import translate
EGG_FRAGMENT = re.compile(r'^egg=([-A-Za-z0-9_.]+)$')
HREF = re.compile("""href\\s*=\\s*['"]?([^'"> ]+)""", re.I)
# this is here to fix emacs' cruddy broken syntax highlighting
-
PYPI_MD5 = re.compile(
'<a href="([^"#]+)">([^<]+)</a>\n\s+\\(<a href="[^?]+\?:action=show_md5'
'&amp;digest=([0-9a-f]{32})">md5</a>\\)'
@@ -124,25 +124,25 @@ def interpret_distro_name(location, basename, metadata,
class PackageIndex(Environment):
"""A distribution index that scans web pages for download URLs"""
- def __init__(self,index_url="http://www.python.org/pypi",*args,**kw):
+ def __init__(self,index_url="http://www.python.org/pypi",hosts=('*',),*args,**kw):
Environment.__init__(self,*args,**kw)
self.index_url = index_url + "/"[:not index_url.endswith('/')]
self.scanned_urls = {}
self.fetched_urls = {}
self.package_pages = {}
+ self.allows = re.compile('|'.join(map(translate,hosts))).match
def process_url(self, url, retrieve=False):
"""Evaluate a URL as a possible download, and maybe retrieve it"""
-
if url in self.scanned_urls and not retrieve:
return
self.scanned_urls[url] = True
-
if not URL_SCHEME(url):
# process filenames or directories
if os.path.isfile(url):
- dists = list(distros_for_filename(url))
+ map(self.add, distros_for_filename(url))
+ return # no need to retrieve anything
elif os.path.isdir(url):
url = os.path.realpath(url)
for item in os.listdir(url):
@@ -153,13 +153,16 @@ class PackageIndex(Environment):
return
else:
dists = list(distros_for_url(url))
+ if dists:
+ if not self.url_ok(url):
+ return
+ self.debug("Found link: %s", url)
- if dists:
- self.debug("Found link: %s", url)
if dists or not retrieve or url in self.fetched_urls:
- for dist in dists:
- self.add(dist)
- # don't need the actual page
+ map(self.add, dists)
+ return # don't need the actual page
+
+ if not self.url_ok(url):
return
self.info("Reading %s", url)
@@ -181,17 +184,14 @@ class PackageIndex(Environment):
self.process_url(link)
-
-
-
-
-
-
-
-
-
-
-
+ def url_ok(self, url, fatal=False):
+ if self.allows(urlparse.urlparse(url)[1]):
+ return True
+ msg = "\nLink to % s ***BLOCKED*** by --allow-hosts\n"
+ if fatal:
+ raise DistutilsError(msg % url)
+ else:
+ self.warn(msg, url)
@@ -368,8 +368,8 @@ class PackageIndex(Environment):
dl_blocksize = 8192
-
def _download_to(self, url, filename):
+ self.url_ok(url,True) # raises error if not allowed
self.info("Downloading %s", url)
# Download the file
fp, tfp, info = None, None, None