Пример #1
0
    def strings(self, no_space=False):
        """
        checks if a configuration is a collection of strings

        After an instance has been set a configuration key (via `conf`), this
        method can be used to check if the value (if any) configured with this
        key is a collection of strings. If not, an
        `ConfluenceConfigurationError` exception will be thrown.

        In the event that the configuration is not set (e.g. a value of `None`)
        or is an empty collection, this method will have no effect.

        Args:
            no_space (optional): whether or not all string values cannot contain
                                  any spaces (default: False)

        Returns:
            the validator instance
        """
        value = self._value()

        if value is not None:
            if not (isinstance(value, (list, set, tuple))
                    and all(isinstance(entry, basestring) for entry in value)):
                raise ConfluenceConfigurationError(
                    '%s is not a collection of strings' % self.key)

            if no_space:
                for entry in value:
                    if ' ' in entry:
                        raise ConfluenceConfigurationError(
                            '%s has an entry containing a space' % self.key)

        return self
Пример #2
0
    def docnames(self):
        """
        checks if a configuration is a collection of valid docnames

        After an instance has been set a configuration key (via `conf`), this
        method can be used to check if the value (if any) configured with this
        key is a collection of valid docnames. If not, an
        `ConfluenceConfigurationError` exception will be thrown.

        In the event that the configuration is not set (e.g. a value of `None`)
        or is an empty collection, this method will have no effect.

        Returns:
            the validator instance
        """
        value = self._value()

        if value is not None:
            if not (isinstance(value, (list, set, tuple)) or
                    not all(isinstance(label, basestring) for label in value)):
                raise ConfluenceConfigurationError(
                    '%s is not a collection of filenames' % self.key)

            for docname in value:
                if not any(
                        os.path.isfile(
                            os.path.join(self.env.srcdir, docname + suffix))
                        for suffix in self.config.source_suffix):
                    raise ConfluenceConfigurationError(
                        '%s is missing document %s' % (self.key, docname))

        return self
Пример #3
0
    def string_or_strings(self):
        """
        checks if a configuration is a string or collection of strings

        After an instance has been set a configuration key (via `conf`), this
        method can be used to check if the value (if any) configured with this
        key is a string or collection of strings. If not, an
        `ConfluenceConfigurationError` exception will be thrown.

        In the event that the configuration is not set (e.g. a value of `None`)
        or is an empty collection, this method will have no effect.

        Returns:
            the validator instance
        """
        value = self._value()

        if value is not None:
            if isinstance(value, (list, set, tuple)):
                if not all(isinstance(entry, basestring) for entry in value):
                    raise ConfluenceConfigurationError(
                        '%s is not a collection of strings' % self.key)
            elif not isinstance(value, basestring):
                raise ConfluenceConfigurationError(
                    '%s is not a string or collection of strings' % self.key)

        return self
Пример #4
0
    def int_(self, positive=False):
        """
        checks if a configuration is an integer

        After an instance has been set a configuration key (via `conf`), this
        method can be used to check if the value (if any) configured with this
        key is an integer. If not, an `ConfluenceConfigurationError` exception
        will be thrown.

        In the event that the configuration is not set (e.g. a value of `None`),
        this method will have no effect.

        Args:
            positive (optional): whether or not the integer value must be a
                                  positive value (default: False)

        Returns:
            the validator instance
        """
        value = self._value()

        if value is not None:
            if positive:
                if not isinstance(value, int) or value <= 0:
                    raise ConfluenceConfigurationError(
                        '%s is not a positive integer' % self.key)
            elif not isinstance(value, int) or value < 0:
                raise ConfluenceConfigurationError(
                    '%s is not a non-negative integer' % self.key)

        return self
Пример #5
0
    def getBasePageId(self):
        base_page_id = None

        if not self.parent_name:
            return base_page_id

        rsp = self.rest_client.get('content', {
            'type': 'page',
            'spaceKey': self.space_name,
            'title': self.parent_name,
            'status': 'current'
        })
        if rsp['size'] == 0:
            raise ConfluenceConfigurationError("""Configured parent """
                """page name do not exist.""")
        page = rsp['results'][0]
        if self.parent_id and page['id'] != str(self.parent_id):
            raise ConfluenceConfigurationError("""Configured parent """
                """page ID and name do not match.""")
        base_page_id = page['id']
        self._name_cache[base_page_id] = self.parent_name

        if not base_page_id and self.parent_id:
            raise ConfluenceConfigurationError("""Unable to find the """
                """parent page matching the ID or name provided.""")

        return base_page_id
Пример #6
0
    def bool(self):
        """
        checks if a configuration is a boolean

        After an instance has been set a configuration key (via `conf`), this
        method can be used to check if the value (if any) configured with this
        key is a boolean. If not, an `ConfluenceConfigurationError` exception
        will be thrown.

        In the event that the configuration is not set (e.g. a value of `None`),
        this method will have no effect.

        Returns:
            the validator instance
        """
        value = self._value()

        if value is not None:
            if isinstance(value, basestring):
                try:
                    str2bool(value)
                except ValueError:
                    raise ConfluenceConfigurationError(
                        '%s is not a boolean string' % self.key)
            elif not isinstance(value, bool) and not isinstance(value, int):
                raise ConfluenceConfigurationError('%s is not a boolean type' %
                                                   self.key)

        return self
