diff --git a/MANIFEST.in b/MANIFEST.in index 4f55264..0611898 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -9,6 +9,7 @@ include pypi-server-in.py include pypiserver/__init__.py include pypiserver/__main__.py include pypiserver/_app.py +include pypiserver/welcome.html include pypiserver/bottle.py include pypiserver/core.py include pypiserver/manage.py diff --git a/README.rst b/README.rst index 65bf5b7..b889477 100644 --- a/README.rst +++ b/README.rst @@ -112,6 +112,9 @@ pypi-server -h will print a detailed usage message:: -o, --overwrite allow overwriting existing package files + --welcome HTML_FILE + uses the ASCII contents of HTML_FILE as welcome message response. + -v enable INFO logging; repeate for more verbosity. diff --git a/pypiserver/__init__.py b/pypiserver/__init__.py index dd112f2..1b56daa 100644 --- a/pypiserver/__init__.py +++ b/pypiserver/__init__.py @@ -9,7 +9,8 @@ def app(root=None, overwrite=False, log_req_frmt="%(bottle.request)s", log_res_frmt="%(status)s", - log_err_frmt="%(body)s: %(exception)s \n%(traceback)s"): + log_err_frmt="%(body)s: %(exception)s \n%(traceback)s", + welcome_file=None): import sys, os from pypiserver import core sys.modules.pop("pypiserver._app", None) @@ -26,7 +27,8 @@ def app(root=None, _app.configure(root=root, redirect_to_fallback=redirect_to_fallback, fallback_url=fallback_url, password_file=password_file, overwrite=overwrite, - log_req_frmt=log_req_frmt, log_res_frmt=log_res_frmt, log_err_frmt=log_err_frmt) + log_req_frmt=log_req_frmt, log_res_frmt=log_res_frmt, log_err_frmt=log_err_frmt, + welcome_file=welcome_file) _app.app.module = _app bottle.debug(True) diff --git a/pypiserver/_app.py b/pypiserver/_app.py index b22ebf6..4009e1e 100644 --- a/pypiserver/_app.py +++ b/pypiserver/_app.py @@ -1,4 +1,4 @@ -import sys, os, itertools, zipfile, mimetypes, logging +import sys, os, io, itertools, zipfile, mimetypes, logging, pkg_resources try: from io import BytesIO @@ -23,6 +23,8 @@ class configuration(object): self.fallback_url = "http://pypi.python.org/simple" self.redirect_to_fallback = True self.htpasswdfile = None + self.welcome_file = None + self.welcome_msg = None config = configuration() @@ -40,7 +42,8 @@ def configure(root=None, overwrite=False, log_req_frmt=None, log_res_frmt=None, - log_err_frmt=None): + log_err_frmt=None, + welcome_file=None): global packages log.info("Starting(%s)", dict(root=root, @@ -48,6 +51,7 @@ def configure(root=None, fallback_url=fallback_url, password_file=password_file, overwrite=overwrite, + welcome_file=welcome_file, log_req_frmt=log_req_frmt, log_res_frmt=log_res_frmt, log_err_frmt=log_err_frmt)) @@ -80,6 +84,40 @@ def configure(root=None, from passlib.apache import HtpasswdFile config.htpasswdfile = HtpasswdFile(password_file) config.overwrite = overwrite + + ## Read welcome-msg from external file, + # or failback to the embedded-msg (ie. in standalone mode). + # + try: + if not welcome_file: + welcome_file = pkg_resources.resource_filename(__name__, "welcome.html") # @UndefinedVariable + config.welcome_file = welcome_file + with io.open(config.welcome_file, 'r', encoding='utf-8') as fd: + config.welcome_msg = fd.read() + except Exception: + log.warning("Could not load welcome-file(%s)!", welcome_file, exc_info=1) + if not config.welcome_msg: + from textwrap import dedent + config.welcome_msg = dedent("""\ + Welcome to pypiserver! +

Welcome to pypiserver!

+

This is a PyPI compatible package index serving %(NUMPKGS)s packages.

+ +

To use this server with pip, run the the following command: +

+            pip install -i %(URL)ssimple/ PACKAGE [PACKAGE2...]
+            

+ +

To use this server with easy_install, run the the following command: +

+            easy_install -i %(URL)ssimple/ PACKAGE
+            

+ +

The complete list of all packages can be found here or via the simple index.

+ +

This instance is running version %(VERSION)s of the pypiserver software.

+ \ + """) config.log_req_frmt = log_req_frmt config.log_res_frmt = log_res_frmt @@ -122,27 +160,13 @@ def root(): except: numpkgs = 0 - return """Welcome to pypiserver! -

Welcome to pypiserver!

-

This is a PyPI compatible package index serving %(NUMPKGS)s packages.

- -

To use this server with pip, run the the following command: -

-pip install -i %(URL)ssimple/ PACKAGE [PACKAGE2...]
-

- -

To use this server with easy_install, run the the following command: -

-easy_install -i %(URL)ssimple/ PACKAGE
-

- -

The complete list of all packages can be found here or via the simple index.

- -

This instance is running version %(VERSION)s of the pypiserver software.

- -""" % dict(URL=request.url, VERSION=__version__, NUMPKGS=numpkgs, + return config.welcome_msg % dict( + URL=request.url, + VERSION=__version__, + NUMPKGS=numpkgs, PACKAGES=urljoin(fp, "packages/"), - SIMPLE=urljoin(fp, "simple/")) + SIMPLE=urljoin(fp, "simple/") + ) @app.post('/') diff --git a/pypiserver/core.py b/pypiserver/core.py index 93168b1..12b1e49 100755 --- a/pypiserver/core.py +++ b/pypiserver/core.py @@ -213,6 +213,9 @@ pypi-server understands the following options: -o, --overwrite allow overwriting existing package files + --welcome HTML_FILE + uses the ASCII contents of HTML_FILE as welcome message response. + -v enable verbose logging; repeate for more verbosity. @@ -283,6 +286,7 @@ def main(argv=None): log_req_frmt = None log_res_frmt = None log_err_frmt = None + welcome_file = None update_dry_run = True update_directory = None @@ -303,6 +307,7 @@ def main(argv=None): "log-req-frmt=", "log-res-frmt=", "log-err-frmt=", + "welcome=", "version", "help" ]) @@ -326,6 +331,8 @@ def main(argv=None): sys.exit("unknown server %r. choose one of %s" % ( v, ", ".join(server_names.keys()))) server = v + elif k == "--welcome": + welcome_file = v elif k == "--version": sys.stdout.write("pypiserver %s\n" % __version__) sys.exit(0) @@ -379,6 +386,7 @@ def main(argv=None): fallback_url=fallback_url, overwrite=overwrite, log_req_frmt=log_req_frmt, log_res_frmt=log_res_frmt, log_err_frmt=log_err_frmt, + welcome_file=welcome_file, ) server = server or "auto" sys.stdout.write("This is pypiserver %s serving %r on http://%s:%s\n\n" % (__version__, ", ".join(roots), host, port)) diff --git a/pypiserver/welcome.html b/pypiserver/welcome.html new file mode 100644 index 0000000..ac3fc99 --- /dev/null +++ b/pypiserver/welcome.html @@ -0,0 +1,18 @@ +Welcome to pypiserver! +

Welcome to pypiserver!

+

This is a PyPI compatible package index serving %(NUMPKGS)s packages.

+ +

To use this server with pip, run the the following command: +

+pip install -i %(URL)ssimple/ PACKAGE [PACKAGE2...]
+

+ +

To use this server with easy_install, run the the following command: +

+easy_install -i %(URL)ssimple/ PACKAGE
+

+ +

The complete list of all packages can be found here or via the simple index.

+ +

This instance is running version %(VERSION)s of the pypiserver software.

+ diff --git a/setup.py b/setup.py index 014c297..79ae75a 100755 --- a/setup.py +++ b/setup.py @@ -32,6 +32,7 @@ setup(name="pypiserver", long_description=open("README.rst").read(), version=get_version(), packages=["pypiserver"], + package_data={'pypiserver': ['welcome.html']}, url="https://github.com/schmir/pypiserver", maintainer="Ralf Schmitt", maintainer_email="ralf@systemexit.de", @@ -53,4 +54,5 @@ setup(name="pypiserver", "Programming Language :: Python :: 3.3", "Topic :: Software Development :: Build Tools", "Topic :: System :: Software Distribution"], + zip_safe=False, **extra) diff --git a/tests/sample_msg.html b/tests/sample_msg.html new file mode 100644 index 0000000..6dbbef4 --- /dev/null +++ b/tests/sample_msg.html @@ -0,0 +1,7 @@ +Hello pypiserver tester! +%(URL)s +%(VERSION)s +%(NUMPKGS)s +%(PACKAGES)s +%(SIMPLE)s + diff --git a/tests/test_app.py b/tests/test_app.py index 2918f33..d5b3264 100755 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -55,6 +55,18 @@ def test_root_hostname(testapp): # go("http://systemexit.de/") +def test_root_welcome_msg(root): + wmsg = "Hey there!" + wfile = root.join("testwelcome.html") + wfile.write(wmsg) + + from pypiserver import app + app = app(root=root.strpath, welcome_file=wfile.strpath) + testapp = webtest.TestApp(app) + resp = testapp.get("/") + resp.mustcontain(wmsg) + + def test_packages_empty(testapp): resp = testapp.get("/packages") assert len(resp.html("a")) == 0 diff --git a/tests/test_main.py b/tests/test_main.py index 3c9bcdd..69235bf 100755 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -102,3 +102,12 @@ def test_logging_verbosity(main): assert logging.getLogger().level == logging.DEBUG main(["-v", "-v", "-v"]) assert logging.getLogger().level == logging.NOTSET + +def test_welcome_file(main): + sample_msg_file = os.path.join(os.path.dirname(__file__), "sample_msg.html") + main(["--welcome", sample_msg_file]) + assert "Hello pypiserver tester!" in main.app.module.config.welcome_msg + +def test_welcome_file_default(main): + main([]) + assert "Welcome to pypiserver!" in main.app.module.config.welcome_msg