예제 #1
0
    def section(self: T, section: Union[str, "Section"]) -> T:
        """Creates a section block

        Args:
            section (str or :class:`Section`): name of section or object

        Returns:
            self for chaining
        """
        from .document import Document
        from .section import Section

        container = self._container
        if not isinstance(container, Document):
            raise ValueError("Sections can only be added at section level!")

        if isinstance(section, str):
            # create a new section
            section = Section(section)
        elif not isinstance(section, Section):
            msg = "Parameter must be a string or Section type!"
            raise ValueError(msg, {"container": section})

        if container.has_section(section.name):
            raise DuplicateSectionError(section.name)

        section.attach(container)
        return self._insert(section)
예제 #2
0
 def ns_sections(self, ns):
     ns = ns.strip()
     ns_sects = OrderedDict() # { id: str(section) }
     for s in self._config.sections():
         mat = _reNamespacedSection.match(s)
         if mat is None:
             continue
         if mat.group('ns') != ns:
             continue
         id_ = mat.group('id')
         if id_ in ns_sects:
             raise DuplicateSectionError("%s:%s" % (ns, id_))
         ns_sects[id_] = s
     return [ (id_, s) for id_, s in ns_sects.items() ] # [ (id, str(section)) ]
예제 #3
0
    def add_section(self, section, comment=None):
        """
        Add a section

        :param str section: Section to add
        :raise DuplicateSectionError: if section already exist.
        """
        self._read_sources()

        if self._to_dot_key(section) in self._dot_keys:
            raise DuplicateSectionError(section)

        self._parser.add_section(section)
        self._add_dot_key(section)
        if comment:
            self._set_comment(section, comment)
예제 #4
0
    def add_section(self, section):
        """Create a new section in the configuration.

        Raise DuplicateSectionError if a section by the specified name
        already exists.  Raise ValueError if name is DEFAULT or any of
        its case-insensitive variants.
        """
        # The default section is the only one that gets the case-insensitive
        # treatment - so it is special-cased here.
        if section.lower() == "default":
            raise ValueError('Invalid section name: %s' % section)

        if self.has_section(section):
            raise DuplicateSectionError(section)
        else:
            self.data._new_namespace(section)
예제 #5
0
    def add_section(self, section):
        """Create a new section in the configuration.

        Raise DuplicateSectionError if a section by the specified name
        already exists. Raise ValueError if name is DEFAULT.

        Args:
            section (str or :class:`Section`): name or Section type
        """
        if section in self.sections():
            raise DuplicateSectionError(section)
        if isinstance(section, str):
            # create a new section
            section = Section(section, container=self)
        elif not isinstance(section, Section):
            raise ValueError("Parameter must be a string or Section type!")
        self._structure.append(section)
예제 #6
0
	def add_section(self, section: Union[str, Section]):
		"""Create a new section in the configuration.

		:raises: :exc:`~.DuplicateSectionError` if a section by the specified name already exists.
		:raises: :exc:`ValueError` if name is ``DEFAULT``.

		:param section:
		"""

		if section in self.sections():
			raise DuplicateSectionError(section)  # type: ignore

		if isinstance(section, str):
			# create a new section
			section = Section(section, container=self)
		elif not isinstance(section, Section):
			raise ValueError("Parameter must be a string or Section type!")
		self._structure.append(section)
예제 #7
0
    def section(self, section):
        """Creates a section block

        Args:
            section (str or :class:`Section`): name of section or object

        Returns:
            self for chaining
        """
        if not isinstance(self._container, ConfigUpdater):
            raise ValueError("Sections can only be added at section level!")
        if isinstance(section, str):
            # create a new section
            section = Section(section, container=self._container)
        elif not isinstance(section, Section):
            raise ValueError("Parameter must be a string or Section type!")
        if section.name in [block.name for block in self._container
                            if isinstance(block, Section)]:
            raise DuplicateSectionError(section.name)
        self._container.structure.insert(self._idx, section)
        self._idx += 1
        return self
