-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
137 changed files
with
2,669 additions
and
1,186 deletions.
There are no files selected for viewing
Empty file.
This file was deleted.
Oops, something went wrong.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
from functools import wraps | ||
|
||
import click | ||
import decorator | ||
from click import get_current_context, Group | ||
|
||
|
||
class State(object): | ||
def __init__(self, format=None, client=None, user_token=None, | ||
list_id=None, part_num=None, color_id=None, set_num=None, api=None): | ||
self.format = format | ||
self.client = client | ||
|
||
self.api = api | ||
self.user_token = user_token | ||
self.list_id = list_id | ||
self.part_num = part_num | ||
self.color_id = color_id | ||
self.set_num = set_num | ||
|
||
|
||
def oprint(obj): | ||
# print an object using the current configured output (json/yaml/py) | ||
get_current_context().find_object(State).format.output(obj) | ||
|
||
|
||
def get_or_push(fun): | ||
@pass_state | ||
@click.pass_context | ||
@wraps(fun) | ||
def decorated(click_context, state, *args, **kwargs): | ||
for attr in kwargs: | ||
setattr(state, attr, kwargs[attr]) | ||
try: | ||
current_obj = fun(*args, **kwargs) | ||
except: | ||
current_obj = fun(state, *args, **kwargs) | ||
if click_context.invoked_subcommand is None: | ||
oprint(current_obj) | ||
else: | ||
click_context.obj = current_obj | ||
|
||
return decorated | ||
|
||
|
||
def object_print(fun): | ||
def object_print_decorator(fun, *args, **kwargs): | ||
obj = fun(*args, **kwargs) | ||
oprint(obj) | ||
|
||
return decorator.decorate(fun, object_print_decorator) | ||
|
||
|
||
def add_typed_subcommands(type_): | ||
def add_fun(fun, attribute_name): | ||
@fun.command(name=attribute_name) | ||
@click.make_pass_decorator(type_) | ||
def type_cmd(obj): | ||
print(getattr(obj, attribute_name)) | ||
|
||
def decorator(fun): | ||
for attribute_name, attribute_type in type_.openapi_types.items(): | ||
add_fun(fun, attribute_name) | ||
|
||
setattr(fun, 'invoke_without_command', True) | ||
|
||
return fun | ||
|
||
return decorator | ||
|
||
|
||
pass_state = click.make_pass_decorator(State) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
import click | ||
|
||
from rebrickable_api import LegoApi, Part, PartColorsElement, Color, Element, Moc, PartCategory, Set, Theme | ||
from rebrickable_cli.cli.common import add_typed_subcommands, pass_state, \ | ||
object_print, oprint, get_or_push | ||
|
||
|
||
@click.group(help='LEGO data (parts, sets, themes, etc.)') | ||
@pass_state | ||
def lego(state): | ||
state.api = LegoApi(state.client) | ||
|
||
|
||
@lego.command('parts') | ||
@pass_state | ||
@object_print | ||
def lego_parts(state): | ||
return state.api.lego_parts_list() | ||
|
||
|
||
@add_typed_subcommands(Part) | ||
@lego.group('part') | ||
@pass_state | ||
@get_or_push | ||
@click.argument('part_num') | ||
def lego_part(state, part_num): | ||
return state.api.lego_parts_read(part_num=state.part_num) | ||
|
||
|
||
@lego_part.command('colors') | ||
@pass_state | ||
@object_print | ||
def lego_part_colors(state): | ||
return state.api.lego_parts_colors_list(part_num=state.part_num) | ||
|
||
|
||
@add_typed_subcommands(PartColorsElement) | ||
@lego_part.group('color') | ||
@pass_state | ||
@get_or_push | ||
@click.argument('color_id', type=int) | ||
def lego_part_color(state, color_id): | ||
return state.api.lego_parts_colors_read(color_id=color_id, part_num=state.part_num) | ||
|
||
|
||
@lego_part_color.command('sets') | ||
@pass_state | ||
@object_print | ||
def lego_part_color_sets(state): | ||
return state.api.lego_parts_colors_sets_list(color_id=state.color_id, part_num=state.part_num) | ||
|
||
|
||
@lego.command('colors') | ||
@pass_state | ||
@object_print | ||
def lego_colors(state): | ||
return state.api.lego_colors_list() | ||
|
||
|
||
@add_typed_subcommands(Color) | ||
@lego.group('color') | ||
@pass_state | ||
@get_or_push | ||
@click.argument('color_id', type=int) | ||
def lego_color(state, color_id): | ||
return state.api.lego_colors_read(id=color_id) | ||
|
||
|
||
@add_typed_subcommands(Element) | ||
@lego.group('element') | ||
@pass_state | ||
@get_or_push | ||
@click.argument('element_id') | ||
def lego_element(state, element_id): | ||
return state.api.lego_elements_read(element_id=element_id) | ||
|
||
|
||
@add_typed_subcommands(Moc) | ||
@lego.group('moc') | ||
@pass_state | ||
@get_or_push | ||
@click.argument('set_num') | ||
def lego_moc(state, set_num): | ||
return state.api.lego_mocs_read(set_num=set_num) | ||
|
||
|
||
@lego_moc.command('parts') | ||
@pass_state | ||
@object_print | ||
def lego_moc_parts(state): | ||
return state.api.lego_mocs_parts_list(set_num=state.set_num) | ||
|
||
|
||
@lego.command('part_categories') | ||
@pass_state | ||
@object_print | ||
def lego_part_categories(state): | ||
return state.api.lego_part_categories_list() | ||
|
||
|
||
@add_typed_subcommands(PartCategory) | ||
@lego.group('part_category') | ||
@pass_state | ||
@get_or_push | ||
@click.argument('id', type=int) | ||
def lego_part_category(state, id): | ||
return state.api.lego_part_categories_read(id=id) | ||
|
||
|
||
@lego.command('sets') | ||
@pass_state | ||
def lego_sets(state): | ||
oprint(state.api.lego_sets_list()) | ||
|
||
|
||
@add_typed_subcommands(Set) | ||
@lego.group('set') | ||
@pass_state | ||
@get_or_push | ||
@click.argument('set_num') | ||
def lego_set(state, set_num): | ||
return state.api.lego_sets_read(set_num=set_num) | ||
|
||
|
||
@lego_set.command('parts') | ||
@pass_state | ||
@object_print | ||
def lego_set_parts(state): | ||
return state.api.lego_sets_parts_list(set_num=state.set_num) | ||
|
||
|
||
@lego_set.command('alternates') | ||
@pass_state | ||
@object_print | ||
def lego_set_alternates(state): | ||
return state.api.lego_sets_alternates_list(set_num=state.set_num) | ||
|
||
|
||
@lego_set.command('sets') | ||
@pass_state | ||
@object_print | ||
def lego_set_sets(state): | ||
return state.api.lego_sets_sets_list(set_num=state.set_num) | ||
|
||
|
||
@lego.command('themes') | ||
@pass_state | ||
@object_print | ||
def lego_themes(state): | ||
return state.api.lego_themes_list() | ||
|
||
|
||
@add_typed_subcommands(Theme) | ||
@lego.group('theme') | ||
@pass_state | ||
@get_or_push | ||
@click.argument('theme_id') | ||
def lego_theme(state, theme_id): | ||
return state.api.lego_themes_read(id=theme_id) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
"""Console script for pyrebrickable.""" | ||
from __future__ import print_function | ||
import json | ||
from collections import namedtuple | ||
from getpass import getpass | ||
|
||
import click | ||
import yaml | ||
from click import get_current_context | ||
|
||
from rebrickable_api import ApiClient, Configuration | ||
from rebrickable_cli.cli.common import State | ||
|
||
from rebrickable_cli.cli.lego import lego | ||
from rebrickable_cli.cli.user import user | ||
from rebrickable_cli.cli.users import users | ||
|
||
try: | ||
from enum import Enum, EnumMeta # pragma: no cover | ||
except ImportError: # pragma: no cover | ||
from enum34 import Enum, EnumMeta # pragma: no cover | ||
|
||
from rebrickable_cli.utils import get_data, DATA_PATH, EnumType, write_data | ||
|
||
|
||
class OutputFormat(Enum): | ||
json = 0 # json.dumps | ||
yaml = 1 # yaml.dump | ||
py = 2 # print | ||
|
||
|
||
OutputFormatter = namedtuple('OutputFormatter', ['output']) | ||
|
||
|
||
def get_api_client(): | ||
configuration = Configuration() | ||
data = get_data() | ||
api_key = data['api_key'] | ||
configuration.api_key['Authorization'] = api_key | ||
configuration.api_key_prefix['Authorization'] = 'key' | ||
return ApiClient(configuration) | ||
|
||
|
||
@click.group(help="Rebrickable CLI implemented in Python") | ||
@click.pass_context | ||
@click.option('--output', '-o', help='output printer (json, yaml, py --regular print Python function--)',type=EnumType(OutputFormat, casesensitive=False), default="py") | ||
def main(click_context, output): | ||
"""Console script for pyrebrickable.""" | ||
|
||
format = None | ||
if output == OutputFormat.json: | ||
format = OutputFormatter(output=lambda o: print(json.dumps(o.to_dict(), default=str))) | ||
elif output == OutputFormat.yaml: | ||
format = OutputFormatter(output=lambda o: print(yaml.dump(o.to_dict(), default_flow_style=False))) | ||
elif output == OutputFormat.py: | ||
format = OutputFormatter(output=lambda o: print(o)) | ||
|
||
try: | ||
click_context.obj = State(format=format, client=get_api_client()) | ||
except (IOError, KeyError, ValueError): | ||
if click_context.invoked_subcommand != 'register': | ||
print('please register your API key using: \nrebrickable register') | ||
raise click.Abort() | ||
|
||
|
||
def get_api_key(): | ||
return getpass(prompt='Please enter your API key:') | ||
|
||
|
||
@main.command(help='registers an API key with the CLI') | ||
def register(): | ||
key = get_api_key() | ||
data = get_data() | ||
data['api_key'] = key | ||
write_data(data) | ||
print('OK, registered API key in %s' % DATA_PATH) | ||
|
||
|
||
main.add_command(lego) | ||
main.add_command(users) | ||
main.add_command(user) | ||
|
||
if __name__ == "__main__": | ||
main() |
Oops, something went wrong.