Пример #7
0
    def docnames_from_file(self):
        """
        checks if a configuration is a collection of valid docnames from a file

        After an instance has been set a configuration key (via `conf`), this
        method can be used to check if the value (if any) configured with this
        key is a collection of valid docnames found within the contents of a
        valid file. If not, an `ConfluenceConfigurationError` exception will be
        thrown.

        In the event that the configuration is not set (e.g. a value of `None`),
        this method will have no effect.

        Returns:
            the validator instance
        """
        value = self._value()

        if value is not None:
            if not isinstance(value, basestring) or not os.path.isfile(
                    os.path.join(self.env.srcdir, value)):
                raise ConfluenceConfigurationError('%s is not a file' %
                                                   self.key)

            docnames = extract_strings_from_file(value)
            for docname in docnames:
                if not any(
                        os.path.isfile(
                            os.path.join(self.env.srcdir, docname + suffix))
                        for suffix in self.config.source_suffix):
                    raise ConfluenceConfigurationError(
                        '%s is missing document %s' % (self.key, docname))

        return self
Пример #8
0
    def matching(self, *expected):
        """
        checks if a configuration matches any of the expected arguments

        After an instance has been set a configuration key (via `conf`), this
        method can be used to check if the value (if any) configured with this
        key matches one of the provided expected arguments. If not, an
        `ConfluenceConfigurationError` exception will be thrown.

        In the event that the configuration is not set (e.g. a value of `None`),
        this method will have no effect.

        Args:
            *expected: valid entries for a configuration to check against

        Returns:
            the validator instance
        """
        value = self._value()

        if value is not None and value not in expected:
            raise ConfluenceConfigurationError(
                '%s does not match expected values' % self.key)

        return self
Пример #9
0
    def string(self, permit_empty=False):
        """
        checks if a configuration is a string

        After an instance has been set a configuration key (via `conf`), this
        method can be used to check if the value (if any) configured with this
        key is a string. If not, an `ConfluenceConfigurationError` exception
        will be thrown.

        In the event that the configuration is not set (e.g. a value of `None`),
        this method will have no effect.

        Args:
            permit_empty (optional): whether or not all an empty string of this
                                      value is considered to be a set value

        Returns:
            the validator instance
        """
        value = self._value(permit_empty=True)

        if value is not None and not isinstance(value, basestring):
            raise ConfluenceConfigurationError(
                '%s is not a string' % self.key)

        return self
Пример #10
0
    def dict_str_str(self):
        """
        checks if a configuration is a dictionary (str, str)

        After an instance has been set a configuration key (via `conf`), this
        method can be used to check if the value (if any) configured with this
        key is a dictionary type with string keys and values. If not, an
        `ConfluenceConfigurationError` exception will be thrown.

        In the event that the configuration is not set (e.g. a value of `None`)
        or is an empty dictionary, this method will have no effect.

        Returns:
            the validator instance
        """
        value = self._value()

        if value is not None:
            if not isinstance(value, dict) or not all(
                    isinstance(k, basestring) and isinstance(v, basestring)
                    for k, v in value.items()):
                raise ConfluenceConfigurationError(
                    '%s is not a dictionary of strings' % self.key)

        return self
Пример #11
0
    def get_base_page_id(self):
        base_page_id = None

        if not self.parent_ref:
            return base_page_id

        if isinstance(self.parent_ref, int):
            base_page_id, page = self.get_page_by_id(self.parent_ref)

            if not page:
                raise ConfluenceConfigurationError(
                    '''Configured parent page identifier does not exist.''')

            return base_page_id

        rsp = self.rest_client.get(
            'content', {
                'type': 'page',
                'spaceKey': self.space_key,
                'title': self.parent_ref,
                'status': 'current'
            })
        if rsp['size'] == 0:
            raise ConfluenceConfigurationError(
                '''Configured parent page name does not exist.''')
        page = rsp['results'][0]
        if self.parent_id and page['id'] != str(self.parent_id):
            raise ConfluenceConfigurationError(
                """Configured parent """
                """page ID and name do not match.""")
        base_page_id = page['id']
        self._name_cache[base_page_id] = self.parent_ref

        if not base_page_id and self.parent_id:
            raise ConfluenceConfigurationError(
                """Unable to find the """
                """parent page matching the ID or name provided.""")

        return base_page_id
Пример #12
0
def process_ask_configs(config):
    """
    process any ask-based configurations for a user

    A series of asking configurations can be set in a configuration, such as
    asking for a password on a command line. This call will help process through
    the available questions and populate a final configuration state for the
    builder/publisher to use.

    Args:
        config: the configuration to check/update
    """

    if config.confluence_ask_user:
        print('(request to accept username from interactive session)')
        print(' Instance: ' + config.confluence_server_url)

        default_user = config.confluence_server_user
        u_str = ''
        if default_user:
            u_str = ' [{}]'.format(default_user)

        input_ = compat.compat_input
        target_user = input_(' User{}: '.format(u_str)) or default_user
        if not target_user:
            raise ConfluenceConfigurationError('no user provided')

        config.confluence_server_user = target_user

    if config.confluence_ask_password:
        print('(request to accept password from interactive session)')
        if not config.confluence_ask_user:
            print(' Instance: ' + config.confluence_server_url)
            print('     User: '******' Password: '******'')
        if not config.confluence_server_pass:
            raise ConfluenceConfigurationError('no password provided')
Пример #13
0
    def callable_(self):
        """
        checks if a configuration is a callable

        After an instance has been set a configuration key (via `conf`), this
        method can be used to check if the value (if any) configured with this
        key is a callable type. If not, an `ConfluenceConfigurationError`
        exception will be thrown.

        In the event that the configuration is not set (e.g. a value of `None`),
        this method will have no effect.

        Returns:
            the validator instance
        """
        value = self._value()

        if value is not None and not callable(value):
            raise ConfluenceConfigurationError('%s is not a callable' %
                                               self.key)

        return self
Пример #14
0
    def file(self):
        """
        checks if a configuration is a valid file

        After an instance has been set a configuration key (via `conf`), this
        method can be used to check if the value (if any) configured with this
        key is a valid file. If not, an `ConfluenceConfigurationError` exception
        will be thrown.

        In the event that the configuration is not set (e.g. a value of `None`),
        this method will have no effect.

        Returns:
            the validator instance
        """
        value = self._value()

        if value is not None:
            if not isinstance(value, basestring) or not os.path.isfile(
                    os.path.join(self.env.srcdir, value)):
                raise ConfluenceConfigurationError('%s is not a file' %
                                                   self.key)

        return self