예제 #8
0
    def add_section(self, section: Union[str, Section]):
        """Create a new section in the configuration.

        Raise DuplicateSectionError if a section by the specified name
        already exists. Raise ValueError if name is DEFAULT.

        Args:
            section (str or :class:`Section`): name or Section type
        """
        if isinstance(section, str):
            # create a new section
            section_obj = Section(section)
        elif isinstance(section, Section):
            section_obj = section
        else:
            raise ValueError("Parameter must be a string or Section type!")

        if self.has_section(section_obj.name):
            raise DuplicateSectionError(section_obj.name)

        section_obj.attach(self)
        self._structure.append(section_obj)
예제 #9
0
	def section(self, section: Union[str, "Section"]) -> "BlockBuilder":
		"""
		Creates a section block.

		:param section: name of section or object.

		:returns: self for chaining.
		"""

		if not isinstance(self._container, ConfigUpdater):
			raise ValueError("Sections can only be added at section level!")

		if isinstance(section, str):
			# create a new section
			section = Section(section, container=self._container)
		elif not isinstance(section, Section):
			raise ValueError("Parameter must be a string or Section type!")

		if section.name in [block.name for block in self._container if isinstance(block, Section)]:
			raise DuplicateSectionError(section.name)

		self._container.structure.insert(self._idx, section)
		self._idx += 1
		return self
예제 #10
0
    def add_section(self, section):
        if section in self.values:
            raise DuplicateSectionError(section)

        self.values[section] = {}
예제 #11
0
    def _read(self, fp, fpname):
        """Parse a sectioned configuration file.

        Each section in a configuration file contains a header, indicated by
        a name in square brackets (`[]`), plus key/value options, indicated by
        `name` and `value` delimited with a specific substring (`=` or `:` by
        default).

        Values can span multiple lines, as long as they are indented deeper
        than the first line of the value. Depending on the parser's mode, blank
        lines may be treated as parts of multiline values or ignored.

        Configuration files may include comments, prefixed by specific
        characters (`#` and `;` by default). Comments may appear on their own
        in an otherwise empty line or may be entered in lines holding values or
        section names.

        Note: This method was borrowed from ConfigParser and we keep this
        mess here as close as possible to the original messod (pardon
        this german pun) for consistency reasons and later upgrades.
        """
        self._structure = []
        elements_added = set()
        cursect = None  # None, or a dictionary
        sectname = None
        optname = None
        lineno = 0
        indent_level = 0
        e = None  # None, or an exception
        for lineno, line in enumerate(fp, start=1):
            comment_start = sys.maxsize
            # strip inline comments
            inline_prefixes = {p: -1 for p in self._inline_comment_prefixes}
            while comment_start == sys.maxsize and inline_prefixes:
                next_prefixes = {}
                for prefix, index in inline_prefixes.items():
                    index = line.find(prefix, index + 1)
                    if index == -1:
                        continue
                    next_prefixes[prefix] = index
                    if index == 0 or (index > 0 and line[index - 1].isspace()):
                        comment_start = min(comment_start, index)
                inline_prefixes = next_prefixes
            # strip full line comments
            for prefix in self._comment_prefixes:
                if line.strip().startswith(prefix):
                    comment_start = 0
                    self._add_comment(line)  # HOOK
                    break
            if comment_start == sys.maxsize:
                comment_start = None
            value = line[:comment_start].strip()
            if not value:
                if self._empty_lines_in_values:
                    # add empty line to the value, but only if there was no
                    # comment on the line
                    if (comment_start is None and cursect is not None
                            and optname and cursect[optname] is not None):
                        cursect[optname].append('')  # newlines added at join
                        self.last_item.last_item.add_line(line)  # HOOK
                else:
                    # empty line marks end of value
                    indent_level = sys.maxsize
                if comment_start is None:
                    self._add_space(line)
                continue
            # continuation line?
            first_nonspace = self.NONSPACECRE.search(line)
            cur_indent_level = first_nonspace.start() if first_nonspace else 0
            if (cursect is not None and optname
                    and cur_indent_level > indent_level):
                cursect[optname].append(value)
                self.last_item.last_item.add_line(line)  # HOOK
            # a section header or option header?
            else:
                indent_level = cur_indent_level
                # is it a section header?
                mo = self.SECTCRE.match(value)
                if mo:
                    sectname = mo.group('header')
                    if sectname in self._sections:
                        if self._strict and sectname in elements_added:
                            raise DuplicateSectionError(
                                sectname, fpname, lineno)
                        cursect = self._sections[sectname]
                        elements_added.add(sectname)
                    else:
                        cursect = self._dict()
                        self._sections[sectname] = cursect
                        elements_added.add(sectname)
                    # So sections can't start with a continuation line
                    optname = None
                    self._add_section(sectname, line)  # HOOK
                # no section header in the file?
                elif cursect is None:
                    raise MissingSectionHeaderError(fpname, lineno, line)
                # an option line?
                else:
                    mo = self._optcre.match(value)
                    if mo:
                        optname, vi, optval = mo.group('option', 'vi', 'value')
                        if not optname:
                            e = self._handle_error(e, fpname, lineno, line)
                        optname = self.optionxform(optname.rstrip())
                        if (self._strict
                                and (sectname, optname) in elements_added):
                            raise DuplicateOptionError(sectname, optname,
                                                       fpname, lineno)
                        elements_added.add((sectname, optname))
                        # This check is fine because the OPTCRE cannot
                        # match if it would set optval to None
                        if optval is not None:
                            optval = optval.strip()
                            cursect[optname] = [optval]
                        else:
                            # valueless option handling
                            cursect[optname] = None
                        self._add_option(optname, vi, optval, line)  # HOOK
                    else:
                        # a non-fatal parsing error occurred. set up the
                        # exception but keep going. the exception will be
                        # raised at the end of the file and will contain a
                        # list of all bogus lines
                        e = self._handle_error(e, fpname, lineno, line)
        # if any parsing errors occurred, raise an exception
        if e:
            raise e
