forked from github.com/pypiserver
FIX #55: Allow unauthenticated uploads with `-P .` option.
+ Add `mock` lib into test-dependencies for py2. + travis: Use new containers.
This commit is contained in:
parent
47b80b414a
commit
1fd5653317
|
@ -1,3 +1,4 @@
|
|||
sudo: false
|
||||
language: python
|
||||
python: 2.7
|
||||
env:
|
||||
|
@ -17,3 +18,4 @@ script:
|
|||
branches:
|
||||
except:
|
||||
- standalone
|
||||
|
13
README.rst
13
README.rst
|
@ -216,14 +216,21 @@ Running ``pypi-server -h`` will print a detailed usage message::
|
|||
|
||||
-a, --authenticate (UPDATE|download|list), ...
|
||||
comma-separated list of (case-insensitive) actions to authenticate
|
||||
(requires giving also the -P option). For example to password-protect
|
||||
package uploads & downloads while leaving listings public, give:
|
||||
-a update,download.
|
||||
Requires -P option and cannot not be empty unless -P is '.'
|
||||
For example to password-protect package downloads (in addition to uploads)
|
||||
while leaving listings public, give:
|
||||
-P foo/htpasswd.txt -a update,download
|
||||
To drop all authentications, use:
|
||||
-P . -a ''
|
||||
For example to password-protect package uploads & downloads while leaving
|
||||
listings public, give:
|
||||
-P -a update,download
|
||||
By default, only 'update' is password-protected.
|
||||
|
||||
-P, --passwords PASSWORD_FILE
|
||||
use apache htpasswd file PASSWORD_FILE to set usernames & passwords
|
||||
used for authentication of certain actions (see -a option).
|
||||
Set it explicitly to '.' to allow empty list of actions to authenticate.
|
||||
|
||||
--disable-fallback
|
||||
disable redirect to real PyPI index for packages not found in the
|
||||
|
|
|
@ -209,14 +209,21 @@ pypi-server understands the following options:
|
|||
|
||||
-a, --authenticate (UPDATE|download|list), ...
|
||||
comma-separated list of (case-insensitive) actions to authenticate
|
||||
(requires giving also the -P option). For example to password-protect
|
||||
package uploads & downloads while leaving listings public, give:
|
||||
-a update,download.
|
||||
Requires -P option and cannot not be empty unless -P is '.'
|
||||
For example to password-protect package downloads (in addition to uploads)
|
||||
while leaving listings public, give:
|
||||
-P foo/htpasswd.txt -a update,download
|
||||
To drop all authentications, use:
|
||||
-P . -a ''
|
||||
For example to password-protect package uploads & downloads while leaving
|
||||
listings public, give:
|
||||
-P -a update,download
|
||||
By default, only 'update' is password-protected.
|
||||
|
||||
-P, --passwords PASSWORD_FILE
|
||||
use apache htpasswd file PASSWORD_FILE to set usernames & passwords
|
||||
used for authentication of certain actions (see -a option).
|
||||
Set it explicitly to '.' to allow empty list of actions to authenticate.
|
||||
|
||||
--disable-fallback
|
||||
disable redirect to real PyPI index for packages not found in the
|
||||
|
@ -249,12 +256,12 @@ pypi-server understands the following options:
|
|||
|
||||
--log-frmt <FILE>
|
||||
the logging format-string. (see `logging.LogRecord` class from standard python library)
|
||||
[Default: %(asctime)s|%(levelname)s|%(thread)d|%(message)s]
|
||||
[Default: %(asctime)s|%(levelname)s|%(thread)d|%(message)s]
|
||||
|
||||
--log-req-frmt FORMAT
|
||||
a format-string selecting Http-Request properties to log; set to '%s' to see them all.
|
||||
[Default: %(bottle.request)s]
|
||||
|
||||
[Default: %(bottle.request)s]
|
||||
|
||||
--log-res-frmt FORMAT
|
||||
a format-string selecting Http-Response properties to log; set to '%s' to see them all.
|
||||
[Default: %(status)s]
|
||||
|
@ -354,7 +361,9 @@ def main(argv=None):
|
|||
if k in ("-p", "--port"):
|
||||
port = int(v)
|
||||
elif k in ("-a", "--authenticate"):
|
||||
authenticated = [a.lower() for a in re.split("[, ]+", v.strip(" ,"))]
|
||||
authenticated = [a.lower()
|
||||
for a in re.split("[, ]+", v.strip(" ,"))
|
||||
if a]
|
||||
actions = ("list", "download", "update")
|
||||
for a in authenticated:
|
||||
if a not in actions:
|
||||
|
@ -408,8 +417,8 @@ def main(argv=None):
|
|||
usage()
|
||||
sys.exit(0)
|
||||
|
||||
if password_file and not (password_file and authenticated):
|
||||
sys.exit("Must give both password file (-P) and actions to authenticate (-a).")
|
||||
if password_file and password_file != '.' and not authenticated:
|
||||
sys.exit("Actions to authenticate (-a) must not be empty, unless password file (-P) is '.'!")
|
||||
|
||||
if len(roots) == 0:
|
||||
roots.append(os.path.expanduser("~/packages"))
|
||||
|
|
|
@ -14,8 +14,10 @@ except ImportError:
|
|||
|
||||
if sys.version_info >= (3, 0):
|
||||
exec("def do_exec(co, loc): exec(co, loc)\n")
|
||||
tests_require = []
|
||||
else:
|
||||
exec("def do_exec(co, loc): exec co in loc\n")
|
||||
tests_require = ['mock']
|
||||
|
||||
|
||||
def get_version():
|
||||
|
@ -33,7 +35,8 @@ setup(name="pypiserver",
|
|||
version=get_version(),
|
||||
packages=["pypiserver"],
|
||||
package_data={'pypiserver': ['welcome.html']},
|
||||
url="https://github.com/pypiserver/pypiserver",
|
||||
tests_require=tests_require,
|
||||
url="https://github.com/pypiserver/pypiserver",
|
||||
maintainer="Ralf Schmitt, Kostis Anagnostopoulos",
|
||||
maintainer_email="ralf@systemexit.de, ankostis@gmail.com",
|
||||
classifiers=[
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
import sys, os, pytest, logging
|
||||
from pypiserver import core
|
||||
try:
|
||||
from unittest import mock
|
||||
except ImportError:
|
||||
import mock
|
||||
|
||||
|
||||
class main_wrapper(object):
|
||||
|
@ -111,3 +115,22 @@ def test_welcome_file(main):
|
|||
def test_welcome_file_default(main):
|
||||
main([])
|
||||
assert "Welcome to pypiserver!" in main.app.module.config.welcome_msg
|
||||
|
||||
def test_password_without_auth_list(main, monkeypatch):
|
||||
sysexit = mock.MagicMock(side_effect=ValueError('BINGO'))
|
||||
monkeypatch.setattr('sys.exit', sysexit)
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
main(["-P", "pswd-file", "-a", ""])
|
||||
assert excinfo.value.args[0] == 'BINGO'
|
||||
|
||||
def test_password_alone(main, monkeypatch):
|
||||
monkeypatch.setitem(sys.modules, 'passlib', mock.MagicMock())
|
||||
monkeypatch.setitem(sys.modules, 'passlib.apache', mock.MagicMock())
|
||||
main(["-P", "pswd-file"])
|
||||
assert main.app.module.config.authenticated == ['update']
|
||||
|
||||
def test_dot_password_without_auth_list(main, monkeypatch):
|
||||
monkeypatch.setitem(sys.modules, 'passlib', mock.MagicMock())
|
||||
monkeypatch.setitem(sys.modules, 'passlib.apache', mock.MagicMock())
|
||||
main(["-P", ".", "-a", ""])
|
||||
assert main.app.module.config.authenticated == []
|
||||
|
|
2
tox.ini
2
tox.ini
|
@ -5,6 +5,7 @@ envlist = py25,py26,py27,py32,py33,py34
|
|||
deps=pytest>=2.3
|
||||
webtest
|
||||
beautifulsoup4
|
||||
mock
|
||||
commands=py.test []
|
||||
sitepackages=False
|
||||
|
||||
|
@ -13,6 +14,7 @@ deps=pytest>=2.3
|
|||
WebTest==1.4.3
|
||||
WebOb==0.9.6.1
|
||||
BeautifulSoup==3.2.1
|
||||
mock
|
||||
|
||||
[pytest]
|
||||
norecursedirs = bin parts develop-eggs eggs .* _* CVS {args}
|
||||
|
|
Loading…
Reference in New Issue