mirror of
https://github.com/ArchiveBox/ArchiveBox
synced 2024-11-21 19:53:06 +00:00
Merge branch 'newchanges' into dev
This commit is contained in:
commit
4dd53dc12a
6 changed files with 75 additions and 105 deletions
|
@ -1,48 +1,36 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
__package__ = 'archivebox.cli'
|
__package__ = 'archivebox.cli'
|
||||||
__command__ = 'archivebox config'
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import argparse
|
import rich_click as click
|
||||||
from pathlib import Path
|
from rich import print
|
||||||
|
from benedict import benedict
|
||||||
|
|
||||||
from typing import Optional, List, IO
|
from archivebox.misc.util import docstring, enforce_types
|
||||||
|
from archivebox.misc.toml_util import CustomTOMLEncoder
|
||||||
from archivebox.misc.util import docstring
|
|
||||||
from archivebox.config import DATA_DIR
|
|
||||||
from archivebox.misc.logging_util import SmartFormatter, accept_stdin
|
|
||||||
|
|
||||||
|
|
||||||
|
@enforce_types
|
||||||
# @enforce_types
|
def config(*keys,
|
||||||
def config(config_options_str: Optional[str]=None,
|
get: bool=False,
|
||||||
config_options: Optional[List[str]]=None,
|
set: bool=False,
|
||||||
get: bool=False,
|
search: bool=False,
|
||||||
set: bool=False,
|
reset: bool=False,
|
||||||
search: bool=False,
|
**kwargs) -> None:
|
||||||
reset: bool=False,
|
|
||||||
out_dir: Path=DATA_DIR) -> None:
|
|
||||||
"""Get and set your ArchiveBox project configuration values"""
|
"""Get and set your ArchiveBox project configuration values"""
|
||||||
|
|
||||||
from rich import print
|
import archivebox
|
||||||
|
from archivebox.misc.checks import check_data_folder
|
||||||
|
from archivebox.misc.logging_util import printable_config
|
||||||
|
from archivebox.config.collection import load_all_config, write_config_file, get_real_name
|
||||||
|
|
||||||
check_data_folder()
|
check_data_folder()
|
||||||
if config_options and config_options_str:
|
|
||||||
stderr(
|
|
||||||
'[X] You should either pass config values as an arguments '
|
|
||||||
'or via stdin, but not both.\n',
|
|
||||||
color='red',
|
|
||||||
)
|
|
||||||
raise SystemExit(2)
|
|
||||||
elif config_options_str:
|
|
||||||
config_options = config_options_str.split('\n')
|
|
||||||
|
|
||||||
FLAT_CONFIG = archivebox.pm.hook.get_FLAT_CONFIG()
|
FLAT_CONFIG = archivebox.pm.hook.get_FLAT_CONFIG()
|
||||||
CONFIGS = archivebox.pm.hook.get_CONFIGS()
|
CONFIGS = archivebox.pm.hook.get_CONFIGS()
|
||||||
|
|
||||||
config_options = config_options or []
|
config_options: list[str] = list(kwargs.pop('key=value', []) or keys or [f'{key}={val}' for key, val in kwargs.items()])
|
||||||
|
|
||||||
no_args = not (get or set or reset or config_options)
|
no_args = not (get or set or reset or config_options)
|
||||||
|
|
||||||
matching_config = {}
|
matching_config = {}
|
||||||
|
@ -51,36 +39,47 @@ def config(config_options_str: Optional[str]=None,
|
||||||
config_options = [get_real_name(key) for key in config_options]
|
config_options = [get_real_name(key) for key in config_options]
|
||||||
matching_config = {key: FLAT_CONFIG[key] for key in config_options if key in FLAT_CONFIG}
|
matching_config = {key: FLAT_CONFIG[key] for key in config_options if key in FLAT_CONFIG}
|
||||||
for config_section in CONFIGS.values():
|
for config_section in CONFIGS.values():
|
||||||
aliases = config_section.aliases
|
aliases = getattr(config_section, 'aliases', {})
|
||||||
|
|
||||||
for search_key in config_options:
|
for search_key in config_options:
|
||||||
# search all aliases in the section
|
# search all aliases in the section
|
||||||
for alias_key, key in aliases.items():
|
for alias_key, key in aliases.items():
|
||||||
if search_key.lower() in alias_key.lower():
|
if search_key.lower() in alias_key.lower():
|
||||||
matching_config[key] = config_section.model_dump()[key]
|
matching_config[key] = dict(config_section)[key]
|
||||||
|
|
||||||
# search all keys and values in the section
|
# search all keys and values in the section
|
||||||
for existing_key, value in config_section.model_dump().items():
|
for existing_key, value in dict(config_section).items():
|
||||||
if search_key.lower() in existing_key.lower() or search_key.lower() in str(value).lower():
|
if search_key.lower() in existing_key.lower() or search_key.lower() in str(value).lower():
|
||||||
matching_config[existing_key] = value
|
matching_config[existing_key] = value
|
||||||
|
|
||||||
print(printable_config(matching_config))
|
print(printable_config(matching_config))
|
||||||
raise SystemExit(not matching_config)
|
raise SystemExit(not matching_config)
|
||||||
|
|
||||||
elif get or no_args:
|
elif get or no_args:
|
||||||
if config_options:
|
if config_options:
|
||||||
config_options = [get_real_name(key) for key in config_options]
|
config_options = [get_real_name(key) for key in config_options]
|
||||||
matching_config = {key: FLAT_CONFIG[key] for key in config_options if key in FLAT_CONFIG}
|
matching_config = {key: FLAT_CONFIG[key] for key in config_options if key in FLAT_CONFIG}
|
||||||
failed_config = [key for key in config_options if key not in FLAT_CONFIG]
|
failed_config = [key for key in config_options if key not in FLAT_CONFIG]
|
||||||
if failed_config:
|
if failed_config:
|
||||||
stderr()
|
print('\n[red][X] These options failed to get[/red]')
|
||||||
stderr('[X] These options failed to get', color='red')
|
print(' {}'.format('\n '.join(config_options)))
|
||||||
stderr(' {}'.format('\n '.join(config_options)))
|
|
||||||
raise SystemExit(1)
|
raise SystemExit(1)
|
||||||
else:
|
else:
|
||||||
matching_config = FLAT_CONFIG
|
matching_config = FLAT_CONFIG
|
||||||
|
|
||||||
print(printable_config(matching_config))
|
for config_section in CONFIGS.values():
|
||||||
|
if hasattr(config_section, 'toml_section_header'):
|
||||||
|
print(f'[grey53]\\[{config_section.toml_section_header}][/grey53]')
|
||||||
|
else:
|
||||||
|
print('[grey53]\\[CONSTANTS] # (read-only)[/grey53]')
|
||||||
|
|
||||||
|
kv_in_section = {key: val for key, val in dict(config_section).items() if key in matching_config}
|
||||||
|
print(benedict(kv_in_section).to_toml(encoder=CustomTOMLEncoder()).strip().replace('\n\n', '\n'))
|
||||||
|
print('[grey53]################################################################[/grey53]')
|
||||||
|
|
||||||
|
|
||||||
raise SystemExit(not matching_config)
|
raise SystemExit(not matching_config)
|
||||||
|
|
||||||
elif set:
|
elif set:
|
||||||
new_config = {}
|
new_config = {}
|
||||||
failed_options = []
|
failed_options = []
|
||||||
|
@ -88,15 +87,15 @@ def config(config_options_str: Optional[str]=None,
|
||||||
if line.startswith('#') or not line.strip():
|
if line.startswith('#') or not line.strip():
|
||||||
continue
|
continue
|
||||||
if '=' not in line:
|
if '=' not in line:
|
||||||
stderr('[X] Config KEY=VALUE must have an = sign in it', color='red')
|
print('[red][X] Config KEY=VALUE must have an = sign in it[/red]')
|
||||||
stderr(f' {line}')
|
print(f' {line}')
|
||||||
raise SystemExit(2)
|
raise SystemExit(2)
|
||||||
|
|
||||||
raw_key, val = line.split('=', 1)
|
raw_key, val = line.split('=', 1)
|
||||||
raw_key = raw_key.upper().strip()
|
raw_key = raw_key.upper().strip()
|
||||||
key = get_real_name(raw_key)
|
key = get_real_name(raw_key)
|
||||||
if key != raw_key:
|
if key != raw_key:
|
||||||
stderr(f'[i] Note: The config option {raw_key} has been renamed to {key}, please use the new name going forwards.', color='lightyellow')
|
print(f'[yellow][i] Note: The config option {raw_key} has been renamed to {key}, please use the new name going forwards.[/yellow]')
|
||||||
|
|
||||||
if key in FLAT_CONFIG:
|
if key in FLAT_CONFIG:
|
||||||
new_config[key] = val.strip()
|
new_config[key] = val.strip()
|
||||||
|
@ -113,82 +112,41 @@ def config(config_options_str: Optional[str]=None,
|
||||||
for key, val in after.items():
|
for key, val in after.items():
|
||||||
if key in FLAT_CONFIG and (str(before[key]) != str(after[key])) and (key not in matching_config):
|
if key in FLAT_CONFIG and (str(before[key]) != str(after[key])) and (key not in matching_config):
|
||||||
side_effect_changes[key] = after[key]
|
side_effect_changes[key] = after[key]
|
||||||
# import ipdb; ipdb.set_trace()
|
|
||||||
|
|
||||||
if side_effect_changes:
|
if side_effect_changes:
|
||||||
stderr()
|
print(file=sys.stderr)
|
||||||
stderr('[i] Note: This change also affected these other options that depended on it:', color='lightyellow')
|
print('[yellow][i] Note: This change also affected these other options that depended on it:[/yellow]', file=sys.stderr)
|
||||||
print(' {}'.format(printable_config(side_effect_changes, prefix=' ')))
|
print(' {}'.format(printable_config(side_effect_changes, prefix=' ')), file=sys.stderr)
|
||||||
|
|
||||||
if failed_options:
|
if failed_options:
|
||||||
stderr()
|
print()
|
||||||
stderr('[X] These options failed to set (check for typos):', color='red')
|
print('[red][X] These options failed to set (check for typos):[/red]')
|
||||||
stderr(' {}'.format('\n '.join(failed_options)))
|
print(' {}'.format('\n '.join(failed_options)))
|
||||||
raise SystemExit(1)
|
raise SystemExit(1)
|
||||||
|
|
||||||
elif reset:
|
elif reset:
|
||||||
stderr('[X] This command is not implemented yet.', color='red')
|
print('[red][X] This command is not implemented yet.[/red]')
|
||||||
stderr(' Please manually remove the relevant lines from your config file:')
|
print(' Please manually remove the relevant lines from your config file:')
|
||||||
raise SystemExit(2)
|
raise SystemExit(2)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
stderr('[X] You must pass either --get or --set, or no arguments to get the whole config.', color='red')
|
print('[red][X] You must pass either --get or --set, or no arguments to get the whole config.[/red]')
|
||||||
stderr(' archivebox config')
|
print(' archivebox config')
|
||||||
stderr(' archivebox config --get SOME_KEY')
|
print(' archivebox config --get SOME_KEY')
|
||||||
stderr(' archivebox config --set SOME_KEY=SOME_VALUE')
|
print(' archivebox config --set SOME_KEY=SOME_VALUE')
|
||||||
raise SystemExit(2)
|
raise SystemExit(2)
|
||||||
|
|
||||||
|
|
||||||
|
@click.command()
|
||||||
|
@click.option('--search', is_flag=True, help='Search config KEYs, VALUEs, and ALIASES for the given term')
|
||||||
|
@click.option('--get', is_flag=True, help='Get the value for the given config KEYs')
|
||||||
|
@click.option('--set', is_flag=True, help='Set the given KEY=VALUE config values')
|
||||||
|
@click.option('--reset', is_flag=True, help='Reset the given KEY config values to their defaults')
|
||||||
|
@click.argument('KEY=VALUE', nargs=-1, type=str)
|
||||||
@docstring(config.__doc__)
|
@docstring(config.__doc__)
|
||||||
def main(args: Optional[List[str]]=None, stdin: Optional[IO]=None, pwd: Optional[str]=None) -> None:
|
def main(**kwargs) -> None:
|
||||||
parser = argparse.ArgumentParser(
|
config(**kwargs)
|
||||||
prog=__command__,
|
|
||||||
description=config.__doc__,
|
|
||||||
add_help=True,
|
|
||||||
formatter_class=SmartFormatter,
|
|
||||||
)
|
|
||||||
group = parser.add_mutually_exclusive_group()
|
|
||||||
parser.add_argument(
|
|
||||||
'--search',
|
|
||||||
action='store_true',
|
|
||||||
help="Search config KEYs, VALUEs, and ALIASES for the given term",
|
|
||||||
)
|
|
||||||
group.add_argument(
|
|
||||||
'--get', #'-g',
|
|
||||||
action='store_true',
|
|
||||||
help="Get the value for the given config KEYs",
|
|
||||||
)
|
|
||||||
group.add_argument(
|
|
||||||
'--set', #'-s',
|
|
||||||
action='store_true',
|
|
||||||
help="Set the given KEY=VALUE config values",
|
|
||||||
)
|
|
||||||
group.add_argument(
|
|
||||||
'--reset', #'-s',
|
|
||||||
action='store_true',
|
|
||||||
help="Reset the given KEY config values to their defaults",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
'config_options',
|
|
||||||
nargs='*',
|
|
||||||
type=str,
|
|
||||||
help='KEY or KEY=VALUE formatted config values to get or set',
|
|
||||||
)
|
|
||||||
command = parser.parse_args(args or ())
|
|
||||||
|
|
||||||
config_options_str = ''
|
|
||||||
if not command.config_options:
|
|
||||||
config_options_str = accept_stdin(stdin)
|
|
||||||
|
|
||||||
config(
|
|
||||||
config_options_str=config_options_str,
|
|
||||||
config_options=command.config_options,
|
|
||||||
search=command.search,
|
|
||||||
get=command.get,
|
|
||||||
set=command.set,
|
|
||||||
reset=command.reset,
|
|
||||||
out_dir=Path(pwd) if pwd else DATA_DIR,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main(args=sys.argv[1:], stdin=sys.stdin)
|
main()
|
||||||
|
|
|
@ -12,6 +12,9 @@ from abx_pkg import (
|
||||||
apt = APT_BINPROVIDER = AptProvider()
|
apt = APT_BINPROVIDER = AptProvider()
|
||||||
brew = BREW_BINPROVIDER = BrewProvider()
|
brew = BREW_BINPROVIDER = BrewProvider()
|
||||||
env = ENV_BINPROVIDER = EnvProvider()
|
env = ENV_BINPROVIDER = EnvProvider()
|
||||||
|
apt.setup()
|
||||||
|
brew.setup()
|
||||||
|
env.setup()
|
||||||
|
|
||||||
|
|
||||||
@abx.hookimpl(tryfirst=True)
|
@abx.hookimpl(tryfirst=True)
|
||||||
|
|
|
@ -36,3 +36,6 @@ SYS_NPM_BINPROVIDER = SystemNpmBinProvider()
|
||||||
LIB_NPM_BINPROVIDER = LibNpmBinProvider()
|
LIB_NPM_BINPROVIDER = LibNpmBinProvider()
|
||||||
LIB_NPM_BINPROVIDER.setup()
|
LIB_NPM_BINPROVIDER.setup()
|
||||||
npm = LIB_NPM_BINPROVIDER
|
npm = LIB_NPM_BINPROVIDER
|
||||||
|
|
||||||
|
LIB_NPM_BINPROVIDER.setup()
|
||||||
|
SYS_NPM_BINPROVIDER.setup()
|
||||||
|
|
|
@ -72,6 +72,11 @@ LIB_PIP_BINPROVIDER = LibPipBinProvider()
|
||||||
LIB_PIP_BINPROVIDER.setup()
|
LIB_PIP_BINPROVIDER.setup()
|
||||||
pip = LIB_PIP_BINPROVIDER
|
pip = LIB_PIP_BINPROVIDER
|
||||||
|
|
||||||
|
SYS_PIP_BINPROVIDER.setup()
|
||||||
|
PIPX_PIP_BINPROVIDER.setup()
|
||||||
|
VENV_PIP_BINPROVIDER.setup()
|
||||||
|
LIB_PIP_BINPROVIDER.setup()
|
||||||
|
|
||||||
# ensure python libraries are importable from these locations (if archivebox wasnt executed from one of these then they wont already be in sys.path)
|
# ensure python libraries are importable from these locations (if archivebox wasnt executed from one of these then they wont already be in sys.path)
|
||||||
assert VENV_PIP_BINPROVIDER.pip_venv is not None
|
assert VENV_PIP_BINPROVIDER.pip_venv is not None
|
||||||
assert LIB_PIP_BINPROVIDER.pip_venv is not None
|
assert LIB_PIP_BINPROVIDER.pip_venv is not None
|
||||||
|
|
|
@ -164,3 +164,4 @@ class PlaywrightBinProvider(BinProvider):
|
||||||
return (proc.stderr.strip() + "\n" + proc.stdout.strip()).strip()
|
return (proc.stderr.strip() + "\n" + proc.stdout.strip()).strip()
|
||||||
|
|
||||||
PLAYWRIGHT_BINPROVIDER = PlaywrightBinProvider()
|
PLAYWRIGHT_BINPROVIDER = PlaywrightBinProvider()
|
||||||
|
PLAYWRIGHT_BINPROVIDER.setup()
|
||||||
|
|
|
@ -115,7 +115,7 @@ class PuppeteerBinProvider(BinProvider):
|
||||||
return (proc.stderr.strip() + "\n" + proc.stdout.strip()).strip()
|
return (proc.stderr.strip() + "\n" + proc.stdout.strip()).strip()
|
||||||
|
|
||||||
PUPPETEER_BINPROVIDER = PuppeteerBinProvider()
|
PUPPETEER_BINPROVIDER = PuppeteerBinProvider()
|
||||||
|
PUPPETEER_BINPROVIDER.setup()
|
||||||
|
|
||||||
# ALTERNATIVE INSTALL METHOD using Ansible:
|
# ALTERNATIVE INSTALL METHOD using Ansible:
|
||||||
# install_playbook = self.plugin_dir / 'install_puppeteer.yml'
|
# install_playbook = self.plugin_dir / 'install_puppeteer.yml'
|
||||||
|
|
Loading…
Reference in a new issue