mirror of
https://github.com/httpie/cli.git
synced 2024-11-24 08:22:22 +02:00
Add httpie cli plugins
in favor of the new cli namespace. (#1320)
* Add `httpie cli plugins` in favor of the new cli namespace. * Separate each task to individual modules. * Move httpie.manager.plugins to httpie.manager.tasks.plugins Co-authored-by: Jakub Roztocil <jakub@roztocil.co>
This commit is contained in:
parent
33ea977b64
commit
c157948531
@ -5,8 +5,10 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
|
||||
## [3.1.1.dev0](https://github.com/httpie/httpie/compare/3.1.0...HEAD) (Unreleased)
|
||||
|
||||
- Changed `httpie plugins` to the new `httpie cli` namespace as `httpie cli plugins` (`httpie plugins` continues to work as a hidden alias). ([#1320](https://github.com/httpie/httpie/issues/1320))
|
||||
- Fixed redundant creation of `Content-Length` header on `OPTIONS` requests. ([#1310](https://github.com/httpie/httpie/issues/1310))
|
||||
|
||||
|
||||
## [3.1.0](https://github.com/httpie/httpie/compare/3.0.2...3.1.0) (2022-03-08)
|
||||
|
||||
- **SECURITY** Fixed the [vulnerability](https://github.com/httpie/httpie/security/advisories/GHSA-9w4w-cpc8-h2fq) that caused exposure of cookies on redirects to third party hosts. ([#1312](https://github.com/httpie/httpie/pull/1312))
|
||||
|
@ -2347,7 +2347,7 @@ However, it is not recommended modifying the default behavior in a way that woul
|
||||
#### `plugins_dir`
|
||||
|
||||
The directory where the plugins will be installed. HTTPie needs to have read/write access on that directory, since
|
||||
`httpie plugins install` will download new plugins to there. See [plugin manager](#plugin-manager) for more information.
|
||||
`httpie cli plugins install` will download new plugins to there. See [plugin manager](#plugin-manager) for more information.
|
||||
|
||||
### Un-setting previously specified options
|
||||
|
||||
@ -2425,7 +2425,7 @@ $ httpie cli export-args | jq '"Program: " + .spec.name + ", Version: " + .vers
|
||||
"Program: http, Version: 0.0.1a0"
|
||||
```
|
||||
|
||||
### `httpie plugins`
|
||||
#### `httpie cli plugins`
|
||||
|
||||
`plugins` interface is a very simple plugin manager for installing, listing and uninstalling HTTPie plugins.
|
||||
|
||||
@ -2436,13 +2436,13 @@ plugin installations on every installation method.
|
||||
By default, the plugins (and their missing dependencies) will be stored under the configuration directory,
|
||||
but this can be modified through `plugins_dir` variable on the config.
|
||||
|
||||
#### `httpie plugins install`
|
||||
##### `httpie cli plugins install`
|
||||
|
||||
For installing plugins from [PyPI](https://pypi.org/) or from local paths, `httpie plugins install`
|
||||
For installing plugins from [PyPI](https://pypi.org/) or from local paths, `httpie cli plugins install`
|
||||
can be used.
|
||||
|
||||
```bash
|
||||
$ httpie plugins install httpie-plugin
|
||||
$ httpie cli plugins install httpie-plugin
|
||||
Installing httpie-plugin...
|
||||
Successfully installed httpie-plugin-1.0.2
|
||||
```
|
||||
@ -2450,12 +2450,12 @@ Successfully installed httpie-plugin-1.0.2
|
||||
> Tip: Generally HTTPie plugins start with `httpie-` prefix. Try searching for it on [PyPI](https://pypi.org/search/?q=httpie-)
|
||||
> to find out all plugins from the community.
|
||||
|
||||
#### `httpie plugins list`
|
||||
##### `httpie cli plugins list`
|
||||
|
||||
List all installed plugins.
|
||||
|
||||
```bash
|
||||
$ httpie plugins list
|
||||
$ httpie cli plugins list
|
||||
httpie_plugin (1.0.2)
|
||||
httpie_plugin (httpie.plugins.auth.v1)
|
||||
httpie_plugin_2 (1.0.6)
|
||||
@ -2465,21 +2465,21 @@ httpie_converter (1.0.0)
|
||||
httpie_konsole_konverter (httpie.plugins.converter.v1)
|
||||
```
|
||||
|
||||
#### `httpie plugins upgrade`
|
||||
##### `httpie cli plugins upgrade`
|
||||
|
||||
For upgrading already installed plugins, use `httpie plugins upgrade`.
|
||||
|
||||
```bash
|
||||
$ httpie plugins upgrade httpie-plugin
|
||||
$ httpie cli plugins upgrade httpie-plugin
|
||||
```
|
||||
|
||||
#### `httpie plugins uninstall`
|
||||
##### `httpie cli plugins uninstall`
|
||||
|
||||
Uninstall plugins from the isolated plugins directory. If the plugin is not installed
|
||||
through `httpie plugins install`, it won’t uninstall it.
|
||||
through `httpie cli plugins install`, it won’t uninstall it.
|
||||
|
||||
```bash
|
||||
$ httpie plugins uninstall httpie-plugin
|
||||
$ httpie cli plugins uninstall httpie-plugin
|
||||
```
|
||||
|
||||
## Meta
|
||||
|
@ -12,37 +12,6 @@ CLI_SESSION_UPGRADE_FLAGS = [
|
||||
]
|
||||
|
||||
COMMANDS = {
|
||||
'plugins': {
|
||||
'help': 'Manage HTTPie plugins.',
|
||||
'install': [
|
||||
'Install the given targets from PyPI '
|
||||
'or from a local paths.',
|
||||
{
|
||||
'dest': 'targets',
|
||||
'nargs': '+',
|
||||
'help': 'targets to install'
|
||||
}
|
||||
],
|
||||
'upgrade': [
|
||||
'Upgrade the given plugins',
|
||||
{
|
||||
'dest': 'targets',
|
||||
'nargs': '+',
|
||||
'help': 'targets to upgrade'
|
||||
}
|
||||
],
|
||||
'uninstall': [
|
||||
'Uninstall the given HTTPie plugins.',
|
||||
{
|
||||
'dest': 'targets',
|
||||
'nargs': '+',
|
||||
'help': 'targets to install'
|
||||
}
|
||||
],
|
||||
'list': [
|
||||
'List all installed HTTPie plugins.'
|
||||
],
|
||||
},
|
||||
'cli': {
|
||||
'help': 'Manage HTTPie for Terminal',
|
||||
'export-args': [
|
||||
@ -82,6 +51,39 @@ COMMANDS = {
|
||||
}
|
||||
|
||||
|
||||
COMMANDS['plugins'] = COMMANDS['cli']['plugins'] = {
|
||||
'help': 'Manage HTTPie plugins.',
|
||||
'install': [
|
||||
'Install the given targets from PyPI '
|
||||
'or from a local paths.',
|
||||
{
|
||||
'dest': 'targets',
|
||||
'nargs': '+',
|
||||
'help': 'targets to install'
|
||||
}
|
||||
],
|
||||
'upgrade': [
|
||||
'Upgrade the given plugins',
|
||||
{
|
||||
'dest': 'targets',
|
||||
'nargs': '+',
|
||||
'help': 'targets to upgrade'
|
||||
}
|
||||
],
|
||||
'uninstall': [
|
||||
'Uninstall the given HTTPie plugins.',
|
||||
{
|
||||
'dest': 'targets',
|
||||
'nargs': '+',
|
||||
'help': 'targets to install'
|
||||
}
|
||||
],
|
||||
'list': [
|
||||
'List all installed HTTPie plugins.'
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def missing_subcommand(*args) -> str:
|
||||
base = COMMANDS
|
||||
for arg in args:
|
||||
|
@ -2,7 +2,6 @@ import argparse
|
||||
from typing import Optional
|
||||
|
||||
from httpie.context import Environment
|
||||
from httpie.manager.plugins import PluginInstaller
|
||||
from httpie.status import ExitStatus
|
||||
from httpie.manager.cli import missing_subcommand, parser
|
||||
from httpie.manager.tasks import CLI_TASKS
|
||||
@ -36,8 +35,7 @@ def program(args: argparse.Namespace, env: Environment) -> ExitStatus:
|
||||
parser.error(MSG_NAKED_INVOCATION)
|
||||
|
||||
if args.action == 'plugins':
|
||||
plugins = PluginInstaller(env, debug=args.debug)
|
||||
return plugins.run(args.plugins_action, args)
|
||||
return dispatch_cli_task(env, args.action, args)
|
||||
elif args.action == 'cli':
|
||||
return dispatch_cli_task(env, args.cli_action, args)
|
||||
|
||||
|
9
httpie/manager/tasks/__init__.py
Normal file
9
httpie/manager/tasks/__init__.py
Normal file
@ -0,0 +1,9 @@
|
||||
from httpie.manager.tasks.sessions import cli_sessions
|
||||
from httpie.manager.tasks.export_args import cli_export_args
|
||||
from httpie.manager.tasks.plugins import cli_plugins
|
||||
|
||||
CLI_TASKS = {
|
||||
'sessions': cli_sessions,
|
||||
'export-args': cli_export_args,
|
||||
'plugins': cli_plugins,
|
||||
}
|
27
httpie/manager/tasks/export_args.py
Normal file
27
httpie/manager/tasks/export_args.py
Normal file
@ -0,0 +1,27 @@
|
||||
import argparse
|
||||
import json
|
||||
|
||||
from httpie.cli.definition import options
|
||||
from httpie.cli.options import to_data
|
||||
from httpie.output.writer import write_raw_data
|
||||
from httpie.status import ExitStatus
|
||||
from httpie.context import Environment
|
||||
|
||||
|
||||
FORMAT_TO_CONTENT_TYPE = {
|
||||
'json': 'application/json'
|
||||
}
|
||||
|
||||
|
||||
def cli_export_args(env: Environment, args: argparse.Namespace) -> ExitStatus:
|
||||
if args.format == 'json':
|
||||
data = json.dumps(to_data(options))
|
||||
else:
|
||||
raise NotImplementedError(f'Unexpected format value: {args.format}')
|
||||
|
||||
write_raw_data(
|
||||
env,
|
||||
data,
|
||||
stream_kwargs={'mime_overwrite': FORMAT_TO_CONTENT_TYPE[args.format]},
|
||||
)
|
||||
return ExitStatus.SUCCESS
|
@ -1,18 +1,18 @@
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import textwrap
|
||||
import re
|
||||
import shutil
|
||||
from collections import defaultdict
|
||||
from contextlib import suppress
|
||||
from pathlib import Path
|
||||
from typing import Tuple, Optional, List
|
||||
from typing import List, Optional, Tuple
|
||||
|
||||
from httpie.manager.cli import parser, missing_subcommand
|
||||
from httpie.compat import importlib_metadata, get_dist_name
|
||||
from httpie.compat import get_dist_name, importlib_metadata
|
||||
from httpie.context import Environment
|
||||
from httpie.manager.cli import missing_subcommand, parser
|
||||
from httpie.status import ExitStatus
|
||||
from httpie.utils import as_site
|
||||
|
||||
@ -248,3 +248,14 @@ class PluginInstaller:
|
||||
status = self.list()
|
||||
|
||||
return status or ExitStatus.SUCCESS
|
||||
|
||||
|
||||
def cli_plugins(env: Environment, args: argparse.Namespace) -> ExitStatus:
|
||||
plugins = PluginInstaller(env, debug=args.debug)
|
||||
|
||||
try:
|
||||
action = args.cli_plugins_action
|
||||
except AttributeError:
|
||||
action = args.plugins_action
|
||||
|
||||
return plugins.run(action, args)
|
@ -1,5 +1,5 @@
|
||||
import argparse
|
||||
from typing import TypeVar, Callable, Tuple
|
||||
from typing import Tuple
|
||||
|
||||
from httpie.sessions import SESSIONS_DIR_NAME, get_httpie_session
|
||||
from httpie.status import ExitStatus
|
||||
@ -7,19 +7,7 @@ from httpie.context import Environment
|
||||
from httpie.legacy import cookie_format as legacy_cookies
|
||||
from httpie.manager.cli import missing_subcommand, parser
|
||||
|
||||
T = TypeVar('T')
|
||||
|
||||
CLI_TASKS = {}
|
||||
|
||||
|
||||
def task(name: str) -> Callable[[T], T]:
|
||||
def wrapper(func: T) -> T:
|
||||
CLI_TASKS[name] = func
|
||||
return func
|
||||
return wrapper
|
||||
|
||||
|
||||
@task('sessions')
|
||||
def cli_sessions(env: Environment, args: argparse.Namespace) -> ExitStatus:
|
||||
action = args.cli_sessions_action
|
||||
if action is None:
|
||||
@ -114,28 +102,3 @@ def cli_upgrade_all_sessions(env: Environment, args: argparse.Namespace) -> Exit
|
||||
session_name=session_name
|
||||
)
|
||||
return status
|
||||
|
||||
|
||||
FORMAT_TO_CONTENT_TYPE = {
|
||||
'json': 'application/json'
|
||||
}
|
||||
|
||||
|
||||
@task('export-args')
|
||||
def cli_export(env: Environment, args: argparse.Namespace) -> ExitStatus:
|
||||
import json
|
||||
from httpie.cli.definition import options
|
||||
from httpie.cli.options import to_data
|
||||
from httpie.output.writer import write_raw_data
|
||||
|
||||
if args.format == 'json':
|
||||
data = json.dumps(to_data(options))
|
||||
else:
|
||||
raise NotImplementedError(f'Unexpected format value: {args.format}')
|
||||
|
||||
write_raw_data(
|
||||
env,
|
||||
data,
|
||||
stream_kwargs={'mime_overwrite': FORMAT_TO_CONTENT_TYPE[args.format]},
|
||||
)
|
||||
return ExitStatus.SUCCESS
|
@ -5,8 +5,9 @@ from tests.utils.plugins_cli import parse_listing
|
||||
|
||||
|
||||
@pytest.mark.requires_installation
|
||||
def test_plugins_installation(httpie_plugins_success, interface, dummy_plugin):
|
||||
lines = httpie_plugins_success('install', dummy_plugin.path)
|
||||
@pytest.mark.parametrize('cli_mode', [True, False])
|
||||
def test_plugins_installation(httpie_plugins_success, interface, dummy_plugin, cli_mode):
|
||||
lines = httpie_plugins_success('install', dummy_plugin.path, cli_mode=cli_mode)
|
||||
assert lines[0].startswith(
|
||||
f'Installing {dummy_plugin.path}'
|
||||
)
|
||||
@ -28,8 +29,9 @@ def test_plugin_installation_with_custom_config(httpie_plugins_success, interfac
|
||||
|
||||
|
||||
@pytest.mark.requires_installation
|
||||
def test_plugins_listing(httpie_plugins_success, interface, dummy_plugin):
|
||||
httpie_plugins_success('install', dummy_plugin.path)
|
||||
@pytest.mark.parametrize('cli_mode', [True, False])
|
||||
def test_plugins_listing(httpie_plugins_success, interface, dummy_plugin, cli_mode):
|
||||
httpie_plugins_success('install', dummy_plugin.path, cli_mode=cli_mode)
|
||||
data = parse_listing(httpie_plugins_success('list'))
|
||||
|
||||
assert data == {
|
||||
@ -50,9 +52,10 @@ def test_plugins_listing_multiple(interface, httpie_plugins_success, dummy_plugi
|
||||
|
||||
|
||||
@pytest.mark.requires_installation
|
||||
def test_plugins_uninstall(interface, httpie_plugins_success, dummy_plugin):
|
||||
httpie_plugins_success('install', dummy_plugin.path)
|
||||
httpie_plugins_success('uninstall', dummy_plugin.name)
|
||||
@pytest.mark.parametrize('cli_mode', [True, False])
|
||||
def test_plugins_uninstall(interface, httpie_plugins_success, dummy_plugin, cli_mode):
|
||||
httpie_plugins_success('install', dummy_plugin.path, cli_mode=cli_mode)
|
||||
httpie_plugins_success('uninstall', dummy_plugin.name, cli_mode=cli_mode)
|
||||
assert not interface.is_installed(dummy_plugin.name)
|
||||
|
||||
|
||||
|
@ -208,12 +208,17 @@ def httpie_plugins(interface):
|
||||
from tests.utils import httpie
|
||||
from httpie.plugins.registry import plugin_manager
|
||||
|
||||
def runner(*args):
|
||||
def runner(*args, cli_mode: bool = True):
|
||||
args = list(args)
|
||||
if cli_mode:
|
||||
args.insert(0, 'cli')
|
||||
args.insert(cli_mode, 'plugins')
|
||||
|
||||
# Prevent installed plugins from showing up.
|
||||
original_plugins = plugin_manager.copy()
|
||||
clean_sys_path = set(sys.path).difference(site.getsitepackages())
|
||||
with patch('sys.path', list(clean_sys_path)):
|
||||
response = httpie('plugins', *args, env=interface.environment)
|
||||
response = httpie(*args, env=interface.environment)
|
||||
plugin_manager.clear()
|
||||
plugin_manager.extend(original_plugins)
|
||||
return response
|
||||
@ -223,8 +228,8 @@ def httpie_plugins(interface):
|
||||
|
||||
@pytest.fixture
|
||||
def httpie_plugins_success(httpie_plugins):
|
||||
def runner(*args):
|
||||
response = httpie_plugins(*args)
|
||||
def runner(*args, cli_mode: bool = True):
|
||||
response = httpie_plugins(*args, cli_mode=True)
|
||||
assert response.exit_status == ExitStatus.SUCCESS
|
||||
return response.splitlines()
|
||||
return runner
|
||||
|
Loading…
Reference in New Issue
Block a user