diff options
-rw-r--r-- | docs/cli.rst | 23 | ||||
-rw-r--r-- | gitlab/cli.py | 20 | ||||
-rw-r--r-- | gitlab/v4/cli.py | 59 |
3 files changed, 76 insertions, 26 deletions
diff --git a/docs/cli.rst b/docs/cli.rst index 8d0550b..349ee02 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -80,10 +80,11 @@ section. * - ``url`` - URL for the GitLab server * - ``private_token`` - - Your user token. Login/password is not supported. - Refer `the official documentation`__ to learn how to obtain a token. + - Your user token. Login/password is not supported. Refer to `the official + documentation`__ to learn how to obtain a token. * - ``api_version`` - - API version to use (``3`` or ``4``), defaults to ``3`` + - GitLab API version to use (``3`` or ``4``). Defaults to ``3`` for now, + but will switch to ``4`` eventually. * - ``http_username`` - Username for optional HTTP authentication * - ``http_password`` @@ -126,7 +127,8 @@ Use the following optional arguments to change the behavior of ``gitlab``. These options must be defined before the mandatory arguments. ``--verbose``, ``-v`` - Outputs detail about retrieved objects. + Outputs detail about retrieved objects. Available for legacy (default) + output only. ``--config-file``, ``-c`` Path to a configuration file. @@ -134,11 +136,18 @@ These options must be defined before the mandatory arguments. ``--gitlab``, ``-g`` ID of a GitLab server defined in the configuration file. +``--output``, ``-o`` + Output format. Defaults to a custom format. Can also be ``yaml`` or ``json``. + +``--fields``, ``-f`` + Comma-separated list of fields to display (``yaml`` and ``json`` formats + only). If not used, all the object fields are displayed. + Example: .. code-block:: console - $ gitlab -v -g elsewhere -c /tmp/gl.cfg project list + $ gitlab -o yaml -f id,permissions -g elsewhere -c /tmp/gl.cfg project list Examples @@ -168,12 +177,11 @@ Get a specific project (id 2): $ gitlab project get --id 2 -Get a specific user by id or by username: +Get a specific user by id: .. code-block:: console $ gitlab user get --id 3 - $ gitlab user get-by-username --query jdoe Get a list of snippets for this project: @@ -200,7 +208,6 @@ Create a snippet: $ gitlab project-snippet create --project-id 2 Impossible to create object (Missing attribute(s): title, file-name, code) - $ # oops, let's add the attributes: $ gitlab project-snippet create --project-id 2 --title "the title" \ --file-name "the name" --code "the code" diff --git a/gitlab/cli.py b/gitlab/cli.py index d803eb5..f6b357b 100644 --- a/gitlab/cli.py +++ b/gitlab/cli.py @@ -51,7 +51,6 @@ def register_custom_action(cls_name, mandatory=tuple(), optional=tuple()): custom_actions[final_name] = {} action = f.__name__ - custom_actions[final_name][action] = (mandatory, optional, in_obj) return wrapped_f @@ -79,7 +78,7 @@ def _get_base_parser(): parser.add_argument("--version", help="Display the version.", action="store_true") parser.add_argument("-v", "--verbose", "--fancy", - help="Verbose mode", + help="Verbose mode (legacy format only)", action="store_true") parser.add_argument("-d", "--debug", help="Debug mode (display HTTP requests", @@ -92,6 +91,15 @@ def _get_base_parser(): "be used. If not defined, the default selection " "will be used."), required=False) + parser.add_argument("-o", "--output", + help=("Output format (v4 only): json|legacy|yaml"), + required=False, + choices=['json', 'legacy', 'yaml'], + default="legacy") + parser.add_argument("-f", "--fields", + help=("Fields to display in the output (comma " + "separated). Not used with legacy output"), + required=False) return parser @@ -117,6 +125,10 @@ def main(): config_files = args.config_file gitlab_id = args.gitlab verbose = args.verbose + output = args.output + fields = [] + if args.fields: + fields = [x.strip() for x in args.fields.split(',')] debug = args.debug action = args.action what = args.what @@ -124,7 +136,7 @@ def main(): args = args.__dict__ # Remove CLI behavior-related args for item in ('gitlab', 'config_file', 'verbose', 'debug', 'what', 'action', - 'version'): + 'version', 'output'): args.pop(item) args = {k: v for k, v in args.items() if v is not None} @@ -137,6 +149,6 @@ def main(): if debug: gl.enable_debug() - cli_module.run(gl, what, action, args, verbose) + cli_module.run(gl, what, action, args, verbose, output, fields) sys.exit(0) diff --git a/gitlab/v4/cli.py b/gitlab/v4/cli.py index 821a27d..ca5c6b1 100644 --- a/gitlab/v4/cli.py +++ b/gitlab/v4/cli.py @@ -245,30 +245,47 @@ def extend_parser(parser): return parser +class JSONPrinter(object): + def display(self, d, **kwargs): + import json # noqa + + print(json.dumps(d)) + + +class YAMLPrinter(object): + def display(self, d, **kwargs): + import yaml # noqa + + print(yaml.safe_dump(d, default_flow_style=False)) + + class LegacyPrinter(object): - def display(self, obj, verbose=False, padding=0): - def display_dict(d): + def display(self, d, **kwargs): + verbose = kwargs.get('verbose', False) + padding = kwargs.get('padding', 0) + obj = kwargs.get('obj') + + def display_dict(d, padding): for k in sorted(d.keys()): v = d[k] if isinstance(v, dict): print('%s%s:' % (' ' * padding, k)) new_padding = padding + 2 - self.display(v, True, new_padding) + self.display(v, verbose=True, padding=new_padding, obj=v) continue print('%s%s: %s' % (' ' * padding, k, v)) if verbose: if isinstance(obj, dict): - display_dict(obj) + display_dict(obj, padding) return # not a dict, we assume it's a RESTObject - id = getattr(obj, obj._id_attr) + id = getattr(obj, obj._id_attr, None) print('%s: %s' % (obj._id_attr, id)) attrs = obj.attributes attrs.pop(obj._id_attr) - display_dict(attrs) - print('') + display_dict(attrs, padding) else: id = getattr(obj, obj._id_attr) @@ -278,19 +295,33 @@ class LegacyPrinter(object): print('%s: %s' % (obj._short_print_attr, value)) -def run(gl, what, action, args, verbose): +PRINTERS = { + 'json': JSONPrinter, + 'legacy': LegacyPrinter, + 'yaml': YAMLPrinter, +} + + +def run(gl, what, action, args, verbose, output, fields): g_cli = GitlabCLI(gl, what, action, args) ret_val = g_cli() - printer = LegacyPrinter() + printer = PRINTERS[output]() + + def get_dict(obj): + if fields: + return {k: v for k, v in obj.attributes.items() + if k in fields} + return obj.attributes if isinstance(ret_val, list): - for o in ret_val: - if isinstance(o, gitlab.base.RESTObject): - printer.display(o, verbose) + for obj in ret_val: + if isinstance(obj, gitlab.base.RESTObject): + printer.display(get_dict(obj), verbose=verbose, obj=obj) else: - print(o) + print(obj) + print('') elif isinstance(ret_val, gitlab.base.RESTObject): - printer.display(ret_val, verbose) + printer.display(get_dict(ret_val), verbose=verbose, obj=ret_val) elif isinstance(ret_val, six.string_types): print(ret_val) |