예제 #12
0
    def _do_read_config(self, config_file, pommanipext):
        """Reads config for a single job defined by section."""
        parser = InterpolationConfigParser()
        dataset = parser.read(config_file)
        if config_file not in dataset:
            raise IOError("Config file %s not found." % config_file)
        if parser.has_option('common', 'include'):
            include = parser.get('common', 'include')
            if include is not "":
                sections_ = self.read_and_load(include)
                for section_ in sections_:
                    if parser.has_section(section_):
                        raise DuplicateSectionError(
                            "The config section [%s] is existed in %s and include %s cfg file"
                            % (section_, config_file,
                               re.split("\\s+", include.strip())[1]))
                parser._sections.update(sections_)

        pom_manipulator_config = {}
        common_section = {}
        package_configs = {}

        if pommanipext and pommanipext != '' and pommanipext != 'None':  #TODO ref: remove none check, it is passed over cmd line in jenkins build
            parse_pom_manipulator_ext(pom_manipulator_config, parser,
                                      pommanipext)

        if not parser.has_section('common'):
            logging.error(
                'Mandatory common section missing from configuration file.')
            raise NoSectionError(
                'Mandatory common section missing from configuration file.')
        common_section['tag'] = parser.get('common', 'tag')
        common_section['target'] = parser.get('common', 'target')
        common_section['jobprefix'] = parser.get('common', 'jobprefix')
        common_section['jobciprefix'] = parser.get('common', 'jobciprefix')
        common_section['jobjdk'] = parser.get('common', 'jobjdk')
        if parser.has_option('common', 'mvnver'):
            common_section['mvnver'] = parser.get('common', 'mvnver')
        if parser.has_option('common', 'skiptests'):
            common_section['skiptests'] = parser.get('common', 'skiptests')
        if parser.has_option('common', 'base'):
            common_section['base'] = parser.get('common', 'base')
        if parser.has_option('common', 'citemplate'):
            common_section['citemplate'] = parser.get('common', 'citemplate')
        if parser.has_option('common', 'jenkinstemplate'):
            common_section['jenkinstemplate'] = parser.get(
                'common', 'jenkinstemplate')
        if parser.has_option('common', 'product_name'):
            common_section['product_name'] = parser.get(
                'common', 'product_name')

        if parser.has_option('common', 'include'):
            common_section['include'] = parser.get('common', 'include')

        common_section['jobfailureemail'] = parser.get('common',
                                                       'jobfailureemail')

        config_dir = utils.get_dir(config_file)

        #Jira
        if parser.has_option('common', 'shared_config') and parser.get(
                'common', 'shared_config') is not "":
            parse_shared_config(common_section, config_dir, parser)

        common_section['jobtimeout'] = parser.getint('common', 'jobtimeout')

        common_section['options'] = {}
        # If the configuration file has global properties insert these into the common properties map.
        # These may be overridden later by particular properties.
        if parser.has_option('common', 'globalproperties'):
            common_section['options']['properties'] = dict(
                x.strip().split('=')
                for x in parser.get('common', 'globalproperties').replace(
                    ",\n", ",").split(','))
        else:
            # Always ensure properties has a valid dictionary so code below doesn't need multiple checks.
            common_section['options']['properties'] = {}
        # The same for global profiles
        if parser.has_option('common', 'globalprofiles'):
            common_section['options']['profiles'] = [
                x.strip()
                for x in parser.get('common', 'globalprofiles').split(',')
            ]
        else:
            # Always ensure profiles has a valid list so code below doesn't need multiple checks.
            common_section['options']['profiles'] = []

        if os.path.dirname(config_file):
            config_path = os.path.dirname(config_file)
        else:
            config_path = os.getcwd()
        logging.info("Configuration file is %s and path %s",
                     os.path.basename(config_file), config_path)

        for section in parser.sections():
            config_type = self.read_config_type(parser, section)
            if section == 'common' or config_type == "bom-builder-meta":
                logging.debug('Skipping section due to meta-type %s', section)
                continue

            self._do_read_section(config_path, os.path.basename(config_file),
                                  package_configs, parser, section)

        return (common_section, package_configs, pom_manipulator_config)