Пример #15
0
def validate_configuration(builder):
    """
    validate a builder's configuration state

    This call will check if the provided builder's configuration has any issues
    with the existing configuration. For errors in the existing configuration,
    an `ConfluenceConfigurationError` exception will be thrown.

    In addition to errors, this call will also generate warning messages on
    other configuration issues such as deprecated configurations.

    Args:
        builder: the builder state to validate a configuration on
    """

    config = builder.config
    env = builder.app.env
    validator = ConfigurationValidation(builder)

    # ##################################################################

    # confluence_add_secnumbers
    validator.conf('confluence_add_secnumbers') \
             .bool()

    # ##################################################################

    # confluence_additional_mime_types
    validator.conf('confluence_additional_mime_types') \
             .strings(no_space=True)

    # ##################################################################

    # confluence_adv_aggressive_search
    validator.conf('confluence_adv_aggressive_search') \
             .bool()

    # ##################################################################

    # confluence_adv_permit_raw_html
    validator.conf('confluence_adv_permit_raw_html') \
             .bool()

    # ##################################################################

    # confluence_adv_trace_data
    validator.conf('confluence_adv_trace_data') \
             .bool()

    # ##################################################################

    # confluence_adv_writer_no_section_cap
    validator.conf('confluence_adv_writer_no_section_cap') \
             .bool()

    # ##################################################################

    # confluence_append_labels
    validator.conf('confluence_append_labels') \
             .bool()

    # ##################################################################

    # confluence_ask_password
    validator.conf('confluence_ask_password') \
             .bool()

    # ##################################################################

    # confluence_ask_user
    validator.conf('confluence_ask_user') \
             .bool()

    # ##################################################################

    # confluence_asset_force_standalone
    validator.conf('confluence_asset_force_standalone') \
             .bool()

    # ##################################################################

    # confluence_asset_override
    validator.conf('confluence_asset_override') \
             .bool()

    # ##################################################################

    validator.conf('confluence_ca_cert') \
             .path()

    # ##################################################################

    if config.confluence_client_cert is not None:
        client_cert = config.confluence_client_cert
        if isinstance(client_cert, tuple):
            cert_files = client_cert
        else:
            cert_files = (client_cert, None)

        if len(cert_files) != 2:
            raise ConfluenceConfigurationError('''\
confluence_client_cert is not a 2-tuple

The option 'confluence_client_cert' has been provided but there are too many
values. The client certificate can either be a file/path which defines a
certificate/key-pair, or a 2-tuple of the certificate and key.
''')

        for cert in cert_files:
            if cert and not os.path.isfile(os.path.join(env.srcdir, cert)):
                raise ConfluenceConfigurationError('''\
confluence_ca_cert missing certificate file

The option 'confluence_client_cert' has been provided to find a client
certificate file from a relative location, but the certificate could not be
found. Ensure the following file exists:

    {file}

'''.format(file=cert))

    # ##################################################################

    # confluence_client_cert_pass
    validator.conf('confluence_client_cert_pass') \
             .string()

    # ##################################################################

    # confluence_default_alignment
    try:
        validator.conf('confluence_default_alignment') \
                 .matching('left', 'center', 'right')
    except ConfluenceConfigurationError as e:
        raise ConfluenceConfigurationError('''\
{msg}

The option 'confluence_default_alignment' has been provided to override the
default alignment for tables, figures, etc. Accepted values include 'left',
'center' and 'right'.
'''.format(msg=e))

    # ##################################################################

    # confluence_disable_autogen_title
    validator.conf('confluence_disable_autogen_title') \
             .bool()

    # ##################################################################

    # confluence_disable_notifications
    validator.conf('confluence_disable_notifications') \
             .bool()

    # ##################################################################

    # confluence_disable_ssl_validation
    validator.conf('confluence_disable_ssl_validation') \
             .bool()

    # ##################################################################

    # confluence_domain_indices
    try:
        validator.conf('confluence_domain_indices').bool()
    except ConfluenceConfigurationError:
        try:
            validator.conf('confluence_domain_indices').strings()
        except ConfluenceConfigurationError:
            raise ConfluenceConfigurationError('''\
confluence_domain_indices is not a boolean or collection of strings

The option 'confluence_domain_indices' has been provided to indicate that
domain indices should be generated. This value can either be set to `True` or
set to a list of domains (strings) to be included.
''')

    # ##################################################################

    # confluence_file_suffix
    validator.conf('confluence_file_suffix') \
             .string()

    # ##################################################################

    # confluence_file_transform
    validator.conf('confluence_file_transform') \
             .callable_()

    # ##################################################################

    # confluence_footer_file
    try:
        validator.conf('confluence_footer_file') \
                 .string() \
                 .file()
    except ConfluenceConfigurationError as e:
        raise ConfluenceConfigurationError('''\
{msg}

The option 'confluence_footer_file' has been provided to find a footer template
file from a path relative to the documentation source. Ensure the value is set
to a proper file path.
'''.format(msg=e))

    # ##################################################################

    # confluence_global_labels
    try:
        validator.conf('confluence_global_labels') \
                 .strings(no_space=True)
    except ConfluenceConfigurationError as e:
        raise ConfluenceConfigurationError('''\
{msg}

The option 'confluence_global_labels' can provide a collection to string values
to use as labels for published documentation. Each label value must be a string
that contains no spaces.
'''.format(msg=e))

    # ##################################################################

    # confluence_header_file
    try:
        validator.conf('confluence_header_file') \
                 .string() \
                 .file()
    except ConfluenceConfigurationError as e:
        raise ConfluenceConfigurationError('''\
{msg}

The option 'confluence_header_file' has been provided to find a header template
file from a path relative to the documentation source. Ensure the value is set
to a proper file path.
'''.format(msg=e))

    # ##################################################################

    # confluence_ignore_titlefix_on_index
    validator.conf('confluence_ignore_titlefix_on_index') \
             .bool()

    # ##################################################################

    # confluence_include_search
    validator.conf('confluence_include_search') \
             .bool()

    # ##################################################################

    # confluence_jira_servers
    if config.confluence_jira_servers is not None:
        issue = False
        jira_servers = config.confluence_jira_servers

        if not isinstance(jira_servers, dict):
            issue = True
        else:
            for name, info in jira_servers.items():
                if not isinstance(name, basestring):
                    issue = True
                    break

                if not isinstance(info, dict):
                    issue = True
                    break

                jira_id = info.get('id')
                jira_name = info.get('name')

                if not (isinstance(jira_id, basestring) and
                        isinstance(jira_name, basestring)):
                    issue = True
                    break

        if issue:
            raise ConfluenceConfigurationError('''\
confluence_jira_servers is not properly formed

Jira server definitions should be a dictionary of string keys which contain
dictionaries with keys 'id' and 'name' which identify the Jira instances.
''')

    # ##################################################################

    # confluence_lang_transform
    validator.conf('confluence_lang_transform') \
             .callable_()

    # ##################################################################

    # confluence_latex_macro
    try:
        validator.conf('confluence_latex_macro').string()
    except ConfluenceConfigurationError:
        try:
            validator.conf('confluence_latex_macro').dict_str_str()

        except ConfluenceConfigurationError:
            raise ConfluenceConfigurationError('''\
confluence_latex_macro is not a string or dictionary of strings

The option 'confluence_latex_macro' has been provided to indicate that a
LaTeX content should be rendered with a LaTeX macro supported on a Confluence
instance. This value can either be set to a string of the macro to be used or
set to a dictionary of key-value strings for advanced options.
''')

        if config.confluence_latex_macro:
            conf_keys = config.confluence_latex_macro.keys()

            required_keys = [
                'block-macro',
                'inline-macro',
            ]

            if not all(name in conf_keys for name in required_keys):
                raise ConfluenceConfigurationError('''\
missing keys in confluence_latex_macro

The following keys are required:

 - {}
'''.format('\n - '.join(required_keys)))

    # ##################################################################

    # confluence_link_suffix
    validator.conf('confluence_link_suffix') \
             .string()

    # ##################################################################

    # confluence_link_transform
    validator.conf('confluence_link_transform') \
             .callable_()

    # ##################################################################

    # confluence_mentions
    validator.conf('confluence_mentions') \
             .dict_str_str()

    # ##################################################################

    # confluence_root_homepage
    validator.conf('confluence_root_homepage') \
             .bool()

    # ##################################################################

    # confluence_max_doc_depth
    try:
        validator.conf('confluence_max_doc_depth') \
                 .int_()
    except ConfluenceConfigurationError as e:
        raise ConfluenceConfigurationError('''\
{msg}

When limiting the document depth permitted for a building/publishing event, the
defined maximum document depth must be defined as a non-negative integer value.

If planning to use a depth of zero, it is recommended to use the
'singleconfluence' builder instead.
'''.format(msg=e))

    # ##################################################################

    # confluence_navdocs_transform
    validator.conf('confluence_navdocs_transform') \
             .callable_()

    # ##################################################################

    try:
        validator.conf('confluence_parent_page').string()
    except ConfluenceConfigurationError:
        try:
            validator.conf('confluence_parent_page').int_(positive=True)
        except ConfluenceConfigurationError:
            raise ConfluenceConfigurationError('''\
confluence_parent_page is not a string or a positive integer''')

    # ##################################################################

    validator.conf('confluence_parent_page_id_check') \
             .int_(positive=True)

    # ##################################################################

    # confluence_page_hierarchy
    validator.conf('confluence_page_hierarchy') \
             .bool()

    # ##################################################################

    # confluence_page_generation_notice
    validator.conf('confluence_page_generation_notice') \
             .bool()

    # ##################################################################

    # confluence_prev_next_buttons_location
    try:
        validator.conf('confluence_prev_next_buttons_location') \
                 .matching('bottom', 'both', 'top')
    except ConfluenceConfigurationError as e:
        raise ConfluenceConfigurationError('''\
{msg}

The option 'confluence_prev_next_buttons_location' has been configured to enable
navigational buttons onto generated pages. Accepted values include 'bottom',
'both' and 'top'.
'''.format(msg=e))

    # ##################################################################

    # confluence_proxy
    validator.conf('confluence_proxy') \
             .string()

    # ##################################################################

    # confluence_publish_allowlist
    # confluence_publish_denylist
    publish_list_options = [
        'confluence_publish_allowlist',
        'confluence_publish_denylist',
    ]

    for option in publish_list_options:
        value = getattr(config, option)
        if not value:
            continue

        # if provided via command line, treat as a list
        def conf_translate(value):
            if option in config['overrides'] and isinstance(value, basestring):
                value = value.split(',')
            return value
        value = conf_translate(value)

        try:
            validator.conf(option, conf_translate) \
                     .string_or_strings()

            if isinstance(value, basestring):
                validator.docnames_from_file()
            else:
                validator.docnames()
        except ConfluenceConfigurationError as e:
            raise ConfluenceConfigurationError('''\
{msg}

The value type permitted for this publish list option can either be a list of
document names or a string pointing to a file containing documents. Document
names are relative to the documentation's source directory.
'''.format(msg=e))

    # ##################################################################

    validator.conf('confluence_publish_delay') \
             .float_(positive=True)

    # ##################################################################

    # confluence_publish_dryrun
    validator.conf('confluence_publish_dryrun') \
             .bool()

    # ##################################################################

    # confluence_publish_headers
    validator.conf('confluence_publish_headers') \
             .dict_str_str()

    # ##################################################################

    # confluence_publish_onlynew
    validator.conf('confluence_publish_onlynew') \
             .bool()

    # ##################################################################

    # confluence_publish_postfix
    validator.conf('confluence_publish_postfix') \
             .string()

    # ##################################################################

    # confluence_publish_prefix
    validator.conf('confluence_publish_prefix') \
             .string()

    # ##################################################################

    validator.conf('confluence_publish_root') \
             .int_(positive=True)

    # ##################################################################

    # confluence_publish_token
    validator.conf('confluence_publish_token') \
             .string()

    # ##################################################################

    # confluence_purge
    validator.conf('confluence_purge') \
             .bool()

    # ##################################################################

    # confluence_purge_from_root
    validator.conf('confluence_purge_from_root') \
             .bool()

    # ##################################################################

    # confluence_remove_title
    validator.conf('confluence_remove_title') \
             .bool()

    # ##################################################################

    # confluence_request_session_override
    validator.conf('confluence_request_session_override') \
             .callable_()

    # ##################################################################

    # confluence_secnumber_suffix
    validator.conf('confluence_secnumber_suffix') \
             .string()

    # ##################################################################

    # confluence_server_auth
    if config.confluence_server_auth is not None:
        if not issubclass(type(config.confluence_server_auth), AuthBase):
            raise ConfluenceConfigurationError('''\
confluence_server_auth is not an implementation of requests.auth.AuthBase

Providing a custom authentication for Requests requires an implementation that
inherits 'requests.auth.AuthBase'. For more information, please consult the
following:

    requests -- Authentication
    https://requests.readthedocs.io/en/latest/user/authentication/
''')

    # ##################################################################

    # confluence_server_cookies
    validator.conf('confluence_server_cookies') \
             .dict_str_str()

    # ##################################################################

    # confluence_server_pass
    validator.conf('confluence_server_pass') \
             .string()

    # ##################################################################

    # confluence_server_url
    validator.conf('confluence_server_url') \
             .string()

    # ##################################################################

    # confluence_server_user
    validator.conf('confluence_server_user') \
             .string()

    # ##################################################################

    # confluence_sourcelink
    validator.conf('confluence_sourcelink') \
             .dict_str_str()

    if config.confluence_sourcelink:
        sourcelink = config.confluence_sourcelink

        # check if a supported template type is provided
        supported_types = [
            'bitbucket',
            'github',
            'gitlab',
        ]
        if 'type' in sourcelink:
            if sourcelink['type'] not in supported_types:
                raise ConfluenceConfigurationError('''\
unsupported type provided in confluence_sourcelink

The following types are supported:

 - {}
'''.format('\n - '.join(supported_types)))

            # ensure requires options are set
            required = [
                'owner',
                'repo',
                'version',
            ]
            if not all(k in sourcelink for k in required):
                raise ConfluenceConfigurationError('''\
required option missing in confluence_sourcelink

The following options are required for the provided template type:

 - {}
'''.format('\n - '.join(required)))

        # if not using a template type, ensure url is set
        elif 'url' not in sourcelink or not sourcelink['url']:
            raise ConfluenceConfigurationError('''\
url option is not set in confluence_sourcelink

If a template type is not being configured for a source link,
the `url` field must be configured.
''')

        reserved = [
            'page',
            'suffix',
        ]
        if any(k in sourcelink for k in reserved):
            raise ConfluenceConfigurationError('''\
reserved option set in confluence_sourcelink

The following options are reserved with confluence_sourcelink
and cannot be set:

 - {}
'''.format('\n - '.join(reserved)))

    # ##################################################################

    # confluence_space_key
    validator.conf('confluence_space_key') \
             .string()

    # ##################################################################

    # confluence_title_overrides
    validator.conf('confluence_title_overrides') \
             .dict_str_str()

    # ##################################################################

    # confluence_timeout
    try:
        validator.conf('confluence_timeout') \
                 .int_()
    except ConfluenceConfigurationError as e:
        raise ConfluenceConfigurationError('''\
{msg}

A configured timeout should be set to a duration, in seconds, before any network
request to timeout after inactivity. This should be set to a positive integer
value (e.g. 2).
'''.format(msg=e))

    # ##################################################################

    # confluence_use_index
    validator.conf('confluence_use_index') \
             .bool()

    # ##################################################################

    # confluence_version_comment
    validator.conf('confluence_version_comment') \
             .string()

    # ##################################################################

    # confluence_watch
    validator.conf('confluence_watch') \
             .bool()

    # ##################################################################

    if config.confluence_publish:
        if not config.confluence_server_url:
            raise ConfluenceConfigurationError('''\
confluence server url not provided

While publishing has been configured using 'confluence_publish', the Confluence
server URL has not. Ensure 'confluence_server_url' has been set to target
Confluence instance to be published to.
''')

        if not config.confluence_space_key and not config.confluence_space_name:
            raise ConfluenceConfigurationError('''\
confluence space key not provided

While publishing has been configured using 'confluence_publish', the Confluence
space key has not. Ensure 'confluence_space_key' has been set to space's key
which content should be published under.
''')

        if (config.confluence_ask_password and not config.confluence_server_user
                and not config.confluence_ask_user):
            raise ConfluenceConfigurationError('''\
confluence username not provided

A publishing password has been flagged with 'confluence_ask_password';
however, no username has been configured. Ensure 'confluence_server_user' is
properly set with the publisher's Confluence username or have
'confluence_ask_user' set to provide a username.
''')

        if config.confluence_server_pass:
            if not config.confluence_server_user:
                raise ConfluenceConfigurationError('''\
confluence username not provided

A publishing password has been configured with 'confluence_server_pass';
however, no username has been configured. Ensure 'confluence_server_user' is
properly set with the publisher's Confluence username.
''')

        if config.confluence_parent_page_id_check:
            if not config.confluence_parent_page:
                raise ConfluenceConfigurationError('''\
parent page (holder) name not set

When a parent page identifier check has been configured with the option
'confluence_parent_page_id_check', no parent page name has been provided with
the 'confluence_parent_page' option. Ensure the name of the parent page name
is provided as well.
''')

        if config.confluence_publish_root:
            if config.confluence_parent_page:
                raise ConfluenceConfigurationError('''\
conflicting publish point configurations

When configuring for a publishing container, a user can configure for either
'confluence_parent_page' or 'confluence_publish_root'; however, both cannot be
configured at the same time.
''')

    # ##################################################################

    # singleconfluence_toctree
    validator.conf('singleconfluence_toctree') \
             .bool()

    # ##################################################################

    # inform users of additional configuration information
    deprecated(validator)
    warnings(validator)
