Skip to content

Commit

Permalink
Revert "feat: Add optional typer subcommands (#723)"
Browse files Browse the repository at this point in the history
This reverts commit d734167.
  • Loading branch information
mattkram committed Oct 21, 2024
1 parent a69f2ac commit 422d229
Show file tree
Hide file tree
Showing 20 changed files with 55 additions and 2,038 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/check-master.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,6 @@ jobs:
conda list --show-channel-urls
- name: Run tests
env:
_TYPER_FORCE_DISABLE_TERMINAL: 1
run: |
mkdir -p .artifacts/reports
python scripts/refresh_coveragerc.py
Expand Down
154 changes: 0 additions & 154 deletions binstar_client/commands/authorizations.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,8 @@
import socket
import sys
import typing
from enum import Enum

import pytz
import typer
from dateutil.parser import parse as parse_date

from binstar_client import errors
Expand Down Expand Up @@ -273,155 +271,3 @@ def add_parser(subparsers):
action='store_true', help='Show information about the current authentication token')

parser.set_defaults(main=main)


def _exclusive_action(ctx: typer.Context, param: typer.CallbackParam, value: str) -> str:
"""Check for exclusivity of action options.
To do this, we attach a new special attribute onto the typer Context the first time
one of the options in the group is used.
"""
# pylint: disable=protected-access,invalid-name
if getattr(ctx, '_actions', None) is None:
ctx._actions = set() # type: ignore
if value:
if ctx._actions: # type: ignore
used_action, = ctx._actions # type: ignore
raise typer.BadParameter(f'mutually exclusive with {used_action}')
ctx._actions.add(' / '.join(f'\'{o}\'' for o in param.opts)) # type: ignore
return value


class TokenStrength(Enum):
"""Available options for strength when creating a token."""
STRONG = 'strong'
WEAK = 'weak'


def mount_subcommand(app: typer.Typer, name: str, hidden: bool, help_text: str, context_settings: dict) -> None:
@app.command(
name=name,
hidden=hidden,
help=help_text,
context_settings=context_settings,
# no_args_is_help=True,
)
def auth_subcommand(
ctx: typer.Context,
name_: str = typer.Option(
...,
'-n',
'--name',
default_factory=lambda: f'binstar_token:{socket.gethostname()}',
help='A unique name so you can identify this token later. View your tokens at anaconda.org/settings/access'
),
organization: typing.Optional[str] = typer.Option(
None,
'-o',
'--org',
'--organization',
help='Set the token owner (must be an organization)',
),
strength: TokenStrength = typer.Option(
default='strong',
help='Specify the strength of the token',
),
strong: typing.Optional[bool] = typer.Option(
None,
help='Create a longer token (default)',
),
weak: typing.Optional[bool] = typer.Option(
None,
'-w',
'--weak',
help='Create a shorter token',
),
url: str = typer.Option(
'http://anaconda.org',
help='The url of the application that will use this token',
),
max_age: typing.Optional[int] = typer.Option(
None,
help='The maximum age in seconds that this token will be valid for',
),
scopes: typing.Optional[typing.List[str]] = typer.Option(
[],
'-s',
'--scopes',
help=(
'Scopes for token. ' +
'For example if you want to limit this token to conda downloads only you would use ' +
'--scopes "repo conda:download". You can also provide multiple scopes by providing ' +
'this option multiple times, e.g. --scopes repo --scopes conda:download.'
),
),
out: typing.Optional[typer.FileTextWrite] = typer.Option(
sys.stdout,
),
list_scopes: typing.Optional[bool] = typer.Option(
False,
'-x',
'--list-scopes',
help='List all authentication scopes',
callback=_exclusive_action,
),
list_: typing.Optional[bool] = typer.Option(
False,
'-l',
'--list',
help='List all user authentication tokens',
callback=_exclusive_action,
),
create: typing.Optional[bool] = typer.Option(
False,
'-c',
'--create',
help='Create an authentication token',
callback=_exclusive_action,
),
info: typing.Optional[bool] = typer.Option(
False,
'-i',
'--info',
'--current-info',
help='Show information about the current authentication token',
callback=_exclusive_action,
),
remove: typing.List[str] = typer.Option(
[],
'-r',
'--remove',
help='Remove authentication tokens. Multiple token names can be provided',
callback=_exclusive_action,
),
) -> None:
# pylint: disable=too-many-arguments,too-many-locals,fixme
if not any([list_scopes, list_, create, info, remove]):
raise typer.BadParameter('one of --list-scopes, --list, --list, --info, or --remove must be provided')