예제 #13
0
 def sidey(name, engine, overwrite=False):
     if not overwrite:
         raise DuplicateSectionError('boom')
예제 #14
0
    def _read(self, fp, fpname):
        """Parse a sectioned configuration file.

        Each section in a configuration file contains a header, indicated by
        a name in square brackets (`[]'), plus key/value options, indicated by
        `name' and `value' delimited with a specific substring (`=' or `:' by
        default).

        Values can span multiple lines, as long as they are indented deeper
        than the first line of the value. Depending on the parser's mode, blank
        lines may be treated as parts of multiline values or ignored.

        Configuration files may include comments, prefixed by specific
        characters (`#' and `;' by default). Comments may appear on their own
        in an otherwise empty line or may be entered in lines holding values or
        section names.

        This implementation is extended from the original to also accept

        .. code:: ini

          #include <file or pisa_resource>

        or

        .. code:: ini

          #include <file or pisa_resource> as <section_name>

        syntax anywhere in the file, which switches (via
        :class:`MutableMultiFileIterator`) to the new file as if it were
        in-lined within the original file. The latter syntax also prepends a
        section header

        .. code:: ini

            [section_name]

        before the text of the specified file or pisa_resource.

        """
        elements_added = set()
        cursect = None  # None, or a dictionary
        sectname = None
        optname = None
        lineno = 0
        indent_level = 0
        e = None  # None, or an exception

        file_iter = MutableMultiFileIterator(fp=fp, fpname=fpname)
        self.file_iterators.append(file_iter)
        for record in file_iter:
            fpname = record['fpname']
            lineno = record['lineno']
            line = record['line']

            comment_start = sys.maxsize
            # strip inline comments
            inline_prefixes = dict(
                (p, -1) for p in self._inline_comment_prefixes)
            while comment_start == sys.maxsize and inline_prefixes:
                next_prefixes = {}
                for prefix, index in inline_prefixes.items():
                    index = line.find(prefix, index + 1)
                    if index == -1:
                        continue
                    next_prefixes[prefix] = index
                    if index == 0 or (index > 0 and line[index - 1].isspace()):
                        comment_start = min(comment_start, index)
                inline_prefixes = next_prefixes
            # parse #include statement
            include_info = self._get_include_info(line)
            if include_info:
                file_iter.switch_to_file(fpname=include_info['file'])
                if include_info['as']:
                    as_header = '[%s]\n' % include_info['as']
                    file_iter.switch_to_file(
                        # Aaron Fienberg
                        # commented out as part of python3 update
                        # fp=StringIO(as_header.decode('utf-8'))
                        fp=StringIO(as_header))
                continue
            # strip full line comments
            for prefix in self._comment_prefixes:
                if line.strip().startswith(prefix):
                    comment_start = 0
                    break
            if comment_start == sys.maxsize:
                comment_start = None
            value = line[:comment_start].strip()
            if not value:
                if self._empty_lines_in_values:
                    # add empty line to the value, but only if there was no
                    # comment on the line
                    if (comment_start is None and cursect is not None
                            and optname and cursect[optname] is not None):
                        cursect[optname].append('')  # newlines added at join
                else:
                    # empty line marks end of value
                    indent_level = sys.maxsize
                continue
            # continuation line?
            first_nonspace = self.NONSPACECRE.search(line)
            cur_indent_level = first_nonspace.start() if first_nonspace else 0
            if (cursect is not None and optname
                    and cur_indent_level > indent_level):
                cursect[optname].append(value)
            # a section header or option header?
            else:
                indent_level = cur_indent_level
                # is it a section header?
                mo = self.SECTCRE.match(value)
                if mo:
                    sectname = mo.group('header')
                    if sectname in self._sections:
                        if self._strict and sectname in elements_added:
                            raise DuplicateSectionError(
                                sectname, fpname, lineno)
                        cursect = self._sections[sectname]
                        elements_added.add(sectname)
                    elif sectname == self.default_section:
                        cursect = self._defaults
                    else:
                        cursect = self._dict()
                        self._sections[sectname] = cursect
                        self._proxies[sectname] = SectionProxy(self, sectname)
                        elements_added.add(sectname)
                    # So sections can't start with a continuation line
                    optname = None
                # no section header in the file?
                elif cursect is None:
                    raise MissingSectionHeaderError(fpname, lineno, line)
                # an option line?
                else:
                    mo = self._optcre.match(value)
                    if mo:
                        optname, vi, optval = mo.group('option', 'vi', 'value')  # pylint: disable=unused-variable
                        if not optname:
                            e = self._handle_error(e, fpname, lineno, line)
                        optname = self.optionxform(optname.rstrip())
                        if (self._strict
                                and (sectname, optname) in elements_added):
                            raise DuplicateOptionError(sectname, optname,
                                                       fpname, lineno)
                        elements_added.add((sectname, optname))
                        # This check is fine because the OPTCRE cannot
                        # match if it would set optval to None
                        if optval is not None:
                            optval = optval.strip()
                            cursect[optname] = [optval]
                        else:
                            # valueless option handling
                            cursect[optname] = None
                    else:
                        # a non-fatal parsing error occurred. set up the
                        # exception but keep going. the exception will be
                        # raised at the end of the file and will contain a
                        # list of all bogus lines
                        e = self._handle_error(e, fpname, lineno, line)
        # if any parsing errors occurred, raise an exception
        if e:
            raise e
        self._join_multiline_values()