Пример #16
0
def validate_configuration(builder):
    """
    validate a builder's configuration state

    This call will check if the provided builder's configuration has any issues
    with the existing configuration. For errors in the existing configuration,
    an `ConfluenceConfigurationError` exception will be thrown.

    In addition to errors, this call will also generate warning messages on
    other configuration issues such as deprecated configurations.

    Args:
        builder: the builder state to validate a configuration on
    """

    config = builder.config
    env = builder.app.env
    validator = ConfigurationValidation(builder)

    # ##################################################################

    # confluence_add_secnumbers
    validator.conf('confluence_add_secnumbers') \
             .bool()

    # ##################################################################

    # confluence_additional_mime_types
    validator.conf('confluence_additional_mime_types') \
             .strings(no_space=True)

    # ##################################################################

    # confluence_adv_aggressive_search
    validator.conf('confluence_adv_aggressive_search') \
             .bool()

    # ##################################################################

    # confluence_adv_hierarchy_child_macro
    validator.conf('confluence_adv_hierarchy_child_macro') \
             .bool()

    # ##################################################################

    # confluence_adv_trace_data
    validator.conf('confluence_adv_trace_data') \
             .bool()

    # ##################################################################

    # confluence_adv_writer_no_section_cap
    validator.conf('confluence_adv_writer_no_section_cap') \
             .bool()

    # ##################################################################

    # confluence_ask_password
    validator.conf('confluence_ask_password') \
             .bool()

    # ##################################################################

    # confluence_ask_user
    validator.conf('confluence_ask_user') \
             .bool()

    # ##################################################################

    # confluence_asset_force_standalone
    validator.conf('confluence_asset_force_standalone') \
             .bool()

    # ##################################################################

    validator.conf('confluence_ca_cert') \
             .file()

    # ##################################################################

    if config.confluence_client_cert is not None:
        client_cert = config.confluence_client_cert
        if isinstance(client_cert, tuple):
            cert_files = client_cert
        else:
            cert_files = (client_cert, None)

        if len(cert_files) != 2:
            raise ConfluenceConfigurationError(
"""confluence_client_cert is not a 2-tuple

The option 'confluence_client_cert' has been provided but there are too many
values. The client certificate can either be a file/path which defines a
certificate/key-pair, or a 2-tuple of the certificate and key.
""")

        for cert in cert_files:
            if cert and not os.path.isfile(os.path.join(env.srcdir, cert)):
                raise ConfluenceConfigurationError(
"""confluence_ca_cert missing certificate file

The option 'confluence_client_cert' has been provided to find a client
certificate file from a relative location, but the certificate could not be
found. Ensure the following file exists:

    %s

""" % cert)

    # ##################################################################

    # confluence_client_cert_pass
    validator.conf('confluence_client_cert_pass') \
             .string()

    # ##################################################################

    # confluence_default_alignment
    try:
        validator.conf('confluence_default_alignment') \
                 .matching('left', 'center', 'right')
    except ConfluenceConfigurationError as e:
        raise ConfluenceConfigurationError(
"""%s

The option 'confluence_default_alignment' has been provided to override the
default alignment for tables, figures, etc. Accepted values include 'left',
'center' and 'right'.
""" % str(e))

    # ##################################################################

    # confluence_disable_autogen_title
    validator.conf('confluence_disable_autogen_title') \
             .bool()

    # ##################################################################

    # confluence_disable_notifications
    validator.conf('confluence_disable_notifications') \
             .bool()

    # ##################################################################

    # confluence_disable_ssl_validation
    validator.conf('confluence_disable_ssl_validation') \
             .bool()

    # ##################################################################

    # confluence_file_suffix
    validator.conf('confluence_file_suffix') \
             .string()

    # ##################################################################

    # confluence_file_transform
    validator.conf('confluence_file_transform') \
             .callable_()

    # ##################################################################

    # confluence_footer_file
    try:
        validator.conf('confluence_footer_file') \
                 .string() \
                 .file()
    except ConfluenceConfigurationError as e:
        raise ConfluenceConfigurationError(
"""%s

The option 'confluence_footer_file' has been provided to find a footer template
file from a path relative to the documentation source. Ensure the value is set
to a proper file path.
""" % str(e))

    # ##################################################################

    # confluence_global_labels
    try:
        validator.conf('confluence_global_labels') \
                 .strings(no_space=True)
    except ConfluenceConfigurationError as e:
        raise ConfluenceConfigurationError(
"""%s

The option 'confluence_global_labels' can provide a collection to string values
to use as labels for published documentation. Each label value must be a string
that contains no spaces.
""" % str(e))

    # ##################################################################

    # confluence_header_file
    try:
        validator.conf('confluence_header_file') \
                 .string() \
                 .file()
    except ConfluenceConfigurationError as e:
        raise ConfluenceConfigurationError(
"""%s

The option 'confluence_header_file' has been provided to find a header template
file from a path relative to the documentation source. Ensure the value is set
to a proper file path.
""" % str(e))

    # ##################################################################

    # confluence_ignore_titlefix_on_index
    validator.conf('confluence_ignore_titlefix_on_index') \
             .bool()

    # ##################################################################

    # confluence_jira_servers
    if config.confluence_jira_servers is not None:
        issue = False
        jira_servers = config.confluence_jira_servers

        if not isinstance(jira_servers, dict):
            issue = True
        else:
            for name, info in jira_servers.items():
                if not isinstance(name, basestring):
                    issue = True
                    break

                if not isinstance(info, dict):
                    issue = True
                    break

                jira_id = info.get('id')
                jira_name = info.get('name')

                if not (isinstance(jira_id, basestring) and
                        isinstance(jira_name, basestring)):
                    issue = True
                    break

        if issue:
            raise ConfluenceConfigurationError(
"""confluence_jira_servers is not properly formed

JIRA server definitions should be a dictionary of string keys which contain
dictionaries with keys 'id' and 'name' which identify the JIRA instances.
""")

    # ##################################################################

    # confluence_lang_transform
    validator.conf('confluence_lang_transform') \
             .callable_()

    # ##################################################################

    # confluence_link_suffix
    validator.conf('confluence_link_suffix') \
             .string()

    # ##################################################################

    # confluence_link_transform
    validator.conf('confluence_link_transform') \
             .callable_()

    # ##################################################################

    # confluence_master_homepage
    validator.conf('confluence_master_homepage') \
             .bool()

    # ##################################################################

    # confluence_max_doc_depth
    try:
        validator.conf('confluence_max_doc_depth') \
                 .int_()
    except ConfluenceConfigurationError as e:
        raise ConfluenceConfigurationError(
"""%s

When limiting the document depth permitted for a building/publishing event, the
defined maximum document depth must be defined as a non-negative integer value.

If planning to use a depth of zero, it is recommended to use the
'singleconfluence' builder instead.
""" % str(e))

    # ##################################################################

    validator.conf('confluence_parent_page') \
             .string()

    # ##################################################################

    validator.conf('confluence_parent_page_id_check') \
             .int_(positive=True)

    # ##################################################################

    # confluence_page_hierarchy
    validator.conf('confluence_page_hierarchy') \
             .bool()

    # ##################################################################

    # confluence_prev_next_buttons_location
    try:
        validator.conf('confluence_prev_next_buttons_location') \
                 .matching('bottom', 'both', 'top')
    except ConfluenceConfigurationError as e:
        raise ConfluenceConfigurationError(
"""%s

The option 'confluence_prev_next_buttons_location' has been configured to enable
navigational buttons onto generated pages. Accepted values include 'bottom',
'both' and 'top'.
""" % str(e))

    # ##################################################################

    # confluence_proxy
    validator.conf('confluence_proxy') \
             .string()

    # ##################################################################

    # confluence_publish_allowlist
    # confluence_publish_denylist
    publish_list_options = [
        'confluence_publish_allowlist',
        'confluence_publish_denylist',
    ]

    for option in publish_list_options:
        value = getattr(config, option)
        if not value:
            continue

        # if provided via command line, treat as a list
        def conf_translate(value):
            if option in config['overrides'] and isinstance(value, basestring):
                value = value.split(',')
            return value
        value = conf_translate(value)

        try:
            validator.conf(option, conf_translate) \
                     .string_or_strings()

            if isinstance(value, basestring):
                validator.docnames_from_file()
            else:
                validator.docnames()
        except ConfluenceConfigurationError as e:
            raise ConfluenceConfigurationError(
"""%s

The value type permitted for this publish list option can either be a list of
document names or a string pointing to a file containing documents. Document
names are relative to the documentation's source directory.
""" % str(e))

    # ##################################################################

    # confluence_publish_dryrun
    validator.conf('confluence_publish_dryrun') \
             .bool()

    # ##################################################################

    # confluence_publish_onlynew
    validator.conf('confluence_publish_onlynew') \
             .bool()

    # ##################################################################

    # confluence_publish_postfix
    validator.conf('confluence_publish_postfix') \
             .string()

    # ##################################################################

    # confluence_publish_prefix
    validator.conf('confluence_publish_prefix') \
             .string()

    # ##################################################################

    # confluence_purge
    validator.conf('confluence_purge') \
             .bool()

    # ##################################################################

    # confluence_purge_from_master
    validator.conf('confluence_purge_from_master') \
             .bool()

    # ##################################################################

    # confluence_remove_title
    validator.conf('confluence_remove_title') \
             .bool()

    # ##################################################################

    # confluence_secnumber_suffix
    validator.conf('confluence_secnumber_suffix') \
             .string(permit_empty=True)

    # ##################################################################

    # confluence_server_auth
    if config.confluence_server_auth is not None:
        if not issubclass(type(config.confluence_server_auth), AuthBase):
            raise ConfluenceConfigurationError(
"""confluence_server_auth is not an implementation of requests.auth.AuthBase

Providing a custom authentication for Requests requires an implementation that
inherits 'requests.auth.AuthBase'. For more information, please consult the
following:

    requests -- Authentication
    https://requests.readthedocs.io/en/latest/user/authentication/
""")

    # ##################################################################

    # confluence_server_cookies
    validator.conf('confluence_server_cookies') \
             .dict_str_str()

    # ##################################################################

    # confluence_server_pass
    validator.conf('confluence_server_pass') \
             .string()

    # ##################################################################

    # confluence_server_url
    validator.conf('confluence_server_url') \
             .string()

    # ##################################################################

    # confluence_server_user
    validator.conf('confluence_server_user') \
             .string()

    # ##################################################################

    # confluence_space_name
    validator.conf('confluence_space_name') \
             .string()

    # ##################################################################

    # confluence_title_overrides
    validator.conf('confluence_title_overrides') \
             .dict_str_str()

    # ##################################################################

    # confluence_timeout
    try:
        validator.conf('confluence_timeout') \
                 .int_()
    except ConfluenceConfigurationError as e:
        raise ConfluenceConfigurationError(
"""%s

A configured timeout should be set to a value, in seconds, before any network
request to timeout after inactivity. This should be set to a positive integer
value (e.g. 2).
""" % str(e))

    # ##################################################################

    # confluence_watch
    validator.conf('confluence_watch') \
             .bool()

    # ##################################################################

    if config.confluence_publish:
        if not config.confluence_server_url:
            raise ConfluenceConfigurationError(
"""confluence server url not provided

While publishing has been configured using 'confluence_publish', the Confluence
server URL has not. Ensure 'confluence_server_url' has been set to target
Confluence instance to be published to.
""")

        if not config.confluence_space_name:
            raise ConfluenceConfigurationError(
"""confluence space name not provided

While publishing has been configured using 'confluence_publish', the Confluence
space name has not. Ensure 'confluence_space_name' has been set to space's name
which content should be published under.
""")

        if (config.confluence_ask_password and not config.confluence_server_user
                and not config.confluence_ask_user):
            raise ConfluenceConfigurationError(
"""confluence username not provided

A publishing password has been flagged with 'confluence_ask_password';
however, no username has been configured. Ensure 'confluence_server_user' is
properly set with the publisher's Confluence username or have
'confluence_ask_user' set to provide a username.
""")

        if config.confluence_server_pass:
            if not config.confluence_server_user:
                raise ConfluenceConfigurationError(
"""confluence username not provided

A publishing password has been configured with 'confluence_server_pass';
however, no username has been configured. Ensure 'confluence_server_user' is
properly set with the publisher's Confluence username.
""")

        if config.confluence_parent_page_id_check:
            if not config.confluence_parent_page:
                raise ConfluenceConfigurationError(
"""parent page (holder) name not set

When a parent page identifier check has been configured with the option
'confluence_parent_page_id_check', no parent page name has been provided with
the 'confluence_parent_page' option. Ensure the name of the parent page name
is provided as well.
""")

    # ##################################################################

    # inform users of aadditional configuration information
    deprecated(validator)
    warnings(validator)
