{"action":"created","comment":{"url":"https://api.github.com/repos/hilbert/hilbert-cli/pulls/comments/89111332","pull_request_review_id":9659681,"id":89111332,"diff_hunk":"@@ -0,0 +1,589 @@\n+#!/usr/bin/env python2\n+\n+# -*- coding: utf-8 -*-\n+# encoding: utf-8\n+# coding: utf-8\n+\n+from __future__ import absolute_import, print_function, unicode_literals\n+\n+assert __name__ == \"__main__\"\n+\n+import sys\n+from os import path\n+DIR=path.dirname(path.dirname(path.abspath(__file__)))\n+sys.path.append(path.join(DIR, 'config'))\n+\n+from helpers import *\n+from hilbert_cli_config import *\n+\n+#from config.hilbert_cli_config import *\n+#from config.helpers import *\n+\n+from arghandler import *               # NOQA \n+import argparse                        # NOQA\n+\n+import logging\n+log = logging.getLogger(__name__)  #\n+\n+# level=logging.INFO!!! , datefmt='%Y.%m.%d %I:%M:%S %p'\n+logging.basicConfig(format='%(levelname)s [%(filename)s:%(lineno)d]: %(message)s', level=logging.DEBUG)\n+# %(name)s            Name of the logger (logging channel)\n+# %(levelno)s         Numeric logging level for the message (DEBUG, INFO, WARNING, ERROR, CRITICAL)\n+# %(levelname)s       Text logging level for the message (\"DEBUG\", \"INFO\", \"WARNING\", \"ERROR\", \"CRITICAL\")\n+# %(pathname)s        Full pathname of the source file where the logging call was issued (if available)\n+# %(filename)s        Filename portion of pathname\n+# %(module)s          Module (name portion of filename)\n+# %(lineno)d          Source line number where the logging call was issued (if available)\n+# %(funcName)s        Function name\n+# %(created)f         Time when the LogRecord was created (time.time() return value)\n+# %(asctime)s         Textual time when the LogRecord was created\n+# %(msecs)d           Millisecond portion of the creation time\n+# %(relativeCreated)d Time in milliseconds when the LogRecord was created, relative to the time the logging module was loaded\n+#                     (typically at application startup time)\n+# %(thread)d          Thread ID (if available)\n+# %(threadName)s      Thread name (if available)\n+# %(process)d         Process ID (if available)\n+# %(message)s         The result of record.getMessage(), computed just as the record is emitted\n+import traceback\n+def main_exception_handler(type, value, tb):\n+    log.exception(\"Uncaught exception! Type: {0}, Value: {1}, TB: {2}\".format(type, value, traceback.format_tb(tb)))\n+\n+# sys.excepthook = main_exception_handler # Install exception handler\n+\n+def _version():\n+    import platform\n+    import dill\n+    import ruamel.yaml as yaml\n+    import semantic_version\n+    log.info(\"Python           version: {}\".format(platform.python_version()))\n+    log.info(\"ruamel.yaml      version: {}\".format(yaml.__version__))\n+    log.info(\"dill             version: {}\".format(dill.__version__))\n+    log.info(\"semantic_version version: {}\".format(semantic_version.__version__))\n+#    log.info(\"Hilbert.Config   version: {}\".format(config.__version__))  # TODO!\n+\n+    # arghandler version? dill version? etc?\n+\n+\n+def _load(f):\n+    return load_yaml_file(f)  # TODO: check that this is a dictionary!\n+\n+\n+@subcmd('version', help='Display version info')\n+def cmd_version(parser, context, args):\n+    log.debug(\"Running '{}'\".format('cfg_version'))\n+    _version()\n+    log.debug(\"Done\")\n+    exit(0)\n+\n+\n+@subcmd('cfg_verify', help='Check correctness of a given general Hilbert configuration (YAML) file as far as possible...')\n+def cmd_verify(parser, context, args):\n+    global PEDANTIC\n+    global INPUT_DIRNAME\n+\n+    log.debug(\"Running '{}'\".format('cfg_verify'))\n+\n+    ctx = vars(context)\n+    pedantic_handler(parser, ctx, args)\n+\n+    if 'inputdump' in ctx:\n+        df = ctx['inputdump']\n+        if df is not None:\n+            log.error(\"Sorry: cannot verify a dump file.\")\n+            exit(1)\n+\n+    args = parser.parse_args(args)\n+    cfg = input_handler(parser, ctx, args)\n+\n+    log.debug(\"Done\")\n+    exit(0)\n+\n+def pedantic_handler(parser, ctx, args):\n+    global PEDANTIC\n+\n+    if 'pedantic' in ctx:\n+        PEDANTIC = ctx['pedantic']\n+\n+    if PEDANTIC:\n+        log.debug(\"PEDANTIC mode is ON!\")\n+\n+def input_handler(parser, ctx, args):\n+    global INPUT_DIRNAME\n+\n+    fn = None\n+    df = None\n+\n+    if 'inputfile' in ctx:\n+        fn = ctx['inputfile']\n+        log.debug(\"Input YAML file specified: {}\".format(fn))\n+\n+    if 'inputdump' in ctx:\n+        df = ctx['inputdump']\n+        log.debug(\"Input dump file specified: {}\".format(df))\n+\n+    if (fn is None) and (df is None):\n+        fn = 'Hilbert.yml'\n+        log.warning(\"Missing input file specification: using default '{}'!\".format(fn))\n+\n+    if (fn is not None) and (df is not None):\n+        log.error(\"Input file specification clashes with the input dump specification: specify a single input source!\")\n+        exit(1)\n+\n+    if fn is not None:\n+        if not URI(None).validate(fn):\n+            log.error(\"Wrong file specification: '{}'\".format(fn))\n+            exit(1)\n+        log.info(\"Input file: '{}'\".format(fn))\n+\n+    if df is not None:\n+        if not URI(None).validate(fn):\n+            log.error(\"Wrong dump file specification: '{}'\".format(df))\n+            exit(1)\n+        log.info(\"Input dump file: '{}'\".format(df))\n+\n+    if fn is not None:\n+        INPUT_DIRNAME = os.path.abspath(os.path.dirname(fn))\n+    else:\n+        assert df is not None\n+        INPUT_DIRNAME = os.path.abspath(os.path.dirname(df))\n+\n+    cfg = None\n+\n+    if fn is not None:\n+        log.info(\"Loading '{}'...\".format(fn))\n+        try:\n+            yml = _load(fn)\n+            log.info(\"Input file is a valid YAML!\")\n+\n+            os.chdir(INPUT_DIRNAME)\n+            log.info(\"Data Validation/Parsing: \")\n+\n+            cfg = parse_hilbert(yml)\n+\n+        except:\n+            log.exception(\"ERROR: wrong input file: '{}'!\".format(fn))\n+            exit(1)\n+    else:\n+        log.info(\"Loading dump '{}'...\".format(df))\n+        try:\n+            cfg = pickle_load(df)\n+            log.info(\"Input dump file is valid!\")\n+        except:\n+            log.exception(\"Wrong input dump file: '{}'!\".format(df))\n+            exit(1)\n+\n+    if cfg is None:\n+        log.error(\"Could not get the configuration!\")\n+        exit(1)\n+\n+    assert isinstance(cfg, Hilbert)\n+    log.info(\"Configuration is OK!\")\n+\n+    return cfg\n+\n+\n+def output_handler(parser, ctx, args):\n+    args = vars(args)\n+\n+    od = None\n+    if 'outputdump' in args:\n+        od = args['outputdump']\n+        log.debug(\"Specified output dump file: {}\".format(od))\n+        assert od is not None\n+\n+        if URI(None).validate(od):\n+            if not PEDANTIC:\n+                log.warning(\"Output dump file: '{}' already exists! Will be overwritten!\".format(od))\n+            else:\n+                log.warning(\"Output dump file: '{}' already exists! Cannot overwrite it in PEDANTIC mode!\".format(od))\n+                od = None\n+    return od\n+\n+def cmd_list(parser, context, args, obj):\n+    ctx = vars(context)\n+    pedantic_handler(parser, ctx, args)\n+    cfg = input_handler(parser, ctx, args)\n+    return cfg.query(obj)\n+\n+\n+@subcmd('cfg_query', help='Load Configuration and query some part of it')\n+def cmd_query(parser, context, args):\n+    log.debug(\"Running '{}'\" . format('cfg_query'))\n+\n+    parser.add_argument('-o', '--object', required=False, default='all',\n+            help=\"specify the object in the config (default: 'all')\")\n+    parser.add_argument('-od', '--outputdump', default=argparse.SUPPRESS,\n+            help=\"specify output dump file\")\n+\n+    args = parser.parse_args(args)\n+\n+    _args = vars(args)\n+\n+    obj = 'all'\n+    if 'object' in _args:\n+        obj = _args['object']\n+\n+    try:\n+        log.info(\"Querring object: '{}'... \" . format(obj))\n+        obj = cmd_list(parser, context, args, obj)\n+    except:\n+        log.exception(\"Sorry cannot query '{}' yet!\" . format(obj))\n+        exit(1)\n+\n+    assert obj is not None\n+\n+    if isinstance(obj, Base):\n+        print(yaml_dump(obj.data_dump()))\n+    else:\n+        print(yaml_dump(obj))\n+\n+    od  = output_handler(parser, vars(context), args)\n+\n+    if od is not None:\n+        log.info(\"Writing the configuration into '{}'...\".format(od))\n+        pickle_dump(od, obj)\n+\n+    log.debug(\"Done\")\n+    exit(0)\n+\n+@subcmd('list_applications', help='Load Configuration and list its applications')\n+def cmd_list_applications(parser, context, args):\n+    log.debug(\"Running '{}'\" . format('list_applications'))\n+    log.debug(\"Listing all Application ID...\")\n+\n+    args = parser.parse_args(args)\n+\n+    obj = None\n+    try:\n+        obj = cmd_list(parser, context, args, 'Applications/keys')\n+    except:\n+        log.exception(\"Sorry could not get the list of '{}' from the input file!\".format('applications'))\n+        exit(1)\n+\n+    assert obj is not None\n+\n+    if isinstance(obj, Base):\n+        print(yaml_dump(obj.data_dump()))\n+    else:\n+        print(yaml_dump(obj))\n+\n+    log.debug(\"Done\")\n+    exit(0)\n+\n+@subcmd('list_stations', help='Load Configuration and list its stations')\n+def cmd_list_stations(parser, context, args):\n+    log.debug(\"Running '{}'\" . format('list_stations'))\n+    log.debug(\"Listing all Station ID...\")\n+\n+    args = parser.parse_args(args)\n+\n+    obj = None\n+    try:\n+        obj = cmd_list(parser, context, args, 'Stations/keys')\n+    except:\n+        log.exception(\"Sorry could not get the list of '{}' from the input file!\".format('stations'))\n+        exit(1)\n+\n+    assert obj is not None\n+\n+    if isinstance(obj, Base):\n+        print(yaml_dump(obj.data_dump()))\n+    else:\n+        print(yaml_dump(obj))\n+\n+    log.debug(\"Done\")\n+    exit(0)\n+\n+\n+@subcmd('list_profiles', help='Load Configuration and list its profiles')\n+def cmd_list_profiles(parser, context, args):\n+    log.debug(\"Running '{}'\" . format('list_profiles'))\n+    log.debug(\"Listing all Profile ID...\")\n+\n+    args = parser.parse_args(args)\n+\n+    obj = None\n+    try:\n+        obj = cmd_list(parser, context, args, 'Profiles/keys')\n+    except:\n+        log.exception(\"Sorry could not get the list of '{}' from the input file!\".format('profiles'))\n+        exit(1)\n+\n+    assert obj is not None\n+\n+    if isinstance(obj, Base):\n+        print(yaml_dump(obj.data_dump()))\n+    else:\n+        print(yaml_dump(obj))\n+\n+    log.debug(\"Done\")\n+    exit(0)\n+\n+\n+@subcmd('list_groups', help='Load Configuration and list its named groups')\n+def cmd_list_groups(parser, context, args):\n+    log.debug(\"Running '{}'\" . format('list_groups'))\n+    log.debug(\"Listing all Group ID...\")\n+\n+    args = parser.parse_args(args)\n+\n+    obj = None\n+    try:\n+        obj = cmd_list(parser, context, args, 'Groups/keys')\n+    except:\n+        log.exception(\"Sorry could not get the list of '{}' from the input file!\".format('groups'))\n+        exit(1)\n+\n+    assert obj is not None\n+\n+    if isinstance(obj, Base):\n+        print(yaml_dump(obj.data_dump()))\n+    else:\n+        print(yaml_dump(obj))\n+\n+    log.debug(\"Done\")\n+    exit(0)\n+\n+\n+@subcmd('list_services', help='Load Configuration and list its services')\n+def cmd_list_services(parser, context, args):\n+    log.debug(\"Running '{}'\" . format('list_services'))\n+    log.debug(\"Listing all Service ID...\")\n+\n+    args = parser.parse_args(args)\n+\n+    obj = None\n+    try:\n+        obj = cmd_list(parser, context, args, 'Services/keys')\n+    except:\n+        log.exception(\"Sorry could not get the list of '{}' from the input file!\".format('services'))\n+        exit(1)\n+\n+    assert obj is not None\n+\n+    if isinstance(obj, Base):\n+        print(yaml_dump(obj.data_dump()))\n+    else:\n+        print(yaml_dump(obj))\n+\n+    log.debug(\"Done\")\n+    exit(0)\n+\n+\n+def cmd_action(parser, context, args, stationId, action, action_args):\n+    stations = None\n+    try:\n+        stations = cmd_list(parser, context, args, 'Stations/all')\n+    except:\n+        log.exception(\"Sorry could not get the list of '{}' from the input file!\".format('stations'))\n+        exit(1)\n+\n+    assert stations is not None\n+    assert stationId in stations.get_data()\n+\n+    station = stations.get_data()[stationId]\n+\n+    assert station is not None\n+\n+    if isinstance(station, Base):\n+        print(yaml_dump(station.data_dump()))\n+    else:\n+        print(yaml_dump(station))\n+\n+    log.debug(\"Trying to run '{0} {1}' on remote station '{2}'\" . format(action, action_args, stationId))\n+\n+    try:\n+        station.run_action(action, action_args)\n+    except:\n+        log.exception(\"Could not run '{0} {1}' on remote station '{2}'\" . format(action, action_args, stationId))\n+        exit(1)\n+\n+\n+@subcmd('poweron', help='Load Configuration and poweron one of the stations')\n+def cmd_poweron(parser, context, args):\n+    log.debug(\"Running '{}'\" . format('cmd_poweron'))\n+\n+    parser.add_argument('-s', '--station', required=True, help=\"specify the station\")\n+    parser.add_argument('-g', '--action_args', required=False, help=\"specify the action arguments\")\n+\n+    args = parser.parse_args(args)\n+    _args = vars(args)\n+    assert 'station' in _args\n+    stationId = _args['station']\n+\n+    action_args = None\n+    if 'action_args' in _args:\n+        action_args = _args['action_args']\n+\n+    cmd_action(parser, context, args, stationId, 'poweron', action_args)\n+\n+    log.debug(\"Done\")\n+    exit(0)\n+\n+\n+@subcmd('shutdown', help='Load Configuration and shutdown one of the stations')\n+def cmd_shutdown(parser, context, args):\n+    log.debug(\"Running '{}'\" . format('cmd_shutdown'))\n+\n+    parser.add_argument('-s', '--station', required=True, help=\"specify the station\")\n+    parser.add_argument('-g', '--action_args', required=False, help=\"specify the action arguments\")\n+\n+    args = parser.parse_args(args)\n+    _args = vars(args)\n+    assert 'station' in _args\n+    stationId = _args['station']\n+\n+    action_args = None\n+    if 'action_args' in _args:\n+        action_args = _args['action_args']\n+\n+    cmd_action(parser, context, args, stationId, 'shutdown', action_args)\n+\n+    log.debug(\"Done\")\n+    exit(0)\n+\n+@subcmd('deploy', help='Load Configuration and deploy its part to one of the stations')\n+def cmd_deploy(parser, context, args):\n+    log.debug(\"Running '{}'\" . format('cmd_deploy'))\n+\n+    parser.add_argument('-s', '--station', required=True, help=\"specify the station\")\n+    parser.add_argument('-g', '--action_args', required=False, help=\"specify the action arguments\")\n+\n+    args = parser.parse_args(args)\n+    _args = vars(args)\n+    assert 'station' in _args\n+    stationId = _args['station']\n+\n+    action_args = None\n+    if 'action_args' in _args:\n+        action_args = _args['action_args']\n+\n+    cmd_action(parser, context, args, stationId, 'deploy', action_args)\n+\n+    log.debug(\"Done\")\n+    exit(0)\n+\n+@subcmd('start', help='Load Configuration and start a service/application on one of the stations')\n+def cmd_start(parser, context, args):\n+    log.debug(\"Running '{}'\" . format('cmd_deploy'))\n+\n+    parser.add_argument('-s', '--station', required=True, help=\"specify the station\")\n+    parser.add_argument('-g', '--action_args', required=False, help=\"specify the action arguments (ApplicationID/ServiceID)\")\n+\n+    args = parser.parse_args(args)\n+    _args = vars(args)\n+    assert 'station' in _args\n+    stationId = _args['station']\n+\n+    action_args = None\n+    if 'action_args' in _args:\n+        action_args = _args['action_args']\n+\n+    cmd_action(parser, context, args, stationId, 'start', action_args)\n+\n+    log.debug(\"Done\")\n+    exit(0)\n+\n+\n+@subcmd('finish', help='Load Configuration and finish a service/application on one of the stations')\n+def cmd_finish(parser, context, args):\n+    log.debug(\"Running '{}'\" . format('cmd_finish'))\n+\n+    parser.add_argument('-s', '--station', required=True, help=\"specify the station\")","path":"tools/hilbert.py","position":null,"original_position":492,"commit_id":"c5409aaf080b331ff6126ebb1c4c155e37496a7d","original_commit_id":"44bbadcdd4d9eac45a13ce9c642694a36f31e1ff","user":{"login":"malex984","id":391009,"avatar_url":"https://avatars.githubusercontent.com/u/391009?v=3","gravatar_id":"","url":"https://api.github.com/users/malex984","html_url":"https://github.com/malex984","followers_url":"https://api.github.com/users/malex984/followers","following_url":"https://api.github.com/users/malex984/following{/other_user}","gists_url":"https://api.github.com/users/malex984/gists{/gist_id}","starred_url":"https://api.github.com/users/malex984/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/malex984/subscriptions","organizations_url":"https://api.github.com/users/malex984/orgs","repos_url":"https://api.github.com/users/malex984/repos","events_url":"https://api.github.com/users/malex984/events{/privacy}","received_events_url":"https://api.github.com/users/malex984/received_events","type":"User","site_admin":false},"body":"later","created_at":"2016-11-22T13:09:11Z","updated_at":"2016-11-22T13:09:11Z","html_url":"https://github.com/hilbert/hilbert-cli/pull/34#discussion_r89111332","pull_request_url":"https://api.github.com/repos/hilbert/hilbert-cli/pulls/34","_links":{"self":{"href":"https://api.github.com/repos/hilbert/hilbert-cli/pulls/comments/89111332"},"html":{"href":"https://github.com/hilbert/hilbert-cli/pull/34#discussion_r89111332"},"pull_request":{"href":"https://api.github.com/repos/hilbert/hilbert-cli/pulls/34"}}},"pull_request":{"url":"https://api.github.com/repos/hilbert/hilbert-cli/pulls/34","id":92949492,"html_url":"https://github.com/hilbert/hilbert-cli/pull/34","diff_url":"https://github.com/hilbert/hilbert-cli/pull/34.diff","patch_url":"https://github.com/hilbert/hilbert-cli/pull/34.patch","issue_url":"https://api.github.com/repos/hilbert/hilbert-cli/issues/34","number":34,"state":"open","locked":false,"title":"Configuration validator","user":{"login":"malex984","id":391009,"avatar_url":"https://avatars.githubusercontent.com/u/391009?v=3","gravatar_id":"","url":"https://api.github.com/users/malex984","html_url":"https://github.com/malex984","followers_url":"https://api.github.com/users/malex984/followers","following_url":"https://api.github.com/users/malex984/following{/other_user}","gists_url":"https://api.github.com/users/malex984/gists{/gist_id}","starred_url":"https://api.github.com/users/malex984/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/malex984/subscriptions","organizations_url":"https://api.github.com/users/malex984/orgs","repos_url":"https://api.github.com/users/malex984/repos","events_url":"https://api.github.com/users/malex984/events{/privacy}","received_events_url":"https://api.github.com/users/malex984/received_events","type":"User","site_admin":false},"body":"#Let us consider this PR as a super-issue for the implementation of the Configuration Design: `Hilbert-CLI-Config`.\r\n\r\nNote: **NOT** to be merged yet!\r\n\r\nSub parts:\r\n\r\n- [ ] super-issue on \"Configuration Design\" (https://github.com/hilbert/hilbert-cli/issues/13)\r\n- [ ] Configuration Validator: modularity (#35)\r\n- [ ] Configuration Validator:  validation of unknown fields (#36)\r\n- [ ] Configuration Validator: complex general validation (#37)\r\n- [ ] add documentation generation (?)\r\n- [ ] add automated testing (e.g. `tox` or `unittest`) with support by PyCharm IDE (?) \r\n- [ ] add Makefile to support documentation generation and automated testing (?)\r\n- [ ] debug output  (?)\r\n- [ ] design CLI (?)","created_at":"2016-11-09T11:48:57Z","updated_at":"2016-11-22T13:09:11Z","closed_at":null,"merged_at":null,"merge_commit_sha":"4c97fd831d4e6bc061658f1f47d7f5f52dc68e95","assignee":null,"assignees":[],"milestone":{"url":"https://api.github.com/repos/hilbert/hilbert-cli/milestones/1","html_url":"https://github.com/hilbert/hilbert-cli/milestones/Configuration%20design","labels_url":"https://api.github.com/repos/hilbert/hilbert-cli/milestones/1/labels","id":2082308,"number":1,"title":"Configuration design","description":"Hilbert needs a static configuration file (YAML) that can be parsed without relying on side effects of the environment it lives in.","creator":{"login":"elondaits","id":6472073,"avatar_url":"https://avatars.githubusercontent.com/u/6472073?v=3","gravatar_id":"","url":"https://api.github.com/users/elondaits","html_url":"https://github.com/elondaits","followers_url":"https://api.github.com/users/elondaits/followers","following_url":"https://api.github.com/users/elondaits/following{/other_user}","gists_url":"https://api.github.com/users/elondaits/gists{/gist_id}","starred_url":"https://api.github.com/users/elondaits/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/elondaits/subscriptions","organizations_url":"https://api.github.com/users/elondaits/orgs","repos_url":"https://api.github.com/users/elondaits/repos","events_url":"https://api.github.com/users/elondaits/events{/privacy}","received_events_url":"https://api.github.com/users/elondaits/received_events","type":"User","site_admin":false},"open_issues":8,"closed_issues":9,"state":"open","created_at":"2016-10-20T11:39:41Z","updated_at":"2016-11-14T14:58:55Z","due_on":"2016-11-08T00:00:00Z","closed_at":null},"commits_url":"https://api.github.com/repos/hilbert/hilbert-cli/pulls/34/commits","review_comments_url":"https://api.github.com/repos/hilbert/hilbert-cli/pulls/34/comments","review_comment_url":"https://api.github.com/repos/hilbert/hilbert-cli/pulls/comments{/number}","comments_url":"https://api.github.com/repos/hilbert/hilbert-cli/issues/34/comments","statuses_url":"https://api.github.com/repos/hilbert/hilbert-cli/statuses/c5409aaf080b331ff6126ebb1c4c155e37496a7d","head":{"label":"hilbert:feature/config_validate","ref":"feature/config_validate","sha":"c5409aaf080b331ff6126ebb1c4c155e37496a7d","user":{"login":"hilbert","id":22076995,"avatar_url":"https://avatars.githubusercontent.com/u/22076995?v=3","gravatar_id":"","url":"https://api.github.com/users/hilbert","html_url":"https://github.com/hilbert","followers_url":"https://api.github.com/users/hilbert/followers","following_url":"https://api.github.com/users/hilbert/following{/other_user}","gists_url":"https://api.github.com/users/hilbert/gists{/gist_id}","starred_url":"https://api.github.com/users/hilbert/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hilbert/subscriptions","organizations_url":"https://api.github.com/users/hilbert/orgs","repos_url":"https://api.github.com/users/hilbert/repos","events_url":"https://api.github.com/users/hilbert/events{/privacy}","received_events_url":"https://api.github.com/users/hilbert/received_events","type":"Organization","site_admin":false},"repo":{"id":69197179,"name":"hilbert-cli","full_name":"hilbert/hilbert-cli","owner":{"login":"hilbert","id":22076995,"avatar_url":"https://avatars.githubusercontent.com/u/22076995?v=3","gravatar_id":"","url":"https://api.github.com/users/hilbert","html_url":"https://github.com/hilbert","followers_url":"https://api.github.com/users/hilbert/followers","following_url":"https://api.github.com/users/hilbert/following{/other_user}","gists_url":"https://api.github.com/users/hilbert/gists{/gist_id}","starred_url":"https://api.github.com/users/hilbert/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hilbert/subscriptions","organizations_url":"https://api.github.com/users/hilbert/orgs","repos_url":"https://api.github.com/users/hilbert/repos","events_url":"https://api.github.com/users/hilbert/events{/privacy}","received_events_url":"https://api.github.com/users/hilbert/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/hilbert/hilbert-cli","description":"Backend management tools: CLI","fork":false,"url":"https://api.github.com/repos/hilbert/hilbert-cli","forks_url":"https://api.github.com/repos/hilbert/hilbert-cli/forks","keys_url":"https://api.github.com/repos/hilbert/hilbert-cli/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hilbert/hilbert-cli/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hilbert/hilbert-cli/teams","hooks_url":"https://api.github.com/repos/hilbert/hilbert-cli/hooks","issue_events_url":"https://api.github.com/repos/hilbert/hilbert-cli/issues/events{/number}","events_url":"https://api.github.com/repos/hilbert/hilbert-cli/events","assignees_url":"https://api.github.com/repos/hilbert/hilbert-cli/assignees{/user}","branches_url":"https://api.github.com/repos/hilbert/hilbert-cli/branches{/branch}","tags_url":"https://api.github.com/repos/hilbert/hilbert-cli/tags","blobs_url":"https://api.github.com/repos/hilbert/hilbert-cli/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hilbert/hilbert-cli/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hilbert/hilbert-cli/git/refs{/sha}","trees_url":"https://api.github.com/repos/hilbert/hilbert-cli/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hilbert/hilbert-cli/statuses/{sha}","languages_url":"https://api.github.com/repos/hilbert/hilbert-cli/languages","stargazers_url":"https://api.github.com/repos/hilbert/hilbert-cli/stargazers","contributors_url":"https://api.github.com/repos/hilbert/hilbert-cli/contributors","subscribers_url":"https://api.github.com/repos/hilbert/hilbert-cli/subscribers","subscription_url":"https://api.github.com/repos/hilbert/hilbert-cli/subscription","commits_url":"https://api.github.com/repos/hilbert/hilbert-cli/commits{/sha}","git_commits_url":"https://api.github.com/repos/hilbert/hilbert-cli/git/commits{/sha}","comments_url":"https://api.github.com/repos/hilbert/hilbert-cli/comments{/number}","issue_comment_url":"https://api.github.com/repos/hilbert/hilbert-cli/issues/comments{/number}","contents_url":"https://api.github.com/repos/hilbert/hilbert-cli/contents/{+path}","compare_url":"https://api.github.com/repos/hilbert/hilbert-cli/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hilbert/hilbert-cli/merges","archive_url":"https://api.github.com/repos/hilbert/hilbert-cli/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hilbert/hilbert-cli/downloads","issues_url":"https://api.github.com/repos/hilbert/hilbert-cli/issues{/number}","pulls_url":"https://api.github.com/repos/hilbert/hilbert-cli/pulls{/number}","milestones_url":"https://api.github.com/repos/hilbert/hilbert-cli/milestones{/number}","notifications_url":"https://api.github.com/repos/hilbert/hilbert-cli/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hilbert/hilbert-cli/labels{/name}","releases_url":"https://api.github.com/repos/hilbert/hilbert-cli/releases{/id}","deployments_url":"https://api.github.com/repos/hilbert/hilbert-cli/deployments","created_at":"2016-09-25T23:42:55Z","updated_at":"2016-10-26T18:30:58Z","pushed_at":"2016-11-22T13:09:02Z","git_url":"git://github.com/hilbert/hilbert-cli.git","ssh_url":"git@github.com:hilbert/hilbert-cli.git","clone_url":"https://github.com/hilbert/hilbert-cli.git","svn_url":"https://github.com/hilbert/hilbert-cli","homepage":null,"size":2507,"stargazers_count":0,"watchers_count":0,"language":"Shell","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":20,"forks":1,"open_issues":20,"watchers":0,"default_branch":"devel"}},"base":{"label":"hilbert:devel","ref":"devel","sha":"ae169e2def56eed88d4b082d76481b3c1d2be160","user":{"login":"hilbert","id":22076995,"avatar_url":"https://avatars.githubusercontent.com/u/22076995?v=3","gravatar_id":"","url":"https://api.github.com/users/hilbert","html_url":"https://github.com/hilbert","followers_url":"https://api.github.com/users/hilbert/followers","following_url":"https://api.github.com/users/hilbert/following{/other_user}","gists_url":"https://api.github.com/users/hilbert/gists{/gist_id}","starred_url":"https://api.github.com/users/hilbert/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hilbert/subscriptions","organizations_url":"https://api.github.com/users/hilbert/orgs","repos_url":"https://api.github.com/users/hilbert/repos","events_url":"https://api.github.com/users/hilbert/events{/privacy}","received_events_url":"https://api.github.com/users/hilbert/received_events","type":"Organization","site_admin":false},"repo":{"id":69197179,"name":"hilbert-cli","full_name":"hilbert/hilbert-cli","owner":{"login":"hilbert","id":22076995,"avatar_url":"https://avatars.githubusercontent.com/u/22076995?v=3","gravatar_id":"","url":"https://api.github.com/users/hilbert","html_url":"https://github.com/hilbert","followers_url":"https://api.github.com/users/hilbert/followers","following_url":"https://api.github.com/users/hilbert/following{/other_user}","gists_url":"https://api.github.com/users/hilbert/gists{/gist_id}","starred_url":"https://api.github.com/users/hilbert/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hilbert/subscriptions","organizations_url":"https://api.github.com/users/hilbert/orgs","repos_url":"https://api.github.com/users/hilbert/repos","events_url":"https://api.github.com/users/hilbert/events{/privacy}","received_events_url":"https://api.github.com/users/hilbert/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/hilbert/hilbert-cli","description":"Backend management tools: CLI","fork":false,"url":"https://api.github.com/repos/hilbert/hilbert-cli","forks_url":"https://api.github.com/repos/hilbert/hilbert-cli/forks","keys_url":"https://api.github.com/repos/hilbert/hilbert-cli/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hilbert/hilbert-cli/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hilbert/hilbert-cli/teams","hooks_url":"https://api.github.com/repos/hilbert/hilbert-cli/hooks","issue_events_url":"https://api.github.com/repos/hilbert/hilbert-cli/issues/events{/number}","events_url":"https://api.github.com/repos/hilbert/hilbert-cli/events","assignees_url":"https://api.github.com/repos/hilbert/hilbert-cli/assignees{/user}","branches_url":"https://api.github.com/repos/hilbert/hilbert-cli/branches{/branch}","tags_url":"https://api.github.com/repos/hilbert/hilbert-cli/tags","blobs_url":"https://api.github.com/repos/hilbert/hilbert-cli/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hilbert/hilbert-cli/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hilbert/hilbert-cli/git/refs{/sha}","trees_url":"https://api.github.com/repos/hilbert/hilbert-cli/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hilbert/hilbert-cli/statuses/{sha}","languages_url":"https://api.github.com/repos/hilbert/hilbert-cli/languages","stargazers_url":"https://api.github.com/repos/hilbert/hilbert-cli/stargazers","contributors_url":"https://api.github.com/repos/hilbert/hilbert-cli/contributors","subscribers_url":"https://api.github.com/repos/hilbert/hilbert-cli/subscribers","subscription_url":"https://api.github.com/repos/hilbert/hilbert-cli/subscription","commits_url":"https://api.github.com/repos/hilbert/hilbert-cli/commits{/sha}","git_commits_url":"https://api.github.com/repos/hilbert/hilbert-cli/git/commits{/sha}","comments_url":"https://api.github.com/repos/hilbert/hilbert-cli/comments{/number}","issue_comment_url":"https://api.github.com/repos/hilbert/hilbert-cli/issues/comments{/number}","contents_url":"https://api.github.com/repos/hilbert/hilbert-cli/contents/{+path}","compare_url":"https://api.github.com/repos/hilbert/hilbert-cli/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hilbert/hilbert-cli/merges","archive_url":"https://api.github.com/repos/hilbert/hilbert-cli/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hilbert/hilbert-cli/downloads","issues_url":"https://api.github.com/repos/hilbert/hilbert-cli/issues{/number}","pulls_url":"https://api.github.com/repos/hilbert/hilbert-cli/pulls{/number}","milestones_url":"https://api.github.com/repos/hilbert/hilbert-cli/milestones{/number}","notifications_url":"https://api.github.com/repos/hilbert/hilbert-cli/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hilbert/hilbert-cli/labels{/name}","releases_url":"https://api.github.com/repos/hilbert/hilbert-cli/releases{/id}","deployments_url":"https://api.github.com/repos/hilbert/hilbert-cli/deployments","created_at":"2016-09-25T23:42:55Z","updated_at":"2016-10-26T18:30:58Z","pushed_at":"2016-11-22T13:09:02Z","git_url":"git://github.com/hilbert/hilbert-cli.git","ssh_url":"git@github.com:hilbert/hilbert-cli.git","clone_url":"https://github.com/hilbert/hilbert-cli.git","svn_url":"https://github.com/hilbert/hilbert-cli","homepage":null,"size":2507,"stargazers_count":0,"watchers_count":0,"language":"Shell","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":20,"forks":1,"open_issues":20,"watchers":0,"default_branch":"devel"}},"_links":{"self":{"href":"https://api.github.com/repos/hilbert/hilbert-cli/pulls/34"},"html":{"href":"https://github.com/hilbert/hilbert-cli/pull/34"},"issue":{"href":"https://api.github.com/repos/hilbert/hilbert-cli/issues/34"},"comments":{"href":"https://api.github.com/repos/hilbert/hilbert-cli/issues/34/comments"},"review_comments":{"href":"https://api.github.com/repos/hilbert/hilbert-cli/pulls/34/comments"},"review_comment":{"href":"https://api.github.com/repos/hilbert/hilbert-cli/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/hilbert/hilbert-cli/pulls/34/commits"},"statuses":{"href":"https://api.github.com/repos/hilbert/hilbert-cli/statuses/c5409aaf080b331ff6126ebb1c4c155e37496a7d"}}}}
{"actor":{"display_login":"malex984"}}