コード例 #1
0
 def test_applicable_for_application_context_when_context_is_specified(
         self):
     command = CommandId('command',
                         'desc',
                         None, [],
                         application_contexts=ApplicationContext.STANDALONE)
     self.assertTrue(
         command.is_applicable_for_application(
             ApplicationContext.STANDALONE))
コード例 #2
0
 def test_not_applicable_for_application_context_that_is_not_specified(
         self):
     command = CommandId('command',
                         'desc',
                         None, [],
                         application_contexts=ApplicationContext.EXTENDABLE)
     self.assertFalse(
         command.is_applicable_for_application(
             ApplicationContext.STANDALONE))
コード例 #3
0
 def test_single_application_context_is_wrapped_in_tuple(self):
     self.assertEqual(
         CommandId('command',
                   'desc',
                   None, [],
                   application_contexts=ApplicationContext.EXTENDABLE).
         application_contexts, (ApplicationContext.EXTENDABLE, ))
コード例 #4
0
    def test_extension_extending_commandid_matches(self):
        command = CommandId('name', 'doc', lambda x: x, ())
        extension = self.mock_extension(extends=[command])

        self.em._all_extensions.append(extension)
        self.em.enable_all_extensions()

        self.assertEqual(self.em.command_extensions(command), [extension])
コード例 #5
0
    def test_extension_extending_command_capability_matches_command_name(self):
        extension = self.mock_extension(extends=['name'])

        command = CommandId('name', 'doc', lambda x: x, ())

        self.em._all_extensions.append(extension)
        self.em.enable_all_extensions()

        self.assertEqual(self.em.command_extensions(command), [extension])
コード例 #6
0
 def test_multiple_application_contexts_is_converted_to_tuple(self):
     self.assertEqual(
         CommandId('command',
                   'desc',
                   None, [],
                   application_contexts=[
                       ApplicationContext.INTERNAL,
                       ApplicationContext.EXTENDABLE
                   ]).application_contexts,
         (ApplicationContext.INTERNAL, ApplicationContext.EXTENDABLE))
コード例 #7
0
    def test_mixed_extends(self):
        command = CommandId('name', 'doc', lambda x: x, (), uses=['a'])

        extension_1 = self.mock_extension(extends=[command])
        self.em._all_extensions.append(extension_1)
        extension_2 = self.mock_extension(extends=['a', 'name'])
        self.em._all_extensions.append(extension_2)

        self.em.enable_all_extensions()

        self.assertEqual(self.em.command_extensions(command),
                         [extension_1, extension_2])
コード例 #8
0
    def test_call_get_endpoints_and_messages_with_uninitialized_command_extension(
            self):
        extension = Mock()
        extension.endpoints_and_messages = {Mock(): [Mock(), Mock()]}
        extension.extension_type = ExtensionType.COMMAND
        extension.load_order = 5
        command = CommandId('name', 'doc', lambda x: x, ())
        extension.extends = [command]

        self.em._all_extensions.append(extension)
        self.em.enable_all_extensions()

        self.assertEqual(self.em.get_endpoints_and_messages(command),
                         extension.endpoints_and_messages)
コード例 #9
0
    multiple=True,
    namespace='httpfileserver')

FILE_SERVER_REDIRECT = ConfigOptionId('redirect',
                                      'Redirect path to another. from:to',
                                      multiple=True,
                                      namespace='httpfileserver')

FILE_SERVER = CommandId('httpfileserver',
                        httpfileserver_command.__doc__,
                        httpfileserver_command,
                        config_options=[
                            ConfigOption(FILE_SERVER_IP, required=True),
                            ConfigOption(FILE_SERVER_PORT, required=True),
                            ConfigOption(FILE_SERVER_SERVE_DATA,
                                         required=False),
                            ConfigOption(FILE_SERVER_SERVE_FILE,
                                         required=False),
                            ConfigOption(FILE_SERVER_ACCEPT_UPLOAD,
                                         required=False),
                            ConfigOption(FILE_SERVER_DENY, required=False),
                            ConfigOption(FILE_SERVER_REDIRECT, required=False),
                        ])


@FrameworkExtension(name='httpfileserver',
                    config_options=[],
                    commands=[FILE_SERVER],
                    endpoints_and_messages={})
class HttpFileServerAddon(AbstractExtension):
    def __init__(self, config, instances):