Пример #17
0
    def init(self, suppress_conf_check=False):
        if not ConfluenceConfig.validate(self, not suppress_conf_check):
            raise ConfluenceConfigurationError('configuration error')
        config = self.config

        if self.config.confluence_publish:
            if self.config.confluence_ask_user:
                print('(request to accept username from interactive session)')
                print(' Instance: ' + self.config.confluence_server_url)

                default_user = self.config.confluence_server_user
                u_str = ''
                if default_user:
                    u_str = ' [{}]'.format(default_user)

                target_user = input(' User{}: '.format(u_str)) or default_user
                if not target_user:
                    raise ConfluenceConfigurationError('no user provided')

                self.config.confluence_server_user = target_user

            if self.config.confluence_ask_password:
                print('(request to accept password from interactive session)')
                if not self.config.confluence_ask_user:
                    print(' Instance: ' + self.config.confluence_server_url)
                    print('     User: '******' Password: '******'')
                if not self.config.confluence_server_pass:
                    raise ConfluenceConfigurationError('no password provided')

        self.assets = ConfluenceAssetManager(self.config.master_doc, self.env,
                                             self.outdir)
        self.writer = ConfluenceWriter(self)
        self.config.sphinx_verbosity = self.app.verbosity
        self.publisher.init(self.config)

        old_url = self.config.confluence_server_url
        new_url = ConfluenceUtil.normalizeBaseUrl(old_url)
        if old_url != new_url:
            ConfluenceLogger.warn('normalizing confluence url from '
                                  '{} to {} '.format(old_url, new_url))
            self.config.confluence_server_url = new_url

        # detect if Confluence Cloud if using the Atlassian domain
        if new_url:
            self.cloud = new_url.endswith('.atlassian.net/wiki/')

        if self.config.confluence_file_suffix is not None:
            self.file_suffix = self.config.confluence_file_suffix
        if self.config.confluence_link_suffix is not None:
            self.link_suffix = self.config.confluence_link_suffix
        elif self.link_suffix is None:
            self.link_suffix = self.file_suffix

        # Function to convert the docname to a reST file name.
        def file_transform(docname):
            return docname + self.file_suffix

        # Function to convert the docname to a relative URI.
        def link_transform(docname):
            return docname + self.link_suffix

        self.prev_next_loc = self.config.confluence_prev_next_buttons_location

        if self.config.confluence_file_transform is not None:
            self.file_transform = self.config.confluence_file_transform
        else:
            self.file_transform = file_transform
        if self.config.confluence_link_transform is not None:
            self.link_transform = self.config.confluence_link_transform
        else:
            self.link_transform = link_transform

        if self.config.confluence_lang_transform is not None:
            self.lang_transform = self.config.confluence_lang_transform
        else:
            self.lang_transform = None

        if self.config.confluence_publish:
            self.publish = True
            self.publisher.connect()
        else:
            self.publish = False

        if self.config.confluence_space_name is not None:
            self.space_name = self.config.confluence_space_name
        else:
            self.space_name = None

        def prepare_subset(option):
            value = getattr(config, option)
            if value is None:
                return None

            # if provided via command line, treat as a list
            if option in config['overrides']:
                value = value.split(',')

            if isinstance(value, basestring):
                files = extract_strings_from_file(value)
            else:
                files = value

            return set(files) if files else None

        self.publish_allowlist = prepare_subset('confluence_publish_allowlist')
        self.publish_denylist = prepare_subset('confluence_publish_denylist')