2020-10-09 02:37:39 +02:00
|
|
|
"""Tests for config parsing."""
|
|
|
|
|
|
|
|
import hashlib
|
|
|
|
import typing as t
|
|
|
|
import itertools
|
|
|
|
import pathlib
|
|
|
|
import sys
|
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
Refactor storage operations into separate Backend classes (#348)
Following the discussion in #253 and #325 I've created a first iteration on what a `Backend` interface could look like and how the current file storage operations may be refactored into this interface. It goes from the following principles
* `app.py` talks only to `core.py` with regards to package operations
* at configuration time, a `Backend` implementation is chosen and created for the lifetime of the configured app
* `core.py` proxies requests for packages to this `Backend()`
* The `Backend` interface/api is defined through three things
* methods that an implementation must implement
* methods that an implementation may override if it knows better than the defaults
* the `PkgFIle` class that is (should be) the main carrier of data
* where possible, implementation details must be hidden from concrete `Backend`s to promote extensibility
Other things I've done in this PR:
* I've tried to talk about packages and projects, rather than files and prefixes, since these are the domain terms PEP503 uses, and imho it's also more clear what it means
* Better testability of the `CacheManager` (no more race conditions when `watchdog` is installed during testing)
* Cleanup some more Python 2 code
* Started moving away from `os.path` and `py.path` in favour of `pathlib`
Furthermore I've created a `plugin.py` with a sample of how I think plugin system could look like. This sampIe assumes we use `argparse` and allows for the extension of cli arguments that a plugin may need. I think the actual implementation of such a plugin system is beyond the scope of this PR, but I've used it as a target for the Backend refactoring. If requested, I'll remove it from this PR.
The following things still need to be done / discussed. These can be part of this PR or moved into their own, separate PRs
- [ ] Simplify the `PgkFile` class. It currently consists of a number of attributes that don't necessarily belong with it, and not all attributes are aptly named (imho). I would like to minimalize the scope of `PkgFile` so that its only concern is being a data carrier between the app and the backends, and make its use more clear.
- [ ] Add a `PkgFile.metadata` that backend implementations may use to store custom data for packages. For example the current `PkgFile.root` attribute is an implementation detail of the filestorage backends, and other Backend implementations should not be bothered by it.
- [ ] Use `pathlib` wherever possible. This may also result in less attributes for `PkgFile`, since some things may be just contained in a single `Path` object, instead of multtiple strings.
- [ ] Improve testing of the `CacheManager`.
----
* move some functions around in preparation for backend module
* rename pkg_utils to pkg_helpers to prevent confusion with stdlib pkgutil
* further implement the current filestorage as simple file backend
* rename prefix to project, since that's more descriptive
* add digester func as attribute to pkgfile
* WIP caching backend
* WIP make cache better testable
* better testability of cache
* WIP file backends as plugin
* fix typos, run black
* Apply suggestions from code review
Co-authored-by: Matthew Planchard <mplanchard@users.noreply.github.com>
* add more type hints to pass mypy, fix tox.ini
* add package count method to backend
* add package count method to backend
* minor changes
* bugfix when checking invalid whl file
* check for existing package recursively, bugfix, some more pathlib
* fix unittest
* rm dead code
* exclude bottle.py from coverage
* fix merge mistakes
* fix tab indentation
* backend as a cli argument
* fix cli, add tests
* fix mypy
* fix more silly mistakes
* process feedback
* remove dead code
Co-authored-by: Matthew Planchard <mplanchard@users.noreply.github.com>
2021-02-02 18:44:29 +01:00
|
|
|
from pypiserver.backend import SimpleFileBackend, BackendProxy
|
2020-10-09 02:37:39 +02:00
|
|
|
from pypiserver.config import DEFAULTS, Config, RunConfig, UpdateConfig
|
|
|
|
|
Use argparse config throughout app (#349)
This PR is a pretty substantial refactor of the entrypoints of pypiserver (`__main__` and `__init__`) to use the argparse-based config added in #339.
- Updated `RunConfig` and `UpdateConfig` classes to have exclusive init kwargs, instead of taking an namespace. This turned out to be much easier when working with the library-style app initialization in `__init__`, both for direct instantiation and via paste config
- Added an `iter_packages()` method to the `RunConfig` to iterate over packages specified by the configuration (note @elfjes, I think that replacing this with e.g. a `backend` reference will be a nice way to tie in #348)
- Added a general-purpose method to map legacy keyword arguments to the `app()` and `paste_app_factory()` functions to updated forms
- Refactored the `paste_app_factory()` to not mutate the incoming dictionary
- Removed all argument-parsing and config-related code from `__main__` and `core`
- Moved `_logwrite` from `__init__` to `__main__`, since that was the only place it was being used after the updates to `core`
- Updated `digest_file` to use `hashlib.new(algo)` instead of `getattr(hashlib, algo)`, because the former supports more algorithms
- Updated `setup.py` to, instead of calling `eval()` on the entirety of `__init__`, to instead just evaluate the line that defines the version
- Assigned the config to a `._pypiserver_config` attribute on the `Bottle` instance to reduce hacky test workarounds
- Fixed the tox config, which I broke in #339
* Config: add auth & absolute path resolution
* Config: check pkg dirs on config creation
* Instantiate config with kwargs, not namespace
* WIP: still pulling the threads
* Init seems to be working
* tests passing locally, still need to update cache
* Fix tox command
* unused import
* Fix typing
* Be more selective in exec() in setup.py
* Require accurate casing for hash algos
* Remove old comment
* Comments, minor updates and simplifications
* move _logwrite to a more reasonable place
* Update config to work with cache
* Type cachemanager listdir in core
* Update config module docstring, rename method
* Add more comments re: paste config
* Add comments to main, remove unneded check
* Remove commented code
* Use {posargs} instead of [] for clarity in tox
* Add dupe check for kwarg updater
* Remove unused references on app instance
* Fix typo
* Remove redundancy in log level parsing
2020-10-26 00:48:28 +01:00
|
|
|
FILE_DIR = pathlib.Path(__file__).parent.resolve()
|
|
|
|
|
|
|
|
# Username and password stored in the htpasswd.a.a test file.
|
|
|
|
HTPASS_TEST_FILE = str(FILE_DIR / "htpasswd.a.a")
|
|
|
|
HTPASS_TEST_USER = "a"
|
|
|
|
HTPASS_TEST_PASS = "a"
|
2020-10-09 02:37:39 +02:00
|
|
|
|
|
|
|
TEST_WELCOME_FILE = str(pathlib.Path(__file__).parent / "sample_msg.html")
|
|
|
|
TEST_IGNORELIST_FILE = str(pathlib.Path(__file__).parent / "test-ignorelist")
|
|
|
|
|
|
|
|
|
|
|
|
class ConfigTestCase(t.NamedTuple):
|
|
|
|
# A description of the test case
|
|
|
|
case: str
|
|
|
|
# Arguments to pass to the Config constructor
|
|
|
|
args: t.List[str]
|
|
|
|
# Legacy arguments that should yield an equivalent config class
|
|
|
|
legacy_args: t.List[str]
|
|
|
|
# The config class the arguments should resolve to
|
|
|
|
exp_config_type: t.Type
|
|
|
|
# Expected values in the config. These don't necessarily need to be
|
|
|
|
# exclusive. Instead, they should just look at the attributes relevant
|
Use argparse config throughout app (#349)
This PR is a pretty substantial refactor of the entrypoints of pypiserver (`__main__` and `__init__`) to use the argparse-based config added in #339.
- Updated `RunConfig` and `UpdateConfig` classes to have exclusive init kwargs, instead of taking an namespace. This turned out to be much easier when working with the library-style app initialization in `__init__`, both for direct instantiation and via paste config
- Added an `iter_packages()` method to the `RunConfig` to iterate over packages specified by the configuration (note @elfjes, I think that replacing this with e.g. a `backend` reference will be a nice way to tie in #348)
- Added a general-purpose method to map legacy keyword arguments to the `app()` and `paste_app_factory()` functions to updated forms
- Refactored the `paste_app_factory()` to not mutate the incoming dictionary
- Removed all argument-parsing and config-related code from `__main__` and `core`
- Moved `_logwrite` from `__init__` to `__main__`, since that was the only place it was being used after the updates to `core`
- Updated `digest_file` to use `hashlib.new(algo)` instead of `getattr(hashlib, algo)`, because the former supports more algorithms
- Updated `setup.py` to, instead of calling `eval()` on the entirety of `__init__`, to instead just evaluate the line that defines the version
- Assigned the config to a `._pypiserver_config` attribute on the `Bottle` instance to reduce hacky test workarounds
- Fixed the tox config, which I broke in #339
* Config: add auth & absolute path resolution
* Config: check pkg dirs on config creation
* Instantiate config with kwargs, not namespace
* WIP: still pulling the threads
* Init seems to be working
* tests passing locally, still need to update cache
* Fix tox command
* unused import
* Fix typing
* Be more selective in exec() in setup.py
* Require accurate casing for hash algos
* Remove old comment
* Comments, minor updates and simplifications
* move _logwrite to a more reasonable place
* Update config to work with cache
* Type cachemanager listdir in core
* Update config module docstring, rename method
* Add more comments re: paste config
* Add comments to main, remove unneded check
* Remove commented code
* Use {posargs} instead of [] for clarity in tox
* Add dupe check for kwarg updater
* Remove unused references on app instance
* Fix typo
* Remove redundancy in log level parsing
2020-10-26 00:48:28 +01:00
|
|
|
# to the test case at hand. A special "_test" key, if present, should
|
|
|
|
# map to a function that takes the config as an argument. If this
|
|
|
|
# returns a falsey value, the test will be failed.
|
2020-10-09 02:37:39 +02:00
|
|
|
exp_config_values: t.Dict[str, t.Any]
|
|
|
|
|
|
|
|
|
|
|
|
# The iterables generated by this function are designed to be unpacked
|
|
|
|
# into the _CONFIG_TEST_PARAMS constant.
|
|
|
|
def generate_subcommand_test_cases(
|
|
|
|
case: str,
|
|
|
|
extra_args: t.List[str] = None,
|
|
|
|
exp_config_values: t.Dict[str, t.Any] = None,
|
|
|
|
) -> t.Iterable[ConfigTestCase]:
|
|
|
|
"""Generate `run` and `update` test cases automatically.
|
|
|
|
|
|
|
|
Use to avoid having to specify individual cases for situations like
|
|
|
|
global arguments, where the resultant configs should have the same values.
|
|
|
|
|
|
|
|
These tests also help to ensure parity between legacy and modern orderings,
|
|
|
|
since generally the only difference between the two should be the presence
|
|
|
|
or absence of the subcommand.
|
|
|
|
|
|
|
|
:param case: the test case name. will be combined with the subcommand
|
|
|
|
to generate a case name for the resultant case.
|
|
|
|
:param extra_args: arguments to pass after the subcommand positional
|
|
|
|
arguments
|
|
|
|
:param extra_legacy_args: legacy arguments to pass in addition to the
|
|
|
|
subcommand arguments, if any
|
|
|
|
:param exp_config_values: the values that should be present on both
|
|
|
|
run and update test cases.
|
|
|
|
"""
|
|
|
|
extra_args = extra_args or []
|
|
|
|
extra_legacy_args = extra_args
|
|
|
|
exp_config_values = exp_config_values or {}
|
|
|
|
# The legacy "update" subcommand was specified with an optional `-U`
|
|
|
|
# argument. This allows us to map the subcommand to that argument, so
|
|
|
|
# we can include it in the resulting legacy args.
|
|
|
|
legacy_base_arg_map = {"update": ["-U"]}
|
|
|
|
# A mapping of subcommands to their expected Config types.
|
|
|
|
config_type_map = {
|
|
|
|
"run": RunConfig,
|
|
|
|
"update": UpdateConfig,
|
|
|
|
}
|
|
|
|
return (
|
|
|
|
ConfigTestCase(
|
|
|
|
case="{subcmd}: {case}",
|
|
|
|
args=[subcmd, *extra_args],
|
|
|
|
legacy_args=[
|
|
|
|
*legacy_base_arg_map.get(subcmd, []),
|
|
|
|
*extra_legacy_args,
|
|
|
|
],
|
|
|
|
exp_config_type=config_type_map[subcmd],
|
|
|
|
exp_config_values=exp_config_values,
|
|
|
|
)
|
|
|
|
for subcmd in ("run", "update")
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# Define Config test parameters
|
|
|
|
_CONFIG_TEST_PARAMS: t.Tuple[ConfigTestCase, ...] = (
|
|
|
|
# ******************************************************************
|
|
|
|
# Raw subcommands
|
|
|
|
# ******************************************************************
|
|
|
|
*generate_subcommand_test_cases(
|
|
|
|
case="no arguments",
|
|
|
|
),
|
|
|
|
# ******************************************************************
|
|
|
|
# Global args
|
|
|
|
# ******************************************************************
|
|
|
|
# Package directories
|
|
|
|
*generate_subcommand_test_cases(
|
|
|
|
case="no package directory specified",
|
|
|
|
exp_config_values={"roots": DEFAULTS.PACKAGE_DIRECTORIES},
|
|
|
|
),
|
|
|
|
*generate_subcommand_test_cases(
|
|
|
|
case="single package directory specified",
|
Use argparse config throughout app (#349)
This PR is a pretty substantial refactor of the entrypoints of pypiserver (`__main__` and `__init__`) to use the argparse-based config added in #339.
- Updated `RunConfig` and `UpdateConfig` classes to have exclusive init kwargs, instead of taking an namespace. This turned out to be much easier when working with the library-style app initialization in `__init__`, both for direct instantiation and via paste config
- Added an `iter_packages()` method to the `RunConfig` to iterate over packages specified by the configuration (note @elfjes, I think that replacing this with e.g. a `backend` reference will be a nice way to tie in #348)
- Added a general-purpose method to map legacy keyword arguments to the `app()` and `paste_app_factory()` functions to updated forms
- Refactored the `paste_app_factory()` to not mutate the incoming dictionary
- Removed all argument-parsing and config-related code from `__main__` and `core`
- Moved `_logwrite` from `__init__` to `__main__`, since that was the only place it was being used after the updates to `core`
- Updated `digest_file` to use `hashlib.new(algo)` instead of `getattr(hashlib, algo)`, because the former supports more algorithms
- Updated `setup.py` to, instead of calling `eval()` on the entirety of `__init__`, to instead just evaluate the line that defines the version
- Assigned the config to a `._pypiserver_config` attribute on the `Bottle` instance to reduce hacky test workarounds
- Fixed the tox config, which I broke in #339
* Config: add auth & absolute path resolution
* Config: check pkg dirs on config creation
* Instantiate config with kwargs, not namespace
* WIP: still pulling the threads
* Init seems to be working
* tests passing locally, still need to update cache
* Fix tox command
* unused import
* Fix typing
* Be more selective in exec() in setup.py
* Require accurate casing for hash algos
* Remove old comment
* Comments, minor updates and simplifications
* move _logwrite to a more reasonable place
* Update config to work with cache
* Type cachemanager listdir in core
* Update config module docstring, rename method
* Add more comments re: paste config
* Add comments to main, remove unneded check
* Remove commented code
* Use {posargs} instead of [] for clarity in tox
* Add dupe check for kwarg updater
* Remove unused references on app instance
* Fix typo
* Remove redundancy in log level parsing
2020-10-26 00:48:28 +01:00
|
|
|
extra_args=[str(FILE_DIR)],
|
|
|
|
exp_config_values={"roots": [FILE_DIR]},
|
2020-10-09 02:37:39 +02:00
|
|
|
),
|
|
|
|
*generate_subcommand_test_cases(
|
|
|
|
case="multiple package directory specified",
|
Use argparse config throughout app (#349)
This PR is a pretty substantial refactor of the entrypoints of pypiserver (`__main__` and `__init__`) to use the argparse-based config added in #339.
- Updated `RunConfig` and `UpdateConfig` classes to have exclusive init kwargs, instead of taking an namespace. This turned out to be much easier when working with the library-style app initialization in `__init__`, both for direct instantiation and via paste config
- Added an `iter_packages()` method to the `RunConfig` to iterate over packages specified by the configuration (note @elfjes, I think that replacing this with e.g. a `backend` reference will be a nice way to tie in #348)
- Added a general-purpose method to map legacy keyword arguments to the `app()` and `paste_app_factory()` functions to updated forms
- Refactored the `paste_app_factory()` to not mutate the incoming dictionary
- Removed all argument-parsing and config-related code from `__main__` and `core`
- Moved `_logwrite` from `__init__` to `__main__`, since that was the only place it was being used after the updates to `core`
- Updated `digest_file` to use `hashlib.new(algo)` instead of `getattr(hashlib, algo)`, because the former supports more algorithms
- Updated `setup.py` to, instead of calling `eval()` on the entirety of `__init__`, to instead just evaluate the line that defines the version
- Assigned the config to a `._pypiserver_config` attribute on the `Bottle` instance to reduce hacky test workarounds
- Fixed the tox config, which I broke in #339
* Config: add auth & absolute path resolution
* Config: check pkg dirs on config creation
* Instantiate config with kwargs, not namespace
* WIP: still pulling the threads
* Init seems to be working
* tests passing locally, still need to update cache
* Fix tox command
* unused import
* Fix typing
* Be more selective in exec() in setup.py
* Require accurate casing for hash algos
* Remove old comment
* Comments, minor updates and simplifications
* move _logwrite to a more reasonable place
* Update config to work with cache
* Type cachemanager listdir in core
* Update config module docstring, rename method
* Add more comments re: paste config
* Add comments to main, remove unneded check
* Remove commented code
* Use {posargs} instead of [] for clarity in tox
* Add dupe check for kwarg updater
* Remove unused references on app instance
* Fix typo
* Remove redundancy in log level parsing
2020-10-26 00:48:28 +01:00
|
|
|
extra_args=[str(FILE_DIR), str(FILE_DIR.parent)],
|
|
|
|
exp_config_values={
|
|
|
|
"roots": [
|
|
|
|
FILE_DIR,
|
|
|
|
FILE_DIR.parent,
|
|
|
|
]
|
|
|
|
},
|
2020-10-09 02:37:39 +02:00
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="update with package directory (out-of-order legacy order)",
|
Use argparse config throughout app (#349)
This PR is a pretty substantial refactor of the entrypoints of pypiserver (`__main__` and `__init__`) to use the argparse-based config added in #339.
- Updated `RunConfig` and `UpdateConfig` classes to have exclusive init kwargs, instead of taking an namespace. This turned out to be much easier when working with the library-style app initialization in `__init__`, both for direct instantiation and via paste config
- Added an `iter_packages()` method to the `RunConfig` to iterate over packages specified by the configuration (note @elfjes, I think that replacing this with e.g. a `backend` reference will be a nice way to tie in #348)
- Added a general-purpose method to map legacy keyword arguments to the `app()` and `paste_app_factory()` functions to updated forms
- Refactored the `paste_app_factory()` to not mutate the incoming dictionary
- Removed all argument-parsing and config-related code from `__main__` and `core`
- Moved `_logwrite` from `__init__` to `__main__`, since that was the only place it was being used after the updates to `core`
- Updated `digest_file` to use `hashlib.new(algo)` instead of `getattr(hashlib, algo)`, because the former supports more algorithms
- Updated `setup.py` to, instead of calling `eval()` on the entirety of `__init__`, to instead just evaluate the line that defines the version
- Assigned the config to a `._pypiserver_config` attribute on the `Bottle` instance to reduce hacky test workarounds
- Fixed the tox config, which I broke in #339
* Config: add auth & absolute path resolution
* Config: check pkg dirs on config creation
* Instantiate config with kwargs, not namespace
* WIP: still pulling the threads
* Init seems to be working
* tests passing locally, still need to update cache
* Fix tox command
* unused import
* Fix typing
* Be more selective in exec() in setup.py
* Require accurate casing for hash algos
* Remove old comment
* Comments, minor updates and simplifications
* move _logwrite to a more reasonable place
* Update config to work with cache
* Type cachemanager listdir in core
* Update config module docstring, rename method
* Add more comments re: paste config
* Add comments to main, remove unneded check
* Remove commented code
* Use {posargs} instead of [] for clarity in tox
* Add dupe check for kwarg updater
* Remove unused references on app instance
* Fix typo
* Remove redundancy in log level parsing
2020-10-26 00:48:28 +01:00
|
|
|
args=["update", str(FILE_DIR)],
|
|
|
|
legacy_args=[str(FILE_DIR), "-U"],
|
2020-10-09 02:37:39 +02:00
|
|
|
exp_config_type=UpdateConfig,
|
Use argparse config throughout app (#349)
This PR is a pretty substantial refactor of the entrypoints of pypiserver (`__main__` and `__init__`) to use the argparse-based config added in #339.
- Updated `RunConfig` and `UpdateConfig` classes to have exclusive init kwargs, instead of taking an namespace. This turned out to be much easier when working with the library-style app initialization in `__init__`, both for direct instantiation and via paste config
- Added an `iter_packages()` method to the `RunConfig` to iterate over packages specified by the configuration (note @elfjes, I think that replacing this with e.g. a `backend` reference will be a nice way to tie in #348)
- Added a general-purpose method to map legacy keyword arguments to the `app()` and `paste_app_factory()` functions to updated forms
- Refactored the `paste_app_factory()` to not mutate the incoming dictionary
- Removed all argument-parsing and config-related code from `__main__` and `core`
- Moved `_logwrite` from `__init__` to `__main__`, since that was the only place it was being used after the updates to `core`
- Updated `digest_file` to use `hashlib.new(algo)` instead of `getattr(hashlib, algo)`, because the former supports more algorithms
- Updated `setup.py` to, instead of calling `eval()` on the entirety of `__init__`, to instead just evaluate the line that defines the version
- Assigned the config to a `._pypiserver_config` attribute on the `Bottle` instance to reduce hacky test workarounds
- Fixed the tox config, which I broke in #339
* Config: add auth & absolute path resolution
* Config: check pkg dirs on config creation
* Instantiate config with kwargs, not namespace
* WIP: still pulling the threads
* Init seems to be working
* tests passing locally, still need to update cache
* Fix tox command
* unused import
* Fix typing
* Be more selective in exec() in setup.py
* Require accurate casing for hash algos
* Remove old comment
* Comments, minor updates and simplifications
* move _logwrite to a more reasonable place
* Update config to work with cache
* Type cachemanager listdir in core
* Update config module docstring, rename method
* Add more comments re: paste config
* Add comments to main, remove unneded check
* Remove commented code
* Use {posargs} instead of [] for clarity in tox
* Add dupe check for kwarg updater
* Remove unused references on app instance
* Fix typo
* Remove redundancy in log level parsing
2020-10-26 00:48:28 +01:00
|
|
|
exp_config_values={"roots": [FILE_DIR]},
|
2020-10-09 02:37:39 +02:00
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="update with multiple package directories (weird ordering)",
|
Use argparse config throughout app (#349)
This PR is a pretty substantial refactor of the entrypoints of pypiserver (`__main__` and `__init__`) to use the argparse-based config added in #339.
- Updated `RunConfig` and `UpdateConfig` classes to have exclusive init kwargs, instead of taking an namespace. This turned out to be much easier when working with the library-style app initialization in `__init__`, both for direct instantiation and via paste config
- Added an `iter_packages()` method to the `RunConfig` to iterate over packages specified by the configuration (note @elfjes, I think that replacing this with e.g. a `backend` reference will be a nice way to tie in #348)
- Added a general-purpose method to map legacy keyword arguments to the `app()` and `paste_app_factory()` functions to updated forms
- Refactored the `paste_app_factory()` to not mutate the incoming dictionary
- Removed all argument-parsing and config-related code from `__main__` and `core`
- Moved `_logwrite` from `__init__` to `__main__`, since that was the only place it was being used after the updates to `core`
- Updated `digest_file` to use `hashlib.new(algo)` instead of `getattr(hashlib, algo)`, because the former supports more algorithms
- Updated `setup.py` to, instead of calling `eval()` on the entirety of `__init__`, to instead just evaluate the line that defines the version
- Assigned the config to a `._pypiserver_config` attribute on the `Bottle` instance to reduce hacky test workarounds
- Fixed the tox config, which I broke in #339
* Config: add auth & absolute path resolution
* Config: check pkg dirs on config creation
* Instantiate config with kwargs, not namespace
* WIP: still pulling the threads
* Init seems to be working
* tests passing locally, still need to update cache
* Fix tox command
* unused import
* Fix typing
* Be more selective in exec() in setup.py
* Require accurate casing for hash algos
* Remove old comment
* Comments, minor updates and simplifications
* move _logwrite to a more reasonable place
* Update config to work with cache
* Type cachemanager listdir in core
* Update config module docstring, rename method
* Add more comments re: paste config
* Add comments to main, remove unneded check
* Remove commented code
* Use {posargs} instead of [] for clarity in tox
* Add dupe check for kwarg updater
* Remove unused references on app instance
* Fix typo
* Remove redundancy in log level parsing
2020-10-26 00:48:28 +01:00
|
|
|
args=["update", str(FILE_DIR), str(FILE_DIR.parent)],
|
|
|
|
legacy_args=[str(FILE_DIR), "-U", str(FILE_DIR.parent)],
|
2020-10-09 02:37:39 +02:00
|
|
|
exp_config_type=UpdateConfig,
|
Use argparse config throughout app (#349)
This PR is a pretty substantial refactor of the entrypoints of pypiserver (`__main__` and `__init__`) to use the argparse-based config added in #339.
- Updated `RunConfig` and `UpdateConfig` classes to have exclusive init kwargs, instead of taking an namespace. This turned out to be much easier when working with the library-style app initialization in `__init__`, both for direct instantiation and via paste config
- Added an `iter_packages()` method to the `RunConfig` to iterate over packages specified by the configuration (note @elfjes, I think that replacing this with e.g. a `backend` reference will be a nice way to tie in #348)
- Added a general-purpose method to map legacy keyword arguments to the `app()` and `paste_app_factory()` functions to updated forms
- Refactored the `paste_app_factory()` to not mutate the incoming dictionary
- Removed all argument-parsing and config-related code from `__main__` and `core`
- Moved `_logwrite` from `__init__` to `__main__`, since that was the only place it was being used after the updates to `core`
- Updated `digest_file` to use `hashlib.new(algo)` instead of `getattr(hashlib, algo)`, because the former supports more algorithms
- Updated `setup.py` to, instead of calling `eval()` on the entirety of `__init__`, to instead just evaluate the line that defines the version
- Assigned the config to a `._pypiserver_config` attribute on the `Bottle` instance to reduce hacky test workarounds
- Fixed the tox config, which I broke in #339
* Config: add auth & absolute path resolution
* Config: check pkg dirs on config creation
* Instantiate config with kwargs, not namespace
* WIP: still pulling the threads
* Init seems to be working
* tests passing locally, still need to update cache
* Fix tox command
* unused import
* Fix typing
* Be more selective in exec() in setup.py
* Require accurate casing for hash algos
* Remove old comment
* Comments, minor updates and simplifications
* move _logwrite to a more reasonable place
* Update config to work with cache
* Type cachemanager listdir in core
* Update config module docstring, rename method
* Add more comments re: paste config
* Add comments to main, remove unneded check
* Remove commented code
* Use {posargs} instead of [] for clarity in tox
* Add dupe check for kwarg updater
* Remove unused references on app instance
* Fix typo
* Remove redundancy in log level parsing
2020-10-26 00:48:28 +01:00
|
|
|
exp_config_values={
|
|
|
|
"roots": [
|
|
|
|
FILE_DIR,
|
|
|
|
FILE_DIR.parent,
|
|
|
|
]
|
|
|
|
},
|
2020-10-09 02:37:39 +02:00
|
|
|
),
|
|
|
|
# verbosity
|
|
|
|
*(
|
|
|
|
# Generate verbosity test-cases for 0 through 5 -v arguments,
|
|
|
|
# for all subcommands.
|
|
|
|
itertools.chain.from_iterable(
|
|
|
|
# This inner iterable (generate(...) for verbosity in range(5))
|
|
|
|
# will be an iterable of 5 items, where each item is essentially
|
|
|
|
# an n-tuple, where n is the number of subcommands. Passing this
|
|
|
|
# iterable to chain.from_iterable() flattens it, so it is just
|
|
|
|
# one long iterable of cases. These are then unpacked into the
|
|
|
|
# test case tuple with the *, above.
|
|
|
|
generate_subcommand_test_cases(
|
|
|
|
case=f"verbosity {verbosity}",
|
|
|
|
extra_args=["-v" for _ in range(verbosity)],
|
|
|
|
exp_config_values={"verbosity": verbosity},
|
|
|
|
)
|
|
|
|
for verbosity in range(5)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
# log-file
|
|
|
|
*generate_subcommand_test_cases(
|
|
|
|
case="log file unspecified", exp_config_values={"log_file": None}
|
|
|
|
),
|
|
|
|
*generate_subcommand_test_cases(
|
|
|
|
case="log file specified",
|
|
|
|
extra_args=["--log-file", "foo"],
|
|
|
|
exp_config_values={"log_file": "foo"},
|
|
|
|
),
|
|
|
|
# log-stream
|
|
|
|
*generate_subcommand_test_cases(
|
|
|
|
case="log stream unspecified",
|
|
|
|
exp_config_values={"log_stream": DEFAULTS.LOG_STREAM},
|
|
|
|
),
|
|
|
|
*generate_subcommand_test_cases(
|
|
|
|
case="log stream set to stdout",
|
|
|
|
extra_args=["--log-stream", "stdout"],
|
|
|
|
exp_config_values={"log_stream": sys.stdout},
|
|
|
|
),
|
|
|
|
*generate_subcommand_test_cases(
|
|
|
|
case="log stream set to stderr",
|
|
|
|
extra_args=["--log-stream", "stderr"],
|
|
|
|
exp_config_values={"log_stream": sys.stderr},
|
|
|
|
),
|
|
|
|
*generate_subcommand_test_cases(
|
|
|
|
case="log stream set to none",
|
|
|
|
extra_args=["--log-stream", "none"],
|
|
|
|
exp_config_values={"log_stream": None},
|
|
|
|
),
|
|
|
|
*generate_subcommand_test_cases(
|
|
|
|
case="log format unset",
|
|
|
|
exp_config_values={"log_frmt": DEFAULTS.LOG_FRMT},
|
|
|
|
),
|
|
|
|
*generate_subcommand_test_cases(
|
|
|
|
case="log format set",
|
|
|
|
extra_args=["--log-frmt", "foobar %(message)s"],
|
|
|
|
exp_config_values={"log_frmt": "foobar %(message)s"},
|
|
|
|
),
|
|
|
|
# ******************************************************************
|
|
|
|
# Run subcommand args
|
|
|
|
# ******************************************************************
|
|
|
|
# port
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: port unspecified",
|
|
|
|
args=["run"],
|
|
|
|
legacy_args=[],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"port": DEFAULTS.PORT},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: port specified",
|
|
|
|
args=["run", "-p", "9900"],
|
|
|
|
legacy_args=["-p", "9900"],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"port": 9900},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: port specified (long form)",
|
|
|
|
args=["run", "--port", "9900"],
|
|
|
|
legacy_args=["--port", "9900"],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"port": 9900},
|
|
|
|
),
|
|
|
|
# interface
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: interface unspecified",
|
|
|
|
args=["run"],
|
|
|
|
legacy_args=[],
|
|
|
|
exp_config_type=RunConfig,
|
Use argparse config throughout app (#349)
This PR is a pretty substantial refactor of the entrypoints of pypiserver (`__main__` and `__init__`) to use the argparse-based config added in #339.
- Updated `RunConfig` and `UpdateConfig` classes to have exclusive init kwargs, instead of taking an namespace. This turned out to be much easier when working with the library-style app initialization in `__init__`, both for direct instantiation and via paste config
- Added an `iter_packages()` method to the `RunConfig` to iterate over packages specified by the configuration (note @elfjes, I think that replacing this with e.g. a `backend` reference will be a nice way to tie in #348)
- Added a general-purpose method to map legacy keyword arguments to the `app()` and `paste_app_factory()` functions to updated forms
- Refactored the `paste_app_factory()` to not mutate the incoming dictionary
- Removed all argument-parsing and config-related code from `__main__` and `core`
- Moved `_logwrite` from `__init__` to `__main__`, since that was the only place it was being used after the updates to `core`
- Updated `digest_file` to use `hashlib.new(algo)` instead of `getattr(hashlib, algo)`, because the former supports more algorithms
- Updated `setup.py` to, instead of calling `eval()` on the entirety of `__init__`, to instead just evaluate the line that defines the version
- Assigned the config to a `._pypiserver_config` attribute on the `Bottle` instance to reduce hacky test workarounds
- Fixed the tox config, which I broke in #339
* Config: add auth & absolute path resolution
* Config: check pkg dirs on config creation
* Instantiate config with kwargs, not namespace
* WIP: still pulling the threads
* Init seems to be working
* tests passing locally, still need to update cache
* Fix tox command
* unused import
* Fix typing
* Be more selective in exec() in setup.py
* Require accurate casing for hash algos
* Remove old comment
* Comments, minor updates and simplifications
* move _logwrite to a more reasonable place
* Update config to work with cache
* Type cachemanager listdir in core
* Update config module docstring, rename method
* Add more comments re: paste config
* Add comments to main, remove unneded check
* Remove commented code
* Use {posargs} instead of [] for clarity in tox
* Add dupe check for kwarg updater
* Remove unused references on app instance
* Fix typo
* Remove redundancy in log level parsing
2020-10-26 00:48:28 +01:00
|
|
|
exp_config_values={"host": DEFAULTS.INTERFACE},
|
2020-10-09 02:37:39 +02:00
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: interface specified",
|
|
|
|
args=["run", "-i", "1.1.1.1"],
|
|
|
|
legacy_args=["-i", "1.1.1.1"],
|
|
|
|
exp_config_type=RunConfig,
|
Use argparse config throughout app (#349)
This PR is a pretty substantial refactor of the entrypoints of pypiserver (`__main__` and `__init__`) to use the argparse-based config added in #339.
- Updated `RunConfig` and `UpdateConfig` classes to have exclusive init kwargs, instead of taking an namespace. This turned out to be much easier when working with the library-style app initialization in `__init__`, both for direct instantiation and via paste config
- Added an `iter_packages()` method to the `RunConfig` to iterate over packages specified by the configuration (note @elfjes, I think that replacing this with e.g. a `backend` reference will be a nice way to tie in #348)
- Added a general-purpose method to map legacy keyword arguments to the `app()` and `paste_app_factory()` functions to updated forms
- Refactored the `paste_app_factory()` to not mutate the incoming dictionary
- Removed all argument-parsing and config-related code from `__main__` and `core`
- Moved `_logwrite` from `__init__` to `__main__`, since that was the only place it was being used after the updates to `core`
- Updated `digest_file` to use `hashlib.new(algo)` instead of `getattr(hashlib, algo)`, because the former supports more algorithms
- Updated `setup.py` to, instead of calling `eval()` on the entirety of `__init__`, to instead just evaluate the line that defines the version
- Assigned the config to a `._pypiserver_config` attribute on the `Bottle` instance to reduce hacky test workarounds
- Fixed the tox config, which I broke in #339
* Config: add auth & absolute path resolution
* Config: check pkg dirs on config creation
* Instantiate config with kwargs, not namespace
* WIP: still pulling the threads
* Init seems to be working
* tests passing locally, still need to update cache
* Fix tox command
* unused import
* Fix typing
* Be more selective in exec() in setup.py
* Require accurate casing for hash algos
* Remove old comment
* Comments, minor updates and simplifications
* move _logwrite to a more reasonable place
* Update config to work with cache
* Type cachemanager listdir in core
* Update config module docstring, rename method
* Add more comments re: paste config
* Add comments to main, remove unneded check
* Remove commented code
* Use {posargs} instead of [] for clarity in tox
* Add dupe check for kwarg updater
* Remove unused references on app instance
* Fix typo
* Remove redundancy in log level parsing
2020-10-26 00:48:28 +01:00
|
|
|
exp_config_values={"host": "1.1.1.1"},
|
2020-10-09 02:37:39 +02:00
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: interface specified (long form)",
|
|
|
|
args=["run", "--interface", "1.1.1.1"],
|
|
|
|
legacy_args=["--interface", "1.1.1.1"],
|
|
|
|
exp_config_type=RunConfig,
|
Use argparse config throughout app (#349)
This PR is a pretty substantial refactor of the entrypoints of pypiserver (`__main__` and `__init__`) to use the argparse-based config added in #339.
- Updated `RunConfig` and `UpdateConfig` classes to have exclusive init kwargs, instead of taking an namespace. This turned out to be much easier when working with the library-style app initialization in `__init__`, both for direct instantiation and via paste config
- Added an `iter_packages()` method to the `RunConfig` to iterate over packages specified by the configuration (note @elfjes, I think that replacing this with e.g. a `backend` reference will be a nice way to tie in #348)
- Added a general-purpose method to map legacy keyword arguments to the `app()` and `paste_app_factory()` functions to updated forms
- Refactored the `paste_app_factory()` to not mutate the incoming dictionary
- Removed all argument-parsing and config-related code from `__main__` and `core`
- Moved `_logwrite` from `__init__` to `__main__`, since that was the only place it was being used after the updates to `core`
- Updated `digest_file` to use `hashlib.new(algo)` instead of `getattr(hashlib, algo)`, because the former supports more algorithms
- Updated `setup.py` to, instead of calling `eval()` on the entirety of `__init__`, to instead just evaluate the line that defines the version
- Assigned the config to a `._pypiserver_config` attribute on the `Bottle` instance to reduce hacky test workarounds
- Fixed the tox config, which I broke in #339
* Config: add auth & absolute path resolution
* Config: check pkg dirs on config creation
* Instantiate config with kwargs, not namespace
* WIP: still pulling the threads
* Init seems to be working
* tests passing locally, still need to update cache
* Fix tox command
* unused import
* Fix typing
* Be more selective in exec() in setup.py
* Require accurate casing for hash algos
* Remove old comment
* Comments, minor updates and simplifications
* move _logwrite to a more reasonable place
* Update config to work with cache
* Type cachemanager listdir in core
* Update config module docstring, rename method
* Add more comments re: paste config
* Add comments to main, remove unneded check
* Remove commented code
* Use {posargs} instead of [] for clarity in tox
* Add dupe check for kwarg updater
* Remove unused references on app instance
* Fix typo
* Remove redundancy in log level parsing
2020-10-26 00:48:28 +01:00
|
|
|
exp_config_values={"host": "1.1.1.1"},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: host specified",
|
|
|
|
args=["run", "-H", "1.1.1.1"],
|
|
|
|
legacy_args=["-H", "1.1.1.1"],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"host": "1.1.1.1"},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: host specified (long form)",
|
|
|
|
args=["run", "--host", "1.1.1.1"],
|
|
|
|
legacy_args=["--host", "1.1.1.1"],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"host": "1.1.1.1"},
|
2020-10-09 02:37:39 +02:00
|
|
|
),
|
|
|
|
# authenticate
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: authenticate unspecified",
|
|
|
|
args=["run"],
|
|
|
|
legacy_args=[],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"authenticate": DEFAULTS.AUTHENTICATE},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: authenticate specified as non-default value",
|
|
|
|
args=["run", "-a", "list"],
|
|
|
|
legacy_args=["-a", "list"],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"authenticate": ["list"]},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: authenticate specified with multiple values",
|
|
|
|
args=["run", "-a", "list, update,download"],
|
|
|
|
legacy_args=["-a", "list, update,download"],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"authenticate": ["download", "list", "update"]},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: authenticate specified with dot",
|
Use argparse config throughout app (#349)
This PR is a pretty substantial refactor of the entrypoints of pypiserver (`__main__` and `__init__`) to use the argparse-based config added in #339.
- Updated `RunConfig` and `UpdateConfig` classes to have exclusive init kwargs, instead of taking an namespace. This turned out to be much easier when working with the library-style app initialization in `__init__`, both for direct instantiation and via paste config
- Added an `iter_packages()` method to the `RunConfig` to iterate over packages specified by the configuration (note @elfjes, I think that replacing this with e.g. a `backend` reference will be a nice way to tie in #348)
- Added a general-purpose method to map legacy keyword arguments to the `app()` and `paste_app_factory()` functions to updated forms
- Refactored the `paste_app_factory()` to not mutate the incoming dictionary
- Removed all argument-parsing and config-related code from `__main__` and `core`
- Moved `_logwrite` from `__init__` to `__main__`, since that was the only place it was being used after the updates to `core`
- Updated `digest_file` to use `hashlib.new(algo)` instead of `getattr(hashlib, algo)`, because the former supports more algorithms
- Updated `setup.py` to, instead of calling `eval()` on the entirety of `__init__`, to instead just evaluate the line that defines the version
- Assigned the config to a `._pypiserver_config` attribute on the `Bottle` instance to reduce hacky test workarounds
- Fixed the tox config, which I broke in #339
* Config: add auth & absolute path resolution
* Config: check pkg dirs on config creation
* Instantiate config with kwargs, not namespace
* WIP: still pulling the threads
* Init seems to be working
* tests passing locally, still need to update cache
* Fix tox command
* unused import
* Fix typing
* Be more selective in exec() in setup.py
* Require accurate casing for hash algos
* Remove old comment
* Comments, minor updates and simplifications
* move _logwrite to a more reasonable place
* Update config to work with cache
* Type cachemanager listdir in core
* Update config module docstring, rename method
* Add more comments re: paste config
* Add comments to main, remove unneded check
* Remove commented code
* Use {posargs} instead of [] for clarity in tox
* Add dupe check for kwarg updater
* Remove unused references on app instance
* Fix typo
* Remove redundancy in log level parsing
2020-10-26 00:48:28 +01:00
|
|
|
# both auth and pass must be specified as empty if one of them is empty.
|
|
|
|
args=["run", "-a", ".", "-P", "."],
|
|
|
|
legacy_args=["-a", ".", "-P", "."],
|
2020-10-09 02:37:39 +02:00
|
|
|
exp_config_type=RunConfig,
|
Use argparse config throughout app (#349)
This PR is a pretty substantial refactor of the entrypoints of pypiserver (`__main__` and `__init__`) to use the argparse-based config added in #339.
- Updated `RunConfig` and `UpdateConfig` classes to have exclusive init kwargs, instead of taking an namespace. This turned out to be much easier when working with the library-style app initialization in `__init__`, both for direct instantiation and via paste config
- Added an `iter_packages()` method to the `RunConfig` to iterate over packages specified by the configuration (note @elfjes, I think that replacing this with e.g. a `backend` reference will be a nice way to tie in #348)
- Added a general-purpose method to map legacy keyword arguments to the `app()` and `paste_app_factory()` functions to updated forms
- Refactored the `paste_app_factory()` to not mutate the incoming dictionary
- Removed all argument-parsing and config-related code from `__main__` and `core`
- Moved `_logwrite` from `__init__` to `__main__`, since that was the only place it was being used after the updates to `core`
- Updated `digest_file` to use `hashlib.new(algo)` instead of `getattr(hashlib, algo)`, because the former supports more algorithms
- Updated `setup.py` to, instead of calling `eval()` on the entirety of `__init__`, to instead just evaluate the line that defines the version
- Assigned the config to a `._pypiserver_config` attribute on the `Bottle` instance to reduce hacky test workarounds
- Fixed the tox config, which I broke in #339
* Config: add auth & absolute path resolution
* Config: check pkg dirs on config creation
* Instantiate config with kwargs, not namespace
* WIP: still pulling the threads
* Init seems to be working
* tests passing locally, still need to update cache
* Fix tox command
* unused import
* Fix typing
* Be more selective in exec() in setup.py
* Require accurate casing for hash algos
* Remove old comment
* Comments, minor updates and simplifications
* move _logwrite to a more reasonable place
* Update config to work with cache
* Type cachemanager listdir in core
* Update config module docstring, rename method
* Add more comments re: paste config
* Add comments to main, remove unneded check
* Remove commented code
* Use {posargs} instead of [] for clarity in tox
* Add dupe check for kwarg updater
* Remove unused references on app instance
* Fix typo
* Remove redundancy in log level parsing
2020-10-26 00:48:28 +01:00
|
|
|
exp_config_values={
|
|
|
|
"authenticate": [],
|
|
|
|
"_test": lambda conf: bool(conf.auther("foo", "bar")) is True,
|
|
|
|
},
|
2020-10-09 02:37:39 +02:00
|
|
|
),
|
|
|
|
# passwords
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: passwords file unspecified",
|
|
|
|
args=["run"],
|
|
|
|
legacy_args=[],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"password_file": None},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
"Run: passwords file specified",
|
Use argparse config throughout app (#349)
This PR is a pretty substantial refactor of the entrypoints of pypiserver (`__main__` and `__init__`) to use the argparse-based config added in #339.
- Updated `RunConfig` and `UpdateConfig` classes to have exclusive init kwargs, instead of taking an namespace. This turned out to be much easier when working with the library-style app initialization in `__init__`, both for direct instantiation and via paste config
- Added an `iter_packages()` method to the `RunConfig` to iterate over packages specified by the configuration (note @elfjes, I think that replacing this with e.g. a `backend` reference will be a nice way to tie in #348)
- Added a general-purpose method to map legacy keyword arguments to the `app()` and `paste_app_factory()` functions to updated forms
- Refactored the `paste_app_factory()` to not mutate the incoming dictionary
- Removed all argument-parsing and config-related code from `__main__` and `core`
- Moved `_logwrite` from `__init__` to `__main__`, since that was the only place it was being used after the updates to `core`
- Updated `digest_file` to use `hashlib.new(algo)` instead of `getattr(hashlib, algo)`, because the former supports more algorithms
- Updated `setup.py` to, instead of calling `eval()` on the entirety of `__init__`, to instead just evaluate the line that defines the version
- Assigned the config to a `._pypiserver_config` attribute on the `Bottle` instance to reduce hacky test workarounds
- Fixed the tox config, which I broke in #339
* Config: add auth & absolute path resolution
* Config: check pkg dirs on config creation
* Instantiate config with kwargs, not namespace
* WIP: still pulling the threads
* Init seems to be working
* tests passing locally, still need to update cache
* Fix tox command
* unused import
* Fix typing
* Be more selective in exec() in setup.py
* Require accurate casing for hash algos
* Remove old comment
* Comments, minor updates and simplifications
* move _logwrite to a more reasonable place
* Update config to work with cache
* Type cachemanager listdir in core
* Update config module docstring, rename method
* Add more comments re: paste config
* Add comments to main, remove unneded check
* Remove commented code
* Use {posargs} instead of [] for clarity in tox
* Add dupe check for kwarg updater
* Remove unused references on app instance
* Fix typo
* Remove redundancy in log level parsing
2020-10-26 00:48:28 +01:00
|
|
|
args=["run", "-P", HTPASS_TEST_FILE],
|
|
|
|
legacy_args=["-P", HTPASS_TEST_FILE],
|
2020-10-09 02:37:39 +02:00
|
|
|
exp_config_type=RunConfig,
|
Use argparse config throughout app (#349)
This PR is a pretty substantial refactor of the entrypoints of pypiserver (`__main__` and `__init__`) to use the argparse-based config added in #339.
- Updated `RunConfig` and `UpdateConfig` classes to have exclusive init kwargs, instead of taking an namespace. This turned out to be much easier when working with the library-style app initialization in `__init__`, both for direct instantiation and via paste config
- Added an `iter_packages()` method to the `RunConfig` to iterate over packages specified by the configuration (note @elfjes, I think that replacing this with e.g. a `backend` reference will be a nice way to tie in #348)
- Added a general-purpose method to map legacy keyword arguments to the `app()` and `paste_app_factory()` functions to updated forms
- Refactored the `paste_app_factory()` to not mutate the incoming dictionary
- Removed all argument-parsing and config-related code from `__main__` and `core`
- Moved `_logwrite` from `__init__` to `__main__`, since that was the only place it was being used after the updates to `core`
- Updated `digest_file` to use `hashlib.new(algo)` instead of `getattr(hashlib, algo)`, because the former supports more algorithms
- Updated `setup.py` to, instead of calling `eval()` on the entirety of `__init__`, to instead just evaluate the line that defines the version
- Assigned the config to a `._pypiserver_config` attribute on the `Bottle` instance to reduce hacky test workarounds
- Fixed the tox config, which I broke in #339
* Config: add auth & absolute path resolution
* Config: check pkg dirs on config creation
* Instantiate config with kwargs, not namespace
* WIP: still pulling the threads
* Init seems to be working
* tests passing locally, still need to update cache
* Fix tox command
* unused import
* Fix typing
* Be more selective in exec() in setup.py
* Require accurate casing for hash algos
* Remove old comment
* Comments, minor updates and simplifications
* move _logwrite to a more reasonable place
* Update config to work with cache
* Type cachemanager listdir in core
* Update config module docstring, rename method
* Add more comments re: paste config
* Add comments to main, remove unneded check
* Remove commented code
* Use {posargs} instead of [] for clarity in tox
* Add dupe check for kwarg updater
* Remove unused references on app instance
* Fix typo
* Remove redundancy in log level parsing
2020-10-26 00:48:28 +01:00
|
|
|
exp_config_values={
|
|
|
|
"password_file": HTPASS_TEST_FILE,
|
|
|
|
"_test": lambda conf: (
|
|
|
|
bool(conf.auther("foo", "bar")) is False
|
|
|
|
and bool(conf.auther("a", "a")) is True
|
|
|
|
),
|
|
|
|
},
|
2020-10-09 02:37:39 +02:00
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
"Run: passwords file specified (long-form)",
|
Use argparse config throughout app (#349)
This PR is a pretty substantial refactor of the entrypoints of pypiserver (`__main__` and `__init__`) to use the argparse-based config added in #339.
- Updated `RunConfig` and `UpdateConfig` classes to have exclusive init kwargs, instead of taking an namespace. This turned out to be much easier when working with the library-style app initialization in `__init__`, both for direct instantiation and via paste config
- Added an `iter_packages()` method to the `RunConfig` to iterate over packages specified by the configuration (note @elfjes, I think that replacing this with e.g. a `backend` reference will be a nice way to tie in #348)
- Added a general-purpose method to map legacy keyword arguments to the `app()` and `paste_app_factory()` functions to updated forms
- Refactored the `paste_app_factory()` to not mutate the incoming dictionary
- Removed all argument-parsing and config-related code from `__main__` and `core`
- Moved `_logwrite` from `__init__` to `__main__`, since that was the only place it was being used after the updates to `core`
- Updated `digest_file` to use `hashlib.new(algo)` instead of `getattr(hashlib, algo)`, because the former supports more algorithms
- Updated `setup.py` to, instead of calling `eval()` on the entirety of `__init__`, to instead just evaluate the line that defines the version
- Assigned the config to a `._pypiserver_config` attribute on the `Bottle` instance to reduce hacky test workarounds
- Fixed the tox config, which I broke in #339
* Config: add auth & absolute path resolution
* Config: check pkg dirs on config creation
* Instantiate config with kwargs, not namespace
* WIP: still pulling the threads
* Init seems to be working
* tests passing locally, still need to update cache
* Fix tox command
* unused import
* Fix typing
* Be more selective in exec() in setup.py
* Require accurate casing for hash algos
* Remove old comment
* Comments, minor updates and simplifications
* move _logwrite to a more reasonable place
* Update config to work with cache
* Type cachemanager listdir in core
* Update config module docstring, rename method
* Add more comments re: paste config
* Add comments to main, remove unneded check
* Remove commented code
* Use {posargs} instead of [] for clarity in tox
* Add dupe check for kwarg updater
* Remove unused references on app instance
* Fix typo
* Remove redundancy in log level parsing
2020-10-26 00:48:28 +01:00
|
|
|
args=["run", "--passwords", HTPASS_TEST_FILE],
|
|
|
|
legacy_args=["--passwords", HTPASS_TEST_FILE],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={
|
|
|
|
"password_file": HTPASS_TEST_FILE,
|
|
|
|
"_test": (
|
|
|
|
lambda conf: (
|
|
|
|
bool(conf.auther("foo", "bar")) is False
|
|
|
|
and conf.auther("a", "a") is True
|
|
|
|
)
|
|
|
|
),
|
|
|
|
},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
"Run: passwords file empty ('.')",
|
|
|
|
# both auth and pass must be specified as empty if one of them is empty.
|
|
|
|
args=["run", "-P", ".", "-a", "."],
|
|
|
|
legacy_args=["-P", ".", "-a", "."],
|
2020-10-09 02:37:39 +02:00
|
|
|
exp_config_type=RunConfig,
|
Use argparse config throughout app (#349)
This PR is a pretty substantial refactor of the entrypoints of pypiserver (`__main__` and `__init__`) to use the argparse-based config added in #339.
- Updated `RunConfig` and `UpdateConfig` classes to have exclusive init kwargs, instead of taking an namespace. This turned out to be much easier when working with the library-style app initialization in `__init__`, both for direct instantiation and via paste config
- Added an `iter_packages()` method to the `RunConfig` to iterate over packages specified by the configuration (note @elfjes, I think that replacing this with e.g. a `backend` reference will be a nice way to tie in #348)
- Added a general-purpose method to map legacy keyword arguments to the `app()` and `paste_app_factory()` functions to updated forms
- Refactored the `paste_app_factory()` to not mutate the incoming dictionary
- Removed all argument-parsing and config-related code from `__main__` and `core`
- Moved `_logwrite` from `__init__` to `__main__`, since that was the only place it was being used after the updates to `core`
- Updated `digest_file` to use `hashlib.new(algo)` instead of `getattr(hashlib, algo)`, because the former supports more algorithms
- Updated `setup.py` to, instead of calling `eval()` on the entirety of `__init__`, to instead just evaluate the line that defines the version
- Assigned the config to a `._pypiserver_config` attribute on the `Bottle` instance to reduce hacky test workarounds
- Fixed the tox config, which I broke in #339
* Config: add auth & absolute path resolution
* Config: check pkg dirs on config creation
* Instantiate config with kwargs, not namespace
* WIP: still pulling the threads
* Init seems to be working
* tests passing locally, still need to update cache
* Fix tox command
* unused import
* Fix typing
* Be more selective in exec() in setup.py
* Require accurate casing for hash algos
* Remove old comment
* Comments, minor updates and simplifications
* move _logwrite to a more reasonable place
* Update config to work with cache
* Type cachemanager listdir in core
* Update config module docstring, rename method
* Add more comments re: paste config
* Add comments to main, remove unneded check
* Remove commented code
* Use {posargs} instead of [] for clarity in tox
* Add dupe check for kwarg updater
* Remove unused references on app instance
* Fix typo
* Remove redundancy in log level parsing
2020-10-26 00:48:28 +01:00
|
|
|
exp_config_values={
|
|
|
|
"password_file": ".",
|
|
|
|
"_test": lambda conf: bool(conf.auther("foo", "bar")) is True,
|
|
|
|
},
|
2020-10-09 02:37:39 +02:00
|
|
|
),
|
|
|
|
# disable-fallback
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: disable-fallback unspecified",
|
|
|
|
args=["run"],
|
|
|
|
legacy_args=[],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"disable_fallback": False},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: disable-fallback set",
|
|
|
|
args=["run", "--disable-fallback"],
|
|
|
|
legacy_args=["--disable-fallback"],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"disable_fallback": True},
|
|
|
|
),
|
|
|
|
# fallback-url
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: fallback-url unspecified",
|
|
|
|
args=["run"],
|
|
|
|
legacy_args=[],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"fallback_url": DEFAULTS.FALLBACK_URL},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: fallback-url specified",
|
|
|
|
args=["run", "--fallback-url", "foobar.com"],
|
|
|
|
legacy_args=["--fallback-url", "foobar.com"],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"fallback_url": "foobar.com"},
|
|
|
|
),
|
|
|
|
# server method
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: server method unspecified",
|
|
|
|
args=["run"],
|
|
|
|
legacy_args=[],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"server_method": DEFAULTS.SERVER_METHOD},
|
|
|
|
),
|
|
|
|
*(
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: server method set to {arg}",
|
|
|
|
args=["run", "--server", arg],
|
|
|
|
legacy_args=["--server", arg],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"server_method": arg},
|
|
|
|
)
|
|
|
|
for arg in (
|
|
|
|
"auto",
|
|
|
|
"cherrypy",
|
|
|
|
"gevent",
|
|
|
|
"gunicorn",
|
|
|
|
"paste",
|
|
|
|
"twisted",
|
|
|
|
"wsgiref",
|
|
|
|
)
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: server method is case insensitive",
|
|
|
|
args=["run", "--server", "CherryPy"],
|
|
|
|
legacy_args=["--server", "CherryPy"],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"server_method": "cherrypy"},
|
|
|
|
),
|
|
|
|
# overwrite
|
|
|
|
ConfigTestCase(
|
|
|
|
"Run: overwrite unset",
|
|
|
|
args=["run"],
|
|
|
|
legacy_args=[],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"overwrite": False},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: overwrite set (long-form)",
|
|
|
|
args=["run", "-o"],
|
|
|
|
legacy_args=["-o"],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"overwrite": True},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: overwrite set (long-form)",
|
|
|
|
args=["run", "--overwrite"],
|
|
|
|
legacy_args=["--overwrite"],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"overwrite": True},
|
|
|
|
),
|
|
|
|
# hash-algo
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: hash-algo unspecified",
|
|
|
|
args=["run"],
|
|
|
|
legacy_args=[],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"hash_algo": DEFAULTS.HASH_ALGO},
|
|
|
|
),
|
|
|
|
*(
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: hash-algo {}",
|
|
|
|
args=["run", "--hash-algo", algo],
|
|
|
|
legacy_args=["--hash-algo", algo],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"hash_algo": algo},
|
|
|
|
)
|
|
|
|
for algo in hashlib.algorithms_available
|
|
|
|
),
|
2020-10-11 21:16:57 +02:00
|
|
|
*(
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: hash-algo disabled",
|
|
|
|
args=["run", "--hash-algo", off_value],
|
|
|
|
legacy_args=["--hash-algo", off_value],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"hash_algo": None},
|
|
|
|
)
|
|
|
|
for off_value in ("0", "off", "false", "no", "NO")
|
|
|
|
),
|
2020-10-09 02:37:39 +02:00
|
|
|
# welcome file
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: welcome file unspecified",
|
|
|
|
args=["run"],
|
|
|
|
legacy_args=[],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={
|
|
|
|
"_test": lambda conf: "Welcome to pypiserver" in conf.welcome_msg
|
|
|
|
},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: custom welcome file specified",
|
|
|
|
args=["run", "--welcome", TEST_WELCOME_FILE],
|
|
|
|
legacy_args=["--welcome", TEST_WELCOME_FILE],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={
|
|
|
|
"_test": lambda conf: "Hello pypiserver tester!" in conf.welcome_msg
|
|
|
|
},
|
|
|
|
),
|
|
|
|
# cache-control
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: cache-control unspecified",
|
|
|
|
args=["run"],
|
|
|
|
legacy_args=[],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"cache_control": None},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: cache-control specified",
|
|
|
|
args=["run", "--cache-control", "1900"],
|
|
|
|
legacy_args=["--cache-control", "1900"],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"cache_control": 1900},
|
|
|
|
),
|
|
|
|
# log-req-frmt
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: log request format unspecified",
|
|
|
|
args=["run"],
|
|
|
|
legacy_args=[],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"log_req_frmt": DEFAULTS.LOG_REQ_FRMT},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: log request format specified",
|
|
|
|
args=["run", "--log-req-frmt", "foo"],
|
|
|
|
legacy_args=["--log-req-frmt", "foo"],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"log_req_frmt": "foo"},
|
|
|
|
),
|
|
|
|
# log-res-frmt
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: log response format unspecified",
|
|
|
|
args=["run"],
|
|
|
|
legacy_args=[],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"log_res_frmt": DEFAULTS.LOG_RES_FRMT},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: log response format specified",
|
|
|
|
args=["run", "--log-res-frmt", "foo"],
|
|
|
|
legacy_args=["--log-res-frmt", "foo"],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"log_res_frmt": "foo"},
|
|
|
|
),
|
|
|
|
# log-err-frmt
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: log error format unspecified",
|
|
|
|
args=["run"],
|
|
|
|
legacy_args=[],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"log_err_frmt": DEFAULTS.LOG_ERR_FRMT},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Run: log error format specified",
|
|
|
|
args=["run", "--log-err-frmt", "foo"],
|
|
|
|
legacy_args=["--log-err-frmt", "foo"],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={"log_err_frmt": "foo"},
|
|
|
|
),
|
Refactor storage operations into separate Backend classes (#348)
Following the discussion in #253 and #325 I've created a first iteration on what a `Backend` interface could look like and how the current file storage operations may be refactored into this interface. It goes from the following principles
* `app.py` talks only to `core.py` with regards to package operations
* at configuration time, a `Backend` implementation is chosen and created for the lifetime of the configured app
* `core.py` proxies requests for packages to this `Backend()`
* The `Backend` interface/api is defined through three things
* methods that an implementation must implement
* methods that an implementation may override if it knows better than the defaults
* the `PkgFIle` class that is (should be) the main carrier of data
* where possible, implementation details must be hidden from concrete `Backend`s to promote extensibility
Other things I've done in this PR:
* I've tried to talk about packages and projects, rather than files and prefixes, since these are the domain terms PEP503 uses, and imho it's also more clear what it means
* Better testability of the `CacheManager` (no more race conditions when `watchdog` is installed during testing)
* Cleanup some more Python 2 code
* Started moving away from `os.path` and `py.path` in favour of `pathlib`
Furthermore I've created a `plugin.py` with a sample of how I think plugin system could look like. This sampIe assumes we use `argparse` and allows for the extension of cli arguments that a plugin may need. I think the actual implementation of such a plugin system is beyond the scope of this PR, but I've used it as a target for the Backend refactoring. If requested, I'll remove it from this PR.
The following things still need to be done / discussed. These can be part of this PR or moved into their own, separate PRs
- [ ] Simplify the `PgkFile` class. It currently consists of a number of attributes that don't necessarily belong with it, and not all attributes are aptly named (imho). I would like to minimalize the scope of `PkgFile` so that its only concern is being a data carrier between the app and the backends, and make its use more clear.
- [ ] Add a `PkgFile.metadata` that backend implementations may use to store custom data for packages. For example the current `PkgFile.root` attribute is an implementation detail of the filestorage backends, and other Backend implementations should not be bothered by it.
- [ ] Use `pathlib` wherever possible. This may also result in less attributes for `PkgFile`, since some things may be just contained in a single `Path` object, instead of multtiple strings.
- [ ] Improve testing of the `CacheManager`.
----
* move some functions around in preparation for backend module
* rename pkg_utils to pkg_helpers to prevent confusion with stdlib pkgutil
* further implement the current filestorage as simple file backend
* rename prefix to project, since that's more descriptive
* add digester func as attribute to pkgfile
* WIP caching backend
* WIP make cache better testable
* better testability of cache
* WIP file backends as plugin
* fix typos, run black
* Apply suggestions from code review
Co-authored-by: Matthew Planchard <mplanchard@users.noreply.github.com>
* add more type hints to pass mypy, fix tox.ini
* add package count method to backend
* add package count method to backend
* minor changes
* bugfix when checking invalid whl file
* check for existing package recursively, bugfix, some more pathlib
* fix unittest
* rm dead code
* exclude bottle.py from coverage
* fix merge mistakes
* fix tab indentation
* backend as a cli argument
* fix cli, add tests
* fix mypy
* fix more silly mistakes
* process feedback
* remove dead code
Co-authored-by: Matthew Planchard <mplanchard@users.noreply.github.com>
2021-02-02 18:44:29 +01:00
|
|
|
# backend
|
|
|
|
ConfigTestCase(
|
|
|
|
"Run: backend unspecified",
|
|
|
|
args=["run"],
|
|
|
|
legacy_args=[],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={
|
|
|
|
"backend_arg": "auto",
|
|
|
|
"_test": (
|
|
|
|
lambda conf: (
|
|
|
|
isinstance(conf.backend, BackendProxy)
|
|
|
|
and isinstance(conf.backend.backend, SimpleFileBackend)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
"Run: simple backend specified",
|
|
|
|
args=["run", "--backend", "simple-dir"],
|
|
|
|
legacy_args=["--backend", "simple-dir"],
|
|
|
|
exp_config_type=RunConfig,
|
|
|
|
exp_config_values={
|
|
|
|
"_test": (
|
|
|
|
lambda conf: (
|
|
|
|
isinstance(conf.backend.backend, SimpleFileBackend)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
},
|
|
|
|
),
|
2020-10-09 02:37:39 +02:00
|
|
|
# ******************************************************************
|
|
|
|
# Update subcommand args
|
|
|
|
# ******************************************************************
|
|
|
|
# exeucte
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Update: execute not specified",
|
|
|
|
args=["update"],
|
|
|
|
legacy_args=["-U"],
|
|
|
|
exp_config_type=UpdateConfig,
|
|
|
|
exp_config_values={"execute": False},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Update: execute specified",
|
|
|
|
args=["update", "-x"],
|
|
|
|
legacy_args=["-U", "-x"],
|
|
|
|
exp_config_type=UpdateConfig,
|
|
|
|
exp_config_values={"execute": True},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Update: execute specified (long-form)",
|
|
|
|
args=["update", "--execute"],
|
|
|
|
legacy_args=["-U", "--execute"],
|
|
|
|
exp_config_type=UpdateConfig,
|
|
|
|
exp_config_values={"execute": True},
|
|
|
|
),
|
|
|
|
# download-directory
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Update: download-directory not specified",
|
|
|
|
args=["update"],
|
|
|
|
legacy_args=["-U"],
|
|
|
|
exp_config_type=UpdateConfig,
|
|
|
|
exp_config_values={"download_directory": None},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Update: download-directory specified",
|
|
|
|
args=["update", "-d", "foo"],
|
|
|
|
legacy_args=["-U", "-d", "foo"],
|
|
|
|
exp_config_type=UpdateConfig,
|
|
|
|
exp_config_values={"download_directory": "foo"},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Update: download-directory specified (long-form)",
|
|
|
|
args=["update", "--download-directory", "foo"],
|
|
|
|
legacy_args=["-U", "--download-directory", "foo"],
|
|
|
|
exp_config_type=UpdateConfig,
|
|
|
|
exp_config_values={"download_directory": "foo"},
|
|
|
|
),
|
|
|
|
# allow-unstable
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Update: allow-unstable not specified",
|
|
|
|
args=["update"],
|
|
|
|
legacy_args=["-U"],
|
|
|
|
exp_config_type=UpdateConfig,
|
|
|
|
exp_config_values={"allow_unstable": False},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Update: allow-unstable specified",
|
|
|
|
args=["update", "-u"],
|
|
|
|
legacy_args=["-U", "-u"],
|
|
|
|
exp_config_type=UpdateConfig,
|
|
|
|
exp_config_values={"allow_unstable": True},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Update: allow-unstable specified (long-form)",
|
|
|
|
args=["update", "--allow-unstable"],
|
|
|
|
legacy_args=["-U", "--allow-unstable"],
|
|
|
|
exp_config_type=UpdateConfig,
|
|
|
|
exp_config_values={"allow_unstable": True},
|
|
|
|
),
|
|
|
|
# ignorelist-file
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Update: ignorelist-file not specified",
|
|
|
|
args=["update"],
|
|
|
|
legacy_args=["-U"],
|
|
|
|
exp_config_type=UpdateConfig,
|
|
|
|
exp_config_values={"ignorelist": []},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Update: ignorelist-file specified",
|
|
|
|
args=["update", "--ignorelist-file", TEST_IGNORELIST_FILE],
|
|
|
|
legacy_args=["-U", "--ignorelist-file", TEST_IGNORELIST_FILE],
|
|
|
|
exp_config_type=UpdateConfig,
|
|
|
|
exp_config_values={"ignorelist": ["mypiserver", "something"]},
|
|
|
|
),
|
|
|
|
ConfigTestCase(
|
|
|
|
case="Update: blacklist-file specified",
|
|
|
|
args=["update", "--blacklist-file", TEST_IGNORELIST_FILE],
|
|
|
|
legacy_args=["-U", "--blacklist-file", TEST_IGNORELIST_FILE],
|
|
|
|
exp_config_type=UpdateConfig,
|
|
|
|
exp_config_values={"ignorelist": ["mypiserver", "something"]},
|
|
|
|
),
|
|
|
|
)
|
|
|
|
|
|
|
|
# Split case names out from cases to use as pytest IDs.
|
|
|
|
# pylint: disable=unsubscriptable-object
|
|
|
|
CONFIG_TEST_PARAMS = (i[1:] for i in _CONFIG_TEST_PARAMS)
|
|
|
|
# pylint: enable=unsubscriptable-object
|
|
|
|
CONFIG_TEST_IDS = (i.case for i in _CONFIG_TEST_PARAMS)
|
|
|
|
|
|
|
|
|
2020-10-11 21:16:57 +02:00
|
|
|
class ConfigErrorCase(t.NamedTuple):
|
|
|
|
"""Configuration arguments that should cause errors.
|
|
|
|
|
|
|
|
The cases include a case descrpition, a list of arguments,
|
|
|
|
and, if desired, expected text that should be part of what
|
|
|
|
is printed out to stderr. If no text is provided, the content
|
|
|
|
of stderr will not be checked.
|
|
|
|
"""
|
|
|
|
|
|
|
|
case: str
|
|
|
|
args: t.List[str]
|
|
|
|
exp_txt: t.Optional[str]
|
|
|
|
|
|
|
|
|
|
|
|
_CONFIG_ERROR_CASES = (
|
|
|
|
*(
|
|
|
|
ConfigErrorCase(
|
|
|
|
case=f"Invalid hash algo: {val}",
|
|
|
|
args=["run", "--hash-algo", val],
|
|
|
|
exp_txt=f"Hash algorithm '{val}' is not available",
|
|
|
|
)
|
|
|
|
for val in ("true", "foo", "1", "md6")
|
|
|
|
),
|
|
|
|
)
|
|
|
|
# pylint: disable=unsubscriptable-object
|
|
|
|
CONFIG_ERROR_PARAMS = (i[1:] for i in _CONFIG_ERROR_CASES)
|
|
|
|
# pylint: enable=unsubscriptable-object
|
|
|
|
CONFIG_ERROR_IDS = (i.case for i in _CONFIG_ERROR_CASES)
|
|
|
|
|
|
|
|
|
2020-10-09 02:37:39 +02:00
|
|
|
@pytest.mark.parametrize(
|
|
|
|
"args, legacy_args, exp_config_type, exp_config_values",
|
|
|
|
CONFIG_TEST_PARAMS,
|
|
|
|
ids=CONFIG_TEST_IDS,
|
|
|
|
)
|
|
|
|
def test_config(
|
|
|
|
args: t.List[str],
|
|
|
|
legacy_args: t.List[str],
|
|
|
|
exp_config_type: t.Type,
|
|
|
|
exp_config_values: t.Dict[str, t.Any],
|
|
|
|
) -> None:
|
|
|
|
"""Validate config test cases."""
|
|
|
|
conf = Config.from_args(args)
|
|
|
|
conf_legacy = Config.from_args(legacy_args)
|
|
|
|
|
|
|
|
assert isinstance(conf, exp_config_type)
|
|
|
|
assert all(
|
|
|
|
getattr(conf, k) == v
|
|
|
|
for k, v in exp_config_values.items()
|
|
|
|
if k != "_test"
|
|
|
|
), {
|
|
|
|
k: (getattr(conf, k), v)
|
|
|
|
for k, v in exp_config_values.items()
|
|
|
|
if k != "_test" and getattr(conf, k) != v
|
|
|
|
}
|
|
|
|
|
|
|
|
if "_test" in exp_config_values:
|
|
|
|
assert exp_config_values["_test"](conf)
|
|
|
|
|
|
|
|
assert conf == conf_legacy
|
|
|
|
|
|
|
|
|
2020-10-11 21:16:57 +02:00
|
|
|
@pytest.mark.parametrize(
|
|
|
|
"args, exp_txt",
|
|
|
|
CONFIG_ERROR_PARAMS,
|
|
|
|
ids=CONFIG_TEST_IDS,
|
|
|
|
)
|
|
|
|
def test_config_error(
|
|
|
|
args: t.List[str],
|
|
|
|
exp_txt: t.Optional[str],
|
|
|
|
capsys,
|
|
|
|
) -> None:
|
|
|
|
"""Validate error cases."""
|
|
|
|
with pytest.raises(SystemExit):
|
|
|
|
Config.from_args(args)
|
|
|
|
# Unfortunatley the error text is printed before the SystemExit is
|
|
|
|
# raised, rather than being raised _with_ the systemexit, so we
|
|
|
|
# need to capture stderr and check it for our expected text, if
|
|
|
|
# any was specified in the test case.
|
|
|
|
if exp_txt is not None:
|
|
|
|
assert exp_txt in capsys.readouterr().err
|
|
|
|
|
|
|
|
|
2020-10-09 02:37:39 +02:00
|
|
|
def test_argv_conf():
|
|
|
|
"""Config uses argv if no args are provided."""
|
|
|
|
orig_args = list(sys.argv)
|
|
|
|
|
|
|
|
sys.argv = [sys.argv[0], "run", "-v", "--disable-fallback"]
|
|
|
|
|
|
|
|
try:
|
|
|
|
conf = Config.from_args()
|
|
|
|
assert isinstance(conf, RunConfig)
|
|
|
|
assert conf.verbosity == 1
|
|
|
|
assert conf.disable_fallback is True
|
|
|
|
finally:
|
|
|
|
sys.argv = orig_args
|