def main(argv=None): """Application entrypoint for pypiserver. This function drives the application (as opposed to the library) implementation of pypiserver. Usage from the commandline will result in this function being called. """ import pypiserver if argv is None: # The first item in sys.argv is the name of the python file being # executed, which we don't need argv = sys.argv[1:] config = Config.from_args(argv) init_logging( level=config.log_level, filename=config.log_file, frmt=config.log_frmt, stream=config.log_stream, ) # Check to see if we were asked to run an update command instead of running # the server if isinstance(config, UpdateConfig): from pypiserver.manage import update_all_packages update_all_packages( config.roots, config.download_directory, dry_run=not config.execute, stable_only=config.allow_unstable, ignorelist=config.ignorelist, ) return # Fixes #49: # The gevent server adapter needs to patch some # modules BEFORE importing bottle! if config.server_method.startswith("gevent"): import gevent.monkey # @UnresolvedImport gevent.monkey.patch_all() from pypiserver import bottle bottle.debug(config.verbosity > 1) bottle._stderr = ft.partial(_logwrite, logging.getLogger(bottle.__name__), logging.INFO) # Here `app` is a Bottle instance, which we pass to bottle.run() to run # the server app = pypiserver.app_from_config(config) bottle.run( app=app, host=config.host, port=config.port, server=config.server_method, )
def main(argv=None): import pypiserver if argv is None: argv = sys.argv command = "serve" c = pypiserver.Configuration(**pypiserver.default_config()) update_dry_run = True update_directory = None update_stable_only = True try: opts, roots = getopt.getopt(argv[1:], "i:p:a:r:d:P:Uuvxoh", [ "interface=", "passwords=", "authenticate=", "port=", "root=", "server=", "fallback-url=", "disable-fallback", "overwrite", "hash-algo=", "log-file=", "log-frmt=", "log-req-frmt=", "log-res-frmt=", "log-err-frmt=", "welcome=", "cache-control=", "version", "help" ]) except getopt.GetoptError: err = sys.exc_info()[1] sys.exit("usage error: %s" % (err, )) for k, v in opts: if k in ("-p", "--port"): try: c.port = int(v) except Exception: err = sys.exc_info()[1] sys.exit("Invalid port(%r) due to: %s" % (v, err)) elif k in ("-a", "--authenticate"): c.authenticated = [ a.lower() for a in re.split("[, ]+", v.strip(" ,")) if a ] if c.authenticated == ['.']: c.authenticated = [] else: actions = ("list", "download", "update") for a in c.authenticated: if a not in actions: errmsg = "Action '%s' for option `%s` not one of %s!" sys.exit(errmsg % (a, k, actions)) elif k in ("-i", "--interface"): c.host = v elif k in ("-r", "--root"): roots.append(v) elif k == "--disable-fallback": c.redirect_to_fallback = False elif k == "--fallback-url": c.fallback_url = v elif k == "--server": c.server = v elif k == "--welcome": c.welcome_file = v elif k == "--version": print("pypiserver %s\n" % pypiserver.__version__) return elif k == "-U": command = "update" elif k == "-x": update_dry_run = False elif k == "-u": update_stable_only = False elif k == "-d": update_directory = v elif k in ("-P", "--passwords"): c.password_file = v elif k in ("-o", "--overwrite"): c.overwrite = True elif k in ("--hash-algo"): c.hash_algo = None if not pypiserver.str2bool(v, c.hash_algo) else v elif k == "--log-file": c.log_file = v elif k == "--log-frmt": c.log_frmt = v elif k == "--log-req-frmt": c.log_req_frmt = v elif k == "--log-res-frmt": c.log_res_frmt = v elif k == "--log-err-frmt": c.log_err_frmt = v elif k == "--cache-control": c.cache_control = v elif k == "-v": c.verbosity += 1 elif k in ("-h", "--help"): print(usage()) sys.exit(0) if (not c.authenticated and c.password_file != '.' or c.authenticated and c.password_file == '.'): auth_err = "When auth-ops-list is empty (-a=.), password-file (-P=%r) must also be empty ('.')!" sys.exit(auth_err % c.password_file) if len(roots) == 0: roots.append(os.path.expanduser("~/packages")) roots = [os.path.abspath(x) for x in roots] c.root = roots verbose_levels = [ logging.WARNING, logging.INFO, logging.DEBUG, logging.NOTSET ] log_level = list(zip(verbose_levels, range(c.verbosity)))[-1][0] init_logging(level=log_level, filename=c.log_file, frmt=c.log_frmt) if command == "update": from pypiserver.manage import update_all_packages update_all_packages(roots, update_directory, dry_run=update_dry_run, stable_only=update_stable_only) return # Fixes #49: # The gevent server adapter needs to patch some # modules BEFORE importing bottle! if c.server and c.server.startswith('gevent'): import gevent.monkey # @UnresolvedImport gevent.monkey.patch_all() from pypiserver import bottle if c.server not in bottle.server_names: sys.exit("unknown server %r. choose one of %s" % (c.server, ", ".join(bottle.server_names.keys()))) bottle.debug(c.verbosity > 1) bottle._stderr = ft.partial(pypiserver._logwrite, logging.getLogger(bottle.__name__), logging.INFO) app = pypiserver.app(**vars(c)) bottle.run(app=app, host=c.host, port=c.port, server=c.server)
def main(argv=None): import pypiserver if argv is None: argv = sys.argv command = "serve" c = pypiserver.Configuration(**pypiserver.default_config()) update_dry_run = True update_directory = None update_stable_only = True try: opts, roots = getopt.getopt(argv[1:], "i:p:a:r:d:P:Uuvxoh", [ "interface=", "passwords=", "authenticate=", "port=", "root=", "server=", "fallback-url=", "disable-fallback", "overwrite", "hash-algo=", "log-file=", "log-frmt=", "log-req-frmt=", "log-res-frmt=", "log-err-frmt=", "welcome=", "cache-control=", "version", "help" ]) except getopt.GetoptError: err = sys.exc_info()[1] sys.exit("usage error: %s" % (err,)) for k, v in opts: if k in ("-p", "--port"): try: c.port = int(v) except Exception: err = sys.exc_info()[1] sys.exit("Invalid port(%r) due to: %s" % (v, err)) elif k in ("-a", "--authenticate"): if '{' in v: try: v = ast.literal_eval(v) except SyntaxError: message = 'Could not parse auth string %s! Please ensure string is correctly formatted.' % v print(message) sys.exit(message) if (not isinstance(v, dict) or not all([isinstance(i, list) for i in v.values()])): message = 'Matrix auth string must be a dict of lists. Please see the README for details.' print(message) sys.exit(message) if isinstance(v, dict): c.authenticated = {} for user in v: c.authenticated[user] = [a.lower() for a in v[user] if a] if c.authenticated[user] == ['.']: c.authenticated[user] = [] else: actions = ("list", "download", "update") for a in c.authenticated[user]: if a not in actions: errmsg = "Action '%s' for option `%s` not one of %s!" sys.exit(errmsg % (a, k, actions)) else: c.authenticated = [a.lower() for a in re.split("[, ]+", v.strip(" ,")) if a] if c.authenticated == ['.']: c.authenticated = [] else: actions = ("list", "download", "update") for a in c.authenticated: if a not in actions: errmsg = "Action '%s' for option `%s` not one of %s!" sys.exit(errmsg % (a, k, actions)) elif k in ("-i", "--interface"): c.host = v elif k in ("-r", "--root"): roots.append(v) elif k == "--disable-fallback": c.redirect_to_fallback = False elif k == "--fallback-url": c.fallback_url = v elif k == "--server": c.server = v elif k == "--welcome": c.welcome_file = v elif k == "--version": print("pypiserver %s\n" % pypiserver.__version__) return elif k == "-U": command = "update" elif k == "-x": update_dry_run = False elif k == "-u": update_stable_only = False elif k == "-d": update_directory = v elif k in ("-P", "--passwords"): c.password_file = v elif k in ("-o", "--overwrite"): c.overwrite = True elif k in ("--hash-algo"): c.hash_algo = None if not pypiserver.str2bool(v, c.hash_algo) else v elif k == "--log-file": c.log_file = v elif k == "--log-frmt": c.log_frmt = v elif k == "--log-req-frmt": c.log_req_frmt = v elif k == "--log-res-frmt": c.log_res_frmt = v elif k == "--log-err-frmt": c.log_err_frmt = v elif k == "--cache-control": c.cache_control = v elif k == "-v": c.verbosity += 1 elif k in ("-h", "--help"): print(usage()) sys.exit(0) if (not c.authenticated and c.password_file != '.' or c.authenticated and c.password_file == '.'): auth_err = "When auth-ops-list is empty (-a=.), password-file (-P=%r) must also be empty ('.')!" sys.exit(auth_err % c.password_file) if len(roots) == 0: roots.append(os.path.expanduser("~/packages")) roots=[os.path.abspath(x) for x in roots] c.root = roots verbose_levels=[ logging.WARNING, logging.INFO, logging.DEBUG, logging.NOTSET] log_level=list(zip(verbose_levels, range(c.verbosity)))[-1][0] init_logging(level=log_level, filename=c.log_file, frmt=c.log_frmt) if command == "update": from pypiserver.manage import update_all_packages update_all_packages(roots, update_directory, dry_run=update_dry_run, stable_only=update_stable_only) return # Fixes #49: # The gevent server adapter needs to patch some # modules BEFORE importing bottle! if c.server and c.server.startswith('gevent'): import gevent.monkey # @UnresolvedImport gevent.monkey.patch_all() from pypiserver import bottle if c.server not in bottle.server_names: sys.exit("unknown server %r. choose one of %s" % ( c.server, ", ".join(bottle.server_names.keys()))) bottle.debug(c.verbosity > 1) bottle._stderr = ft.partial(pypiserver._logwrite, logging.getLogger(bottle.__name__), logging.INFO) app = pypiserver.app(**vars(c)) bottle.run(app=app, host=c.host, port=c.port, server=c.server)
def main(argv: t.Sequence[str] = None) -> None: """Application entrypoint for pypiserver. This function drives the application (as opposed to the library) implementation of pypiserver. Usage from the commandline will result in this function being called. """ # pylint: disable=import-outside-toplevel import pypiserver # pylint: disable=redefined-outer-name if argv is None: # The first item in sys.argv is the name of the python file being # executed, which we don't need argv = sys.argv[1:] config = Config.from_args(argv) init_logging( level=config.log_level, filename=config.log_file, frmt=config.log_frmt, stream=config.log_stream, ) # Check to see if we were asked to run an update command instead of running # the server if isinstance(config, UpdateConfig): from pypiserver.manage import update_all_packages update_all_packages( config.roots, config.download_directory, dry_run=not config.execute, stable_only=config.allow_unstable, ignorelist=config.ignorelist, ) return # Fixes #49: # The gevent server adapter needs to patch some # modules BEFORE importing bottle! if config.server_method.startswith("gevent"): import gevent.monkey # @UnresolvedImport gevent.monkey.patch_all() from pypiserver import bottle bottle.debug(config.verbosity > 1) bottle._stderr = ft.partial( # pylint: disable=protected-access _logwrite, logging.getLogger(bottle.__name__), logging.INFO) # Here `app` is a Bottle instance, which we pass to bottle.run() to run # the server app = pypiserver.app_from_config(config) if config.server_method == "gunicorn": # When bottle runs gunicorn, gunicorn tries to pull its arguments from # sys.argv. Because pypiserver's arguments don't match gunicorn's, # this leads to errors. # Gunicorn can be configured by using a `gunicorn.conf.py` config file # or by specifying the `GUNICORN_CMD_ARGS` env var. See gunicorn # docs for more info. sys.argv = ["gunicorn"] wsgi_kwargs = {"handler_class": WsgiHandler} if config.server_method == "auto": expected_server = guess_auto_server() extra_kwargs = (wsgi_kwargs if expected_server is AutoServer.WsgiRef else {}) log.debug( "Server 'auto' selected. Expecting bottle to run '%s'. " "Passing extra keyword args: %s", expected_server.name, extra_kwargs, ) else: extra_kwargs = wsgi_kwargs if config.server_method == "wsgiref" else {} log.debug("Running bottle with selected server '%s'", config.server_method) bottle.run( app=app, host=config.host, port=config.port, server=config.server_method, **extra_kwargs, )
def testapp(app): """Return a webtest TestApp initiated with pypiserver app""" bottle.debug(True) return webtest.TestApp(app)