123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- """Core of the fluent API used by **ConfigUpdater** to make editing configuration files
- easier.
- """
- from configparser import DuplicateOptionError, DuplicateSectionError
- from typing import TYPE_CHECKING, Optional, TypeVar, Union
- if TYPE_CHECKING:
- from .block import Block
- from .container import Container
- from .section import Section
- T = TypeVar("T", bound="BlockBuilder")
- class BlockBuilder:
- """Builder that injects blocks at a given index position."""
- def __init__(self, container: "Container", idx: int):
- self._container = container
- self._idx = idx
- def _insert(self: T, block: "Block") -> T:
- self._container.structure.insert(self._idx, block)
- self._idx += 1
- return self
- def comment(self: T, text: str, comment_prefix="#") -> T:
- """Creates a comment block
- Args:
- text (str): content of comment without #
- comment_prefix (str): character indicating start of comment
- Returns:
- self for chaining
- """
- from .block import Comment
- comment = Comment(self._container)
- if not text.startswith(comment_prefix):
- text = "{} {}".format(comment_prefix, text)
- if not text.endswith("\n"):
- text = "{}{}".format(text, "\n")
- return self._insert(comment.add_line(text))
- 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)
- def space(self: T, newlines: int = 1) -> T:
- """Creates a vertical space of newlines
- Args:
- newlines (int): number of empty lines
- Returns:
- self for chaining
- """
- from .block import Space
- space = Space(container=self._container)
- for _ in range(newlines):
- space.add_line("\n")
- return self._insert(space)
- def option(self: T, key, value: Optional[str] = None, **kwargs) -> T:
- """Creates a new option inside a section
- Args:
- key (str): key of the option
- value (str or None): value of the option
- **kwargs: are passed to the constructor of :class:`Option`
- Returns:
- self for chaining
- """
- from .section import Section
- if not isinstance(self._container, Section):
- msg = "Options can only be added inside a section!"
- raise ValueError(msg, {"container": self._container})
- section = self._container
- option = section.create_option(key, value)
- if option.key in section.options():
- raise DuplicateOptionError(section.name, option.key)
- option.value = value
- return self._insert(option)
|