if weak:
strength = TokenStrength.WEAK
if strong:
# Strong overrides everything
strength = TokenStrength.STRONG

args = argparse.Namespace(
token=ctx.obj.params.get('token'),
site=ctx.obj.params.get('site'),
name=name_,
organization=organization,
strength=strength.value,
list_scopes=list_scopes,
list=list_,
create=create,
info=info,
# TODO: The default of None here is to match existing argparse behavior
remove=remove or None,
url=url,
max_age=max_age,
scopes=scopes,
out=out,
)

main(args=args)
112 changes: 0 additions & 112 deletions binstar_client/commands/channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@
import argparse
import functools
import logging
from typing import List, Optional, Tuple, Union

import typer

from binstar_client.utils import get_server_api

Expand Down Expand Up @@ -106,112 +103,3 @@ def _add_parser(subparsers, name, deprecated=False):
def add_parser(subparsers):
_add_parser(subparsers, name='label')
_add_parser(subparsers, name='channel', deprecated=True)


def _parse_optional_tuple(value: Optional[Tuple[str, str]]) -> Optional[List[str]]:
# pylint: disable=fixme
# Convert a sentinel tuple of empty strings to None, since it is not possible with typer parser or callback
if value == ('', '') or value is None:
return None
# TODO: We only return a list because argparse does. Should really be a tuple.
return list(value)


def _exclusive_action(
ctx: typer.Context,
param: typer.CallbackParam,
value: Union[str, Tuple[str, str]],
) -> Union[str, Tuple[str, str]]:
"""Check for exclusivity of action options.
To do this, we attach a new special attribute onto the typer Context the first time
one of the options in the group is used.
"""
# pylint: disable=protected-access,invalid-name
parsed_value: Union[List[str], str, None]
if isinstance(value, tuple):
# This is here so we can treat the empty tuple as falsy, but I don't like it
parsed_value = _parse_optional_tuple(value)
else:
parsed_value = value

if getattr(ctx, '_actions', None) is None:
ctx._actions = set() # type: ignore
if parsed_value:
if ctx._actions: # type: ignore
used_action, = ctx._actions # type: ignore
raise typer.BadParameter(f'mutually exclusive with {used_action}')
ctx._actions.add(' / '.join(f'\'{o}\'' for o in param.opts)) # type: ignore
return value


def mount_subcommand(app: typer.Typer, name: str, hidden: bool, help_text: str, context_settings: dict) -> None:

@app.command(
name=name,
hidden=hidden,
help=help_text,
context_settings=context_settings,
# no_args_is_help=True,
)
def channel(
ctx: typer.Context,
organization: Optional[str] = typer.Option(
None,
'-o',
'--organization',
help='Manage an organizations {}s'.format(name),
),
copy: Optional[Tuple[str, str]] = typer.Option(
('', ''),
help=f'Copy a package from one {name} to another',
show_default=False,
callback=_exclusive_action,
),
list_: Optional[bool] = typer.Option(
False,
'--list',
is_flag=True,
help=f'List all {name}s for a user',
callback=_exclusive_action,
),
show: Optional[str] = typer.Option(
None,
help=f'Show all of the files in a {name}',
callback=_exclusive_action,
),
lock: Optional[str] = typer.Option(
None,
help=f'Lock a {name}',
callback=_exclusive_action,
),
unlock: Optional[str] = typer.Option(
None,
help=f'Unlock a {name}',
callback=_exclusive_action,
),
remove: Optional[str] = typer.Option(
None,
help=f'Remove a {name}',
callback=_exclusive_action,
),
) -> None:
# pylint: disable=too-many-arguments
parsed_copy = _parse_optional_tuple(copy)
if not any([parsed_copy, list_, show, lock, unlock, remove]):
raise typer.BadParameter('one of --copy, --list, --show, --lock, --unlock, or --remove must be provided')

args = argparse.Namespace(
token=ctx.obj.params.get('token'),
site=ctx.obj.params.get('site'),
organization=organization,
copy=parsed_copy,
list=list_,
show=show,
lock=lock,
unlock=unlock,
remove=remove,
)

main(args=args, name='channel', deprecated=True)
Loading

0 comments on commit 422d229

Please sign in to comment.