コード例 #10
0
from zaf.commands.command import CommandId
from zaf.extensions.extension import AbstractExtension, CommandExtension


def action():
    pass


TESTCOMMANDADDON_COMMAND = CommandId('testcommand', 'A command only used for testing', action, [])


@CommandExtension('testcommandaddon', extends=[TESTCOMMANDADDON_COMMAND])
class TestCommandAddon(AbstractExtension):

    def __init__(self, config, instances):
        pass
コード例 #11
0
    try:
        futures[0].result()
        print('Created output file: {file}'.format(file=output_html))
        return 0
    except Exception as e:
        print("Failed to create file '{file}': {msg}".format(file=output_html, msg=str(e)))
        return 1


OUTPUT_HTML = ConfigOptionId('output.html', 'The output HTML file. Default <input name>.html.')

HTML_CSS_STYLESHEET = ConfigOptionId(
    'css.stylesheet',
    'The CSS stylesheet',
    default=data_file('styles/zenterio-html-theme.css'),
    option_type=Path(exists=True))

HTML_COMMAND = CommandId(
    'html', 'Generate HTML', html, [
        ConfigOption(OUTPUT_HTML, required=False),
        ConfigOption(HTML_CSS_STYLESHEET, required=True),
    ])


@FrameworkExtension(
    name='htmlcommand',
    commands=[HTML_COMMAND],
)
class HtmlCommand(AbstractExtension):
    pass
コード例 #12
0
ファイル: docgen.py プロジェクト: andni233/opensourcelib
    'include.custom.logging.docs',
    'Include application-specific logging documentation items',
    option_type=Path(),
    multiple=True,
    namespace='docgen',
    short_alias=True)

DOCGEN_COMMAND = CommandId(
    'docgen',
    docgen.__doc__,
    docgen,
    config_options=[
        ConfigOption(DOC_DIR, required=True),
        ConfigOption(LIMIT_EXTENSION_NAMESPACES, required=False),
        ConfigOption(ADDITIONAL_EXTENSIONS, required=False),
        ConfigOption(INCLUDE_COMPONENTS, required=True),
        ConfigOption(INCLUDE_ENDPOINTS_AND_MESSAGES, required=True),
        ConfigOption(INCLUDE_CLASSES, required=True),
        ConfigOption(INCLUDE_HIDDEN_COMMANDS, required=True),
        ConfigOption(INCLUDE_HIDDEN_OPTIONS, required=True),
        ConfigOption(INCLUDE_CUSTOM_LOGGING_DOCS, required=False),
    ],
    hidden=True,
    uses=['changelog'],
)


@FrameworkExtension(name='docgencommand', commands=[DOCGEN_COMMAND])
class DocGenCommand(object):
    """Provides the docgen command."""
    def __init__(self, config, instances):
        pass
コード例 #13
0
ファイル: unittest.py プロジェクト: andni233/opensourcelib
    'A specific test case can be identified by appending :<test>. '
    'This can be given multiple times and it overrides the extension name argument'
),
                       multiple=True,
                       namespace='unittest',
                       short_alias=True)

UNITTEST_COMMAND = CommandId(
    'unittest',
    unittest.__doc__,
    unittest,
    config_options=[
        ConfigOption(EXTENSION_NAMES, required=False),
        ConfigOption(REPORT_ENABLED, required=False),
        ConfigOption(REPORT_FILE, required=False),
        ConfigOption(COVERAGE_ENABLED, required=False),
        ConfigOption(COVERAGE_FILE, required=False),
        ConfigOption(COVERAGE_XML_ENABLED, required=False),
        ConfigOption(COVERAGE_XML_FILE, required=False),
        ConfigOption(DETAILS, required=False),
        ConfigOption(EXCLUDE_SYSTESTS, required=False),
        ConfigOption(TESTS, required=False)
    ],
    hidden=True,
)


@FrameworkExtension(name='unittestcommand', commands=[UNITTEST_COMMAND])
class UnittestCommand():
    """Provides the unittest command."""
    def __init__(self, config, instances):
        pass
コード例 #14
0
            self):
        check_for_ambiguous_duplicates(
            'zaf', [], {
                COMMAND: [option('name')],
                COMMAND2: [option('name', namespace='namespace')]
            })

    def test_commands_options_on_different_commands_with_same_short_name_does_not_raise_exception(
            self):
        check_for_ambiguous_duplicates(
            'zaf', [], {
                COMMAND: [option('name1', short_name='n')],
                COMMAND2: [option('name2', short_name='n')]
            })