예제 #15
0
    def _read(self, fp, fpname):
        """Parse a sectioned configuration file.

        Each section in a configuration file contains a header, indicated by
        a name in square brackets (`[]'), plus key/value options, indicated by
        `name' and `value' delimited with a specific substring (`=' or `:' by
        default).

        Values can span multiple lines, as long as they are indented deeper
        than the first line of the value. Depending on the parser's mode, blank
        lines may be treated as parts of multiline values or ignored.

        Configuration files may include comments, prefixed by specific
        characters (`#' and `;' by default). Comments may appear on their own
        in an otherwise empty line or may be entered in lines holding values or
        section names.
        """
        elements_added = set()
        cursect = None  # None, or a dictionary
        sectname = None
        optname = None
        lineno = 0
        indent_level = 0
        e = None  # None, or an exception
        for lineno, line in enumerate(fp, start=1):
            comment_start = None
            # strip inline comments
            for prefix in self._inline_comment_prefixes:
                index = line.find(prefix)
                if index == 0 or (index > 0 and line[index - 1].isspace()):
                    comment_start = index
                    break
            # strip full line comments
            for prefix in self._comment_prefixes:
                if line.strip().startswith(prefix):
                    comment_start = 0
                    break
            value = line[:comment_start].strip()
            if not value:
                if self._empty_lines_in_values:
                    # add empty line to the value, but only if there was no
                    # comment on the line
                    if (comment_start is None and cursect is not None
                            and optname and cursect[optname] is not None):
                        cursect[optname].append('')  # newlines added at join
                else:
                    # empty line marks end of value
                    indent_level = sys.maxsize
                continue
            # continuation line?
            first_nonspace = self.NONSPACECRE.search(line)
            cur_indent_level = first_nonspace.start() if first_nonspace else 0
            if (cursect is not None and optname
                    and cur_indent_level > indent_level):
                cursect[optname].append(value)
            # a section header or option header?
            else:
                indent_level = cur_indent_level
                # is it a section header?
                mo = self.SECTCRE.match(value)
                if mo:
                    sectname = mo.group('header')
                    if sectname in self._sections:
                        if self._strict and sectname in elements_added:
                            raise DuplicateSectionError(
                                sectname, fpname, lineno)
                        cursect = self._sections[sectname]
                        elements_added.add(sectname)
                    elif sectname == self.default_section:
                        cursect = self._defaults
                    else:
                        cursect = self._dict()
                        self._sections[sectname] = cursect
                        self._proxies[sectname] = configparser.SectionProxy(
                            self, sectname)
                        elements_added.add(sectname)
                    # So sections can't start with a continuation line
                    optname = None
                # no section header in the file?
                elif cursect is None:
                    raise MissingSectionHeaderError(fpname, lineno, line)
                # an option line?
                else:
                    mo = self._optcre.match(value)
                    if mo:
                        optname, vi, optval = mo.group('option', 'vi', 'value')
                        if not optname:
                            e = self._handle_error(e, fpname, lineno, line)
                        optname = self.optionxform(optname.rstrip())
                        if (self._strict
                                and (sectname, optname) in elements_added):
                            raise configparser.DuplicateOptionError(
                                sectname, optname, fpname, lineno)
                        elements_added.add((sectname, optname))
                        # This check is fine because the OPTCRE cannot
                        # match if it would set optval to None
                        if optval is not None:
                            optval = optval.strip()
                            # Check if this optname already exists
                            if (optname in cursect) and (cursect[optname]
                                                         is not None):
                                # If it does, convert it to a tuple if it isn't already one
                                if not isinstance(cursect[optname], tuple):
                                    cursect[optname] = tuple(cursect[optname])
                                cursect[optname] = cursect[optname] + tuple(
                                    [optval])
                            else:
                                cursect[optname] = [optval]
                        else:
                            # valueless option handling
                            cursect[optname] = None
                    else:
                        # a non-fatal parsing error occurred. set up the
                        # exception but keep going. the exception will be
                        # raised at the end of the file and will contain a
                        # list of all bogus lines
                        e = self._handle_error(e, fpname, lineno, line)
        # if any parsing errors occurred, raise an exception
        if e:
            raise e
        self._join_multiline_values()
예제 #16
0
        path = os.path.dirname(
            os.path.realpath(__file__)) + "/../src/docstats/__main__.py"
        exec(compile(open(path).read(), path, "exec"), {},
             {"__name__": "__main__"})


def test_main_with_empty_args():
    with pytest.raises(DocoptExit):
        main([])


@pytest.mark.parametrize('error', [
    KeyboardInterrupt,
    FileNotFoundError,
    OSError,
    DuplicateSectionError('fake-sec'),
    DuplicateOptionError('fake-sec', 'fake-opt'),
])
@patch('docstats.main.parsecli')
def test_main_with_ctrl_c(mock_parsecli, error):
    mock_parsecli.side_effect = error
    result = main([])
    assert result


@patch('docstats.worker.work')
@patch('docstats.main.os.makedirs')
@patch('docstats.main.gettmpdir')
@patch('docstats.main.parseconfig')
@patch('docstats.main.parsecli')
def test_main_return_with_0(mock_parsecli, mock_parseconfig, mock_gettmpdir,