def option(name, namespace=None, short_name=None):
    global unique_id_counter
    unique_id_counter += 1
    return ConfigOption(
        ConfigOptionId(
            name,
            str(unique_id_counter),
            namespace=namespace,
            short_alias=bool(namespace),
            short_name=short_name),
        required=True)


COMMAND2 = CommandId('command2', '', callable=None, config_options=[])
コード例 #15
0
 def test_application_contexts_not_given_gives_empty_tuple(self):
     self.assertEqual(
         CommandId('command', 'desc', None, []).application_contexts, ())
コード例 #16
0
ファイル: yaml.py プロジェクト: andni233/opensourcelib
            filename=os.path.splitext(adoc_file)[0])
    output_yaml = os.path.abspath(output_yaml)

    futures = zpider.messagebus.send_request(
        GENERATE_DOC, data=YamlAsciidoctorCommand(output_yaml))
    futures.wait()
    try:
        futures[0].result()
        print('Created output file: {file}'.format(file=output_yaml))
        return 0
    except Exception as e:
        print("Failed to create file '{file}': {msg}".format(file=output_yaml,
                                                             msg=str(e)))
        return 1


OUTPUT_YAML = ConfigOptionId(
    'output.yaml', 'The output YAML file. Default <input name>.yaml.')

YAML_COMMAND = CommandId('yaml', 'Generate YAML', yaml, [
    ConfigOption(OUTPUT_YAML, required=False),
])


@FrameworkExtension(
    name='yamlcommand',
    commands=[YAML_COMMAND],
)
class YamlCommand(AbstractExtension):
    pass
コード例 #17
0
                text += 'The power state of sut {sut} was already {state}\n'.format(
                    sut=sut, state=sut_result['state'])
    return text


POWER_SUBCOMMAND = ConfigOptionId(
    'powerswitch.subcommand',
    'The subcommand to powerswitch',
    option_type=Choice(['state', 'on', 'off']),
    argument=True)

POWER_COMMAND = CommandId(
    'powerswitch',
    power.__doc__,
    power,
    config_options=[
        ConfigOption(POWER_SUBCOMMAND, required=True),
        ConfigOption(JSON_OUTPUT, required=False),
        ConfigOption(SUT, required=True)
    ])


@FrameworkExtension(
    'powerswitch',
    commands=[POWER_COMMAND],
    groups=['powerswitch'],
)
class PowerSwitchExtension(object):
    """Provides the power command."""

    def __init__(self, config, instances):
コード例 #18
0
    def test_count_clamped_to_max_value(self):
        count_option = ConfigOption(ConfigOptionId('count',
                                                   '',
                                                   option_type=Count(0, 1)),
                                    required=False)
        self.config.set(count_option.option_id, 0)

        with patch('sys.argv', ['zaf', '--count', '--count', 'command']):
            extension_config = self.plugin.get_config(self.config,
                                                      [count_option],
                                                      {COMMAND: []})
            self.assertIn('count', extension_config.config)
            self.assertEqual(extension_config.config['count'], 1)


COMMAND = CommandId('command', '', callable=None, config_options=[])
COMMAND_ALLOW_UNKNOWN = CommandId('command-unknown',
                                  '',
                                  callable=None,
                                  config_options=[],
                                  allow_unknown_options=True)
REQUIRED = ConfigOption(ConfigOptionId('required', ''), required=True)
ENTITY_IDS = ConfigOptionId('ids',
                            '',
                            entity=True,
                            multiple=True,
                            namespace='entities')
DEPENDENT = ConfigOption(ConfigOptionId('dependent', '', at=ENTITY_IDS),
                         required=True)
REQUIRED_ARGUMENT = ConfigOptionId('required.arg', '', argument=True)
SINGLE_ENTITY_ID = ConfigOptionId('id',
コード例 #19
0
ファイル: noop.py プロジェクト: andni233/opensourcelib
"""Provides the *noop* (no operation) command."""

import logging

from zaf.application import ApplicationContext
from zaf.commands.command import CommandId
from zaf.extensions.extension import AbstractExtension, FrameworkExtension, get_logger_name

logger = logging.getLogger(get_logger_name('zaf', 'noop'))
logger.addHandler(logging.NullHandler())


def noop(core):
    """Noop (no operation) command. Does nothing. Takes no arguments."""
    return 0


NOOP_COMMAND = CommandId('noop',
                         noop.__doc__,
                         noop, [],
                         hidden=True,
                         application_contexts=ApplicationContext.EXTENDABLE)


@FrameworkExtension(name='noop', commands=[NOOP_COMMAND])
class NoopExtension(AbstractExtension):
    """Provides the noop (no operation) command."""
    def __init__(self, config, instances):
        pass
コード例 #20
0
ファイル: subcommands.py プロジェクト: andni233/opensourcelib
    cfg = application.config
    print('command', cfg.get(COMMAND_OPTION))


def subcommand(application):
    cfg = application.config
    print('subcommand', cfg.get(COMMAND_OPTION), cfg.get(SUBCOMMAND_OPTION))


def subsubcommand(application):
    cfg = application.config
    print('subsubcommand', cfg.get(COMMAND_OPTION), cfg.get(SUBCOMMAND_OPTION),
          cfg.get(SUBSUBCOMMAND_OPTION))


COMMAND = CommandId('command', 'description', command,
                    [ConfigOption(COMMAND_OPTION, required=True)])
SUBCOMMAND = CommandId('subcommand',
                       'description',
                       subcommand,
                       [ConfigOption(SUBCOMMAND_OPTION, required=True)],
                       parent=COMMAND)
SUBSUBCOMMAND = CommandId('subsubcommand',
                          'description',
                          subsubcommand,
                          [ConfigOption(SUBSUBCOMMAND_OPTION, required=True)],
                          parent=SUBCOMMAND)


@FrameworkExtension('subcommands',
                    commands=[COMMAND, SUBCOMMAND, SUBSUBCOMMAND])
class Commands(AbstractExtension):
コード例 #21
0
        # Send CONTINUE before stopping blocking so that it exists in the testcase queue
        # on next get. This verifies that the block actually blocked the test case
        client.send_request(CONTINUE, ENDPOINT).wait(timeout=1)

        blocker.stop_blocking()
        assert blocker.wait_for_finished()

        # Send a final continue to test case. This is needed because otherwise the remote server
        # will be stopped before the BLOCKING_COMPLETED message has been received
        client.send_request(CONTINUE, ENDPOINT, is_async=True)

    print('Reached end of command')


REMOTE_AND_BLOCKER_COMMAND = CommandId('remoteandblockercommand',
                                       '',
                                       remote_and_blocker_command,
                                       config_options=[])

REMOTE_AND_BLOCKER_USING_BLOCKER_COMPONENT_COMMAND = CommandId(
    'remoteandblockerusingblockercomponentcommand',
    '',
    remote_and_blocker_using_blocker_component_command,
    config_options=[])


@FrameworkExtension(
    'usestheblockerandremotefacilitiesextension',
    commands=[
        REMOTE_AND_BLOCKER_COMMAND,
        REMOTE_AND_BLOCKER_USING_BLOCKER_COMPONENT_COMMAND
    ],
コード例 #22
0
        with self.assertRaisesRegex(TypeError, regex):
            self.validator.get_config(config, [], {CMD: all_options})


def create_config(options, entity=None, additional_options={}):
    config = ConfigManager()
    for option_id, value in options.items():
        key = config._option_key(option_id, entity)
        config._config[key].add(value, 1, '')
    for option, value in additional_options.items():
        key = config._option_key(option.option_id)
        config._config[key].add(value, 1, '')
    return config


CMD = CommandId('cmd', '', None, [])
MULTIPLE_STR_OPTION = ConfigOption(ConfigOptionId('multiple.str.option',
                                                  '',
                                                  multiple=True),
                                   required=False)
STR_OPTION = ConfigOption(ConfigOptionId('str.option', ''), required=False)
INT_OPTION = ConfigOption(ConfigOptionId('int.option', '', option_type=int),
                          required=False)
FLOAT_OPTION = ConfigOption(ConfigOptionId('float.option',
                                           '',
                                           option_type=float),
                            required=False)
BOOL_OPTION = ConfigOption(ConfigOptionId('bool.option', '', option_type=bool),
                           required=False)
FLAG_OPTION = ConfigOption(ConfigOptionId('flag.option',
                                          '',
コード例 #23
0
        help_output = StringIO()

        with patch('sys.argv', ['zaf', '--full-help']), \
                self.assertRaises(SystemExit),\
                redirect_stdout(help_output):
            self.plugin.get_config(self.config, self.options, self.commands_with_options)

        if not_in:
            self.assertNotIn(string, help_output.getvalue(), msg=help_output.getvalue())
        else:
            self.assertIn(string, help_output.getvalue(), msg=help_output.getvalue())


COMMAND_INTERNAL = CommandId(
    'internalcommand',
    '',
    callable=None,
    config_options=[],
    application_contexts=ApplicationContext.INTERNAL)
COMMAND_EXTENDABLE = CommandId(
    'extendablecommand',
    '',
    callable=None,
    config_options=[],
    application_contexts=ApplicationContext.EXTENDABLE)
COMMAND_NONE = CommandId('nonecommand', '', callable=None, config_options=[])
OPTION_INTERNAL = ConfigOption(
    ConfigOptionId('internaloption', '', application_contexts=ApplicationContext.INTERNAL),
    required=False)
OPTION_EXTENDABLE = ConfigOption(
    ConfigOptionId('extendableoption', '', application_contexts=ApplicationContext.EXTENDABLE),
    required=False)
コード例 #24
0
ファイル: test_help.py プロジェクト: andni233/opensourcelib
        with patch('sys.argv', argv), \
                self.assertRaises(SystemExit),\
                redirect_stdout(help_output):
            self.plugin.get_config(self.config, options, commands_with_options)

        if not_in:
            self.assertNotIn(string,
                             help_output.getvalue(),
                             msg=help_output.getvalue())
        else:
            self.assertIn(string,
                          help_output.getvalue(),
                          msg=help_output.getvalue())


COMMAND = CommandId('mycommand', '', callable=None, config_options=[])
COMMAND_HIDDEN = CommandId('myhiddencommand',
                           '',
                           callable=None,
                           config_options=[],
                           hidden=True)
OPTION_REQUIRED = ConfigOption(ConfigOptionId(
    'requiredoption',
    '',
),
                               required=True)
OPTION_REQUIRED_WITH_DEFAULT = ConfigOption(ConfigOptionId(
    'defaultrequiredoption', '', default='mydefault'),
                                            required=True)
OPTION_OPTIONAL = ConfigOption(ConfigOptionId(
    'optionaloption',
コード例 #25
0
            {{message.name}}
              {%- for line in message.description.strip().splitlines() %}
              {{line}}
              {%- endfor %}
              {%- if endpoints %}

              endpoints
                {%- for endpoint in endpoints %}
                {{endpoint.name}}
                {%- endfor %}
              {%- endif %}
            {% endfor %}
            """)
    return render_template(template_string,
                           messages_with_endpoints=messages_with_endpoints)


MESSAGES_COMMAND = CommandId(
    'messages',
    messages.__doc__,
    messages,
    config_options=[ConfigOption(TARGET_COMMAND, required=True)],
    application_contexts=ApplicationContext.EXTENDABLE)


@FrameworkExtension(name='messagescommand', commands=[MESSAGES_COMMAND])
class MessagesCommand():
    """Provides the messages command."""
    def __init__(self, config, instances):
        pass
コード例 #26
0
ファイル: run.py プロジェクト: andni233/opensourcelib
    :param name: the message_id defining the sequence poitn
    :param message_bus: the messagebus to send the message to
    :param data: message data
    """
    logger.debug('Executing sequence point {sequence_point}'.format(
        sequence_point=message_id.name))
    messagebus.trigger_event(message_id,
                             RUN_COMMAND_ENDPOINT,
                             entity=entity,
                             data=data)


RUN_COMMAND = CommandId(
    'run',
    run.__doc__,
    run, [
        ConfigOption(EXIT_CODE_FROM_VERDICT, required=True),
    ],
    uses=['sut'])


@FrameworkExtension(name='runcommand',
                    commands=[RUN_COMMAND],
                    endpoints_and_messages={
                        RUN_COMMAND_ENDPOINT: [
                            PRE_INITIALIZE_SUT, INITIALIZE_SUT,
                            POST_INITIALIZE_SUT, UNINITIALIZE_SUT,
                            PRE_TEST_RUN, TEST_RUN, POST_TEST_RUN,
                            GET_RUN_VERDICT
                        ]
                    })
コード例 #27
0
    def _init_commands(self):
        """
        Initialize the command metadata objects.

        Commands are only included if the belong to an extension class that
        is included in the metadata and they are not filtered out by the
        MetadataFilter.

        The commands will only contain config option ids that
        are not filtered out by the metadata filter.
        """
        framework_config_option_ids = {
            config_option.option_id
            for ext_class in self._extension_manager.framework_extensions(
                only_enabled=False) if ext_class in self._extension_classes
            for config_option in ext_class.config_options
            if self._metadata_filter.include_config_option_id(
                config_option.option_id)
        }

        root_command = CommandId(
            self._application_name, 'The {application} root command.'.format(
                application=self._application_name), None, [])
        commands = OrderedDict([
            (root_command,
             CommandMetadata(self, root_command, None, root_command, [], [],
                             framework_config_option_ids))
        ])

        for command, defining_ext_class in sorted(
            ((command, ext_class)
             for ext_class in self._extension_classes.keys()
             for command in ext_class.commands
             if self._metadata_filter.include_command(command)),
                key=lambda t: t[0].name):

            config_option_ids = [
                config_option.option_id
                for config_option in command.config_options
                if self._metadata_filter.include_config_option_id(
                    config_option.option_id)
            ]

            ext_classes = [
                ext_class
                for ext_class in self._extension_manager.command_extensions(
                    command, only_enabled=False)
                if ext_class in self._extension_classes
            ]
            extension_config_option_ids = set()
            for ext_class in ext_classes:
                extension_config_option_ids.update([
                    config_option.option_id
                    for config_option in ext_class.config_options
                    if self._metadata_filter.include_config_option_id(
                        config_option.option_id)
                ])

            commands[command] = CommandMetadata(
                self, command, defining_ext_class, root_command, ext_classes,
                config_option_ids,
                sorted(extension_config_option_ids, key=lambda c: c.key))

        self._commands = commands
コード例 #28
0
            {{cmd.name}}
              {%- for line in cmd.description.splitlines() %}
              {{line}}
              {%- endfor %}
            {% endfor %}
            """)
    return render_template(template_string, commands=commands)


COMMANDS_SHORT = ConfigOptionId(
    name='short',
    description='Short format (less information)',
    option_type=Flag(),
    default=False,
    namespace='commands',
    short_alias=True)

COMMANDS_COMMAND = CommandId(
    'commands',
    command_list.__doc__,
    command_list, [ConfigOption(COMMANDS_SHORT, required=False)],
    application_contexts=ApplicationContext.EXTENDABLE)


@FrameworkExtension(name='commandscommand', commands=[COMMANDS_COMMAND])
class CommandsCommand():
    """Provides the commands command."""

    def __init__(self, config, instances):
        pass
コード例 #29
0
    return docker_run.run_in_docker(command_with_arguments,
                                    forward_signals=False)


EXEC_COMMAND_WITH_ARGUMENTS = ConfigOptionId(
    'command.with.arguments',
    'The command to run.',
    multiple=True,
    namespace='exec',
    argument=True,
)

EXEC_COMMAND = CommandId(
    'exec',
    exec.__doc__,
    exec,
    config_options=[
        ConfigOption(EXEC_COMMAND_WITH_ARGUMENTS, required=True),
    ],
    allow_unknown_options=True,
)


@FrameworkExtension(
    'execcommand',
    commands=[EXEC_COMMAND],
)
class ExecExtension(AbstractExtension):
    pass
コード例 #30
0
ファイル: endpoints.py プロジェクト: andni233/opensourcelib
            {{endpoint.name}}
              {%- for line in endpoint.description.strip().splitlines() %}
              {{line}}
              {%- endfor %}
              {%- if messages %}

              messages
                {%- for message in messages %}
                {{message.name}}
                {%- endfor %}
              {%- endif %}
            {% endfor %}
            """)
    return render_template(template_string,
                           endpoints_and_messages=endpoints_and_messages)


ENDPOINTS_COMMAND = CommandId(
    'endpoints',
    endpoints.__doc__,
    endpoints,
    config_options=[ConfigOption(TARGET_COMMAND, required=True)],
    application_contexts=ApplicationContext.EXTENDABLE)


@FrameworkExtension('endpointscommand', commands=[ENDPOINTS_COMMAND])
class EndpointsCommand():
    """Provides the endpoints command."""
    def __init__(self, config, instances):
        pass