hammurabi.rules package¶
Submodules¶
hammurabi.rules.attributes module¶
Attributes module contains file and directory attribute manipulation rules which can be handy after creating new files or directories or even when adding execute permissions for a script in the project.
-
class
hammurabi.rules.attributes.
ModeChanged
(name: str, path: Optional[pathlib.Path] = None, new_value: Optional[int] = None, **kwargs)[source]¶ Bases:
hammurabi.rules.attributes.SingleAttributeRule
Change the mode of a file or directory.
Supported modes:
Config option
Description
stat.S_ISUID
Set user ID on execution.
stat.S_ISGID
Set group ID on execution.
stat.S_ENFMT
Record locking enforced.
stat.S_ISVTX
Save text image after execution.
stat.S_IREAD
Read by owner.
stat.S_IWRITE
Write by owner.
stat.S_IEXEC
Execute by owner.
stat.S_IRWXU
Read, write, and execute by owner.
stat.S_IRUSR
Read by owner.
stat.S_IWUSR
Write by owner.
stat.S_IXUSR
Execute by owner.
stat.S_IRWXG
Read, write, and execute by group.
stat.S_IRGRP
Read by group.
stat.S_IWGRP
Write by group.
stat.S_IXGRP
Execute by group.
stat.S_IRWXO
Read, write, and execute by others.
stat.S_IROTH
Read by others.
stat.S_IWOTH
Write by others.
stat.S_IXOTH
Execute by others.
Example usage:
>>> import stat >>> from pathlib import Path >>> from hammurabi import Law, Pillar, ModeChanged >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> ModeChanged( >>> name="Update script must be executable", >>> path=Path("./scripts/update.sh"), >>> new_value=stat.S_IXGRP | stat.S_IXGRP | stat.S_IXOTH >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
-
class
hammurabi.rules.attributes.
OwnerChanged
(name: str, path: Optional[pathlib.Path] = None, new_value: Optional[str] = None, **kwargs)[source]¶ Bases:
hammurabi.rules.attributes.SingleAttributeRule
Change the ownership of a file or directory.
The new ownership of a file or directory can be set in three ways. To set only the user use
new_value="username"
. To set only the group usenew_value=":group_name"
(please note the colon:
). It is also possible to set both username and group at the same time by usingnew_value="username:group_name"
.Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, OwnerChanged >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> OwnerChanged( >>> name="Change ownership of nginx config", >>> path=Path("./nginx.conf"), >>> new_value="www:web_admin" >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
-
class
hammurabi.rules.attributes.
SingleAttributeRule
(name: str, path: Optional[pathlib.Path] = None, new_value: Optional[str] = None, **kwargs)[source]¶ Bases:
hammurabi.rules.common.SinglePathRule
Extend
hammurabi.rules.base.Rule
to handle attributes of a single file or directory.-
post_task_hook
()[source]¶ Run code after the
hammurabi.rules.base.Rule.task()
has been performed. To access the parameter passed to the rule, always useself.param
forhammurabi.rules.base.Rule.post_task_hook()
.Note
This method can be used for execution of git commands like git add, or double checking a modification made.
Warning
This method is not called in dry run mode.
-
abstract
task
() → Any[source]¶ Abstract method representing how a
hammurabi.rules.base.Rule.task()
must be parameterized. Any difference in the parameters will result in pylint/mypy errors.For more details please check
hammurabi.rules.base.Rule.task()
.
-
hammurabi.rules.base module¶
This module contains the definition of Rule which describes what to do with the received parameter and does the necessary changes.
The Rule is an abstract class which describes all the required methods and
parameters, but it can be extended and customized easily by inheriting from
it. A good example for this kind of customization is hammurabi.rules.text.LineExists
which adds more parameters to hammurabi.rules.files.SingleFileRule
which
inherits from hammurabi.rules.base.Rule
.
-
class
hammurabi.rules.base.
Rule
(name: str, param: Any, preconditions: Iterable[Rule] = (), pipe: Optional[Rule] = None, children: Iterable[Rule] = ())[source]¶ Bases:
abc.ABC
Abstract class which describes the bare minimum and helper functions for Rules. A rule defines what and how should be executed. Since a rule can have piped and children rules, the “parent” rule is responsible for those executions. This kind of abstraction allows to run both piped and children rules sequentially in a given order.
Example usage:
>>> from typing import Optional >>> from pathlib import Path >>> from hammurabi import Rule >>> from hammurabi.mixins import GitMixin >>> >>> class SingleFileRule(Rule, GitMixin): >>> def __init__(self, name: str, path: Optional[Path] = None, **kwargs): >>> super().__init__(name, path, **kwargs) >>> >>> def post_task_hook(self): >>> self.git_add(self.param) >>> >>> @abstractmethod >>> def task(self, param: Path) -> Path: >>> pass
- Parameters
name (str) – Name of the rule which will be used for printing
preconditions (Iterable["Rule"]) – “Boolean Rules” which returns a truthy or falsy value
pipe (Optional["Rule"]) – Pipe will be called when the rule is executed successfully
children (Iterable["Rule"]) – Children will be executed after the piped rule if there is any
Warning
Preconditions can be used in several ways. The most common way is to run “Boolean Rules” which takes a parameter and returns a truthy or falsy value. In case of a falsy return, the precondition will fail and the rule will not be executed.
If any modification is done by any of the rules which are used as a precondition, those changes will be committed.
-
property
can_proceed
¶ Evaluate if a rule can continue its execution. In case the execution is called with
dry_run
config option set to true, this method will always returnFalse
to make sure not performing any changes. If preconditions are set, those will be evaluated by this method.- Returns
Return with the result of evaluation
- Return type
bool
Warning
hammurabi.rules.base.Rule.can_proceed()
checks the result ofself.preconditions
, which means the preconditions are executed. Make sure that you are not doing any modifications within rules used as preconditions, otherwise take extra attention for those rules.
-
property
description
¶ Return the description of the
hammurabi.rules.base.Rule.task()
based on its docstring.- Returns
Stripped description of
hammurabi.rules.base.Rule.task()
- Return type
str
Note
As of this method returns the docstring of
hammurabi.rules.base.Rule.task()
method, it worth to take care of its description when initialized.
-
property
documentation
¶ Return the documentation of the rule based on its name, docstring and the description of its task.
- Returns
Concatenation of the rule’s name, docstring, and task description
- Return type
str
Note
As of this method returns the name and docstring of the rule it worth to take care of its name and description when initialized.
-
execute
(param: Optional[Any] = None)[source]¶ Execute the rule’s task, its piped and children rules as well.
The execution order of task, piped rule and children rules described in but not by
hammurabi.rules.base.Rule.get_rule_chain()
.- Parameters
param (Optional[Any]) – Input parameter of the rule given by the user
- Raise
AssertionError
- Returns
None
Note
The input parameter can be optional because of the piped and children rules which are receiving the output of its parent. In this case the user is not able to set the param manually, since it is calculated.
Warning
If
self.can_proceed
returnsFalse
the whole execution will be stopped immediately andAssertionError
will be raised.
-
get_execution_order
() → List[Rule][source]¶ Same as
hammurabi.rules.base.Rule.get_rule_chain()
but for the root rule.
-
get_rule_chain
(rule: Rule) → List[Rule][source]¶ Get the execution chain of the given rule. The execution order is the following:
task (current rule’s
hammurabi.rules.base.Rule.task()
)Piped rule
Children rules (in the order provided by the iterator used)
- Parameters
rule (
hammurabi.rules.base.Rule
) – The rule which execution chain should be returned- Returns
Returns the list of rules in the order above
- Return type
List[Rule]
-
post_task_hook
()[source]¶ Run code after the
hammurabi.rules.base.Rule.task()
has been performed. To access the parameter passed to the rule, always useself.param
forhammurabi.rules.base.Rule.post_task_hook()
.Note
This method can be used for execution of git commands like git add, or double checking a modification made.
Warning
This method is not called in dry run mode.
-
pre_task_hook
()[source]¶ Run code before performing the
hammurabi.rules.base.Rule.task()
. To access the parameter passed to the rule, always useself.param
forhammurabi.rules.base.Rule.pre_task_hook()
.Warning
This method is not called in dry run mode.
-
abstract
task
() → Any[source]¶ Abstract method representing how a
hammurabi.rules.base.Rule.task()
must be parameterized. Any difference in the parameters will result in pylint/mypy errors.To be able to use the power of
pipe
andchildren
, return something which can be generally used for other rules as in input.- Returns
Returns an output which can be used as an input for other rules
- Return type
Any (usually same as self.param’s type)
Note
Although it is a good practice to return the same type for the output that the input has, but this is not the case for “Boolean Rules”. “Boolean Rules” should return True (or truthy) or False (or falsy) values.
Example usage:
>>> import logging >>> from pathlib import Path >>> from hammurabi.rules.files import SingleFileRule >>> >>> class FileExists(SingleFileRule): >>> def task(self) -> Path: >>> logging.debug('Creating file "%s" if not exists', str(self.param)) >>> self.param.touch() >>> return self.param
-
static
validate
(val: Any, cast_to: Optional[Any] = None, required=False) → Any[source]¶ Validate and/or cast the given value to another type. In case the existence of the value is required or casting failed an exception will be raised corresponding to the failure.
- Parameters
val (Any) – Value to validate
cast_to (Any) – Type in which the value should be returned
required (bool) – Check that the value is not falsy
- Raise
ValueError
if the given value is required but falsy- Returns
Returns the value in its original or casted type
- Return type
Any
Example usage:
>>> from typing import Optional >>> from pathlib import Path >>> from hammurabi import Rule >>> >>> class MyAwesomeRule(Rule): >>> def __init__(self, name: str, param: Optional[Path] = None): >>> self.param = self.validate(param, required=True) >>> >>> # Other method definitions ... >>>
hammurabi.rules.common module¶
-
class
hammurabi.rules.common.
MultiplePathRule
(name: str, paths: Optional[Iterable[pathlib.Path]] = (), **kwargs)[source]¶ Bases:
hammurabi.rules.base.Rule
,hammurabi.mixins.GitMixin
Abstract class which extends
hammurabi.rules.base.Rule
to handle operations on multiple files.-
post_task_hook
()[source]¶ Run code after the
hammurabi.rules.base.Rule.task()
has been performed. To access the parameter passed to the rule, always useself.param
forhammurabi.rules.base.Rule.post_task_hook()
.Note
This method can be used for execution of git commands like git add, or double checking a modification made.
Warning
This method is not called in dry run mode.
-
abstract
task
() → Any[source]¶ Abstract method representing how a
hammurabi.rules.base.Rule.task()
must be parameterized. Any difference in the parameters will result in pylint/mypy errors.For more details please check
hammurabi.rules.base.Rule.task()
.
-
-
class
hammurabi.rules.common.
SinglePathRule
(name: str, path: Optional[pathlib.Path] = None, **kwargs)[source]¶ Bases:
hammurabi.rules.base.Rule
,hammurabi.mixins.GitMixin
Abstract class which extends
hammurabi.rules.base.Rule
to handle operations on a single directory.-
post_task_hook
()[source]¶ Run code after the
hammurabi.rules.base.Rule.task()
has been performed. To access the parameter passed to the rule, always useself.param
forhammurabi.rules.base.Rule.post_task_hook()
.Note
This method can be used for execution of git commands like git add, or double checking a modification made.
Warning
This method is not called in dry run mode.
-
abstract
task
() → Any[source]¶ Abstract method representing how a
hammurabi.rules.base.Rule.task()
must be parameterized. Any difference in the parameters will result in pylint/mypy errors.For more details please check
hammurabi.rules.base.Rule.task()
.
-
hammurabi.rules.directories module¶
Directories module contains directory specific manipulation rules. Please
note that those rules which can be used for files and directories are
located in other modules like hammurabi.rules.operations
or
hammurabi.rules.attributes
.
-
class
hammurabi.rules.directories.
DirectoryEmptied
(name: str, path: Optional[pathlib.Path] = None, **kwargs)[source]¶ Bases:
hammurabi.rules.common.SinglePathRule
Ensure that the given directory’s content is removed. Please note the difference between emptying a directory and recreating it. The latter results in lost ACLs, permissions and modes.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, DirectoryEmptied >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> DirectoryEmptied( >>> name="Empty results directory", >>> path=Path("./test-results") >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
-
class
hammurabi.rules.directories.
DirectoryExists
(name: str, path: Optional[pathlib.Path] = None, **kwargs)[source]¶ Bases:
hammurabi.rules.common.SinglePathRule
Ensure that a directory exists. If the directory does not exists, make sure the directory is created.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, DirectoryExists >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> DirectoryExists( >>> name="Create secrets directory", >>> path=Path("./secrets") >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
-
class
hammurabi.rules.directories.
DirectoryNotExists
(name: str, path: Optional[pathlib.Path] = None, **kwargs)[source]¶ Bases:
hammurabi.rules.common.SinglePathRule
Ensure that the given directory does not exists.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, DirectoryNotExists >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> DirectoryNotExists( >>> name="Remove unnecessary directory", >>> path=Path("./temp") >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
hammurabi.rules.files module¶
Files module contains file specific manipulation rules. Please note that
those rules which can be used for files and directories are located in
other modules like hammurabi.rules.operations
or
hammurabi.rules.attributes
.
-
class
hammurabi.rules.files.
FileEmptied
(name: str, path: Optional[pathlib.Path] = None, **kwargs)[source]¶ Bases:
hammurabi.rules.common.SinglePathRule
Remove the content of the given file, but keep the file. Please note the difference between emptying a file and recreating it. The latter results in lost ACLs, permissions and modes.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, FileEmptied >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> FileEmptied( >>> name="Empty the check log file", >>> path=Path("/var/log/service/check.log") >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
-
class
hammurabi.rules.files.
FileExists
(name: str, path: Optional[pathlib.Path] = None, **kwargs)[source]¶ Bases:
hammurabi.rules.common.SinglePathRule
Ensure that a file exists. If the file does not exists, make sure the file is created.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, FileExists >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> FileExists( >>> name="Create service descriptor", >>> path=Path("./service.yaml") >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
-
class
hammurabi.rules.files.
FileNotExists
(name: str, path: Optional[pathlib.Path] = None, **kwargs)[source]¶ Bases:
hammurabi.rules.common.SinglePathRule
Ensure that the given file does not exists. If the file exists remove it, otherwise do nothing and return the original path.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, FileNotExists >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> FileNotExists( >>> name="Remove unused file", >>> path=Path("./debug.yaml") >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
-
class
hammurabi.rules.files.
FilesExist
(name: str, paths: Optional[Iterable[pathlib.Path]] = (), **kwargs)[source]¶ Bases:
hammurabi.rules.common.MultiplePathRule
Ensure that all files exists. If the files does not exists, make sure the files are created.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, FilesExist >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> FilesExist( >>> name="Create test files", >>> paths=[ >>> Path("./file_1"), >>> Path("./file_2"), >>> Path("./file_3"), >>> ] >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
-
class
hammurabi.rules.files.
FilesNotExist
(name: str, paths: Optional[Iterable[pathlib.Path]] = (), **kwargs)[source]¶ Bases:
hammurabi.rules.common.MultiplePathRule
Ensure that the given files does not exist. If the files exist remove them, otherwise do nothing and return the original paths.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, FilesNotExist >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> FilesNotExist( >>> name="Remove several files", >>> paths=[ >>> Path("./file_1"), >>> Path("./file_2"), >>> Path("./file_3"), >>> ] >>> ), >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
hammurabi.rules.ini module¶
Ini module is an extension for text rules tailor made for .ini/.cfg files. The main difference lies in the way it works. First, the .ini/.cfg file is parsed, then the modifications are made on the already parsed file.
-
class
hammurabi.rules.ini.
OptionRenamed
(name: str, path: Optional[pathlib.Path] = None, option: Optional[str] = None, new_name: Optional[str] = None, **kwargs)[source]¶ Bases:
hammurabi.rules.ini.SingleConfigFileRule
Ensure that an option of a section is renamed.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, OptionRenamed >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> OptionRenamed( >>> name="Rename an option", >>> path=Path("./config.ini"), >>> section="my_section", >>> option="typo", >>> new_name="correct", >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
-
task
() → pathlib.Path[source]¶ Rename an option of a section. In case a section can not be found, a
LookupError
exception will be raised to stop the execution. The execution must be stopped at this point, because if dependant rules will fail otherwise.- Raises
LookupError
raised if no section can be renamed- Returns
Return the input path as an output
- Return type
Path
-
-
class
hammurabi.rules.ini.
OptionsExist
(name: str, path: Optional[pathlib.Path] = None, options: Iterable[Tuple[str, Any]] = None, force_value: bool = False, **kwargs)[source]¶ Bases:
hammurabi.rules.ini.SingleConfigFileRule
Ensure that the given config option exists. If needed, the rule will create a config option with the given value. In case the
force_value
parameter is set to True, the original values will be replaced by the give ones.Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, OptionsExist >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> OptionsExist( >>> name="Ensure options are changed", >>> path=Path("./config.ini"), >>> section="fetching", >>> options=( >>> ("interval", "2s"), >>> ("abort_on_error", True), >>> ), >>> force_value=True, >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
Warning
When using the
force_value
parameter, please note that all the existing option values will be replaced by those set inoptions
parameter.-
task
() → pathlib.Path[source]¶ Remove one or more option from a section. In case a section can not be found, a
LookupError
exception will be raised to stop the execution. The execution must be stopped at this point, because if dependant rules will fail otherwise.- Raises
LookupError
raised if no section can be renamed- Returns
Return the input path as an output
- Return type
Path
-
-
class
hammurabi.rules.ini.
OptionsNotExist
(name: str, path: Optional[pathlib.Path] = None, options: Iterable[str] = (), **kwargs)[source]¶ Bases:
hammurabi.rules.ini.SingleConfigFileRule
Remove one or more option from a section.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, OptionsNotExist >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> OptionsNotExist( >>> name="Ensure options are removed", >>> path=Path("./config.ini"), >>> section="invalid", >>> options=( >>> "remove", >>> "me", >>> "please", >>> ) >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
-
task
() → pathlib.Path[source]¶ Remove one or more option from a section. In case a section can not be found, a
LookupError
exception will be raised to stop the execution. The execution must be stopped at this point, because if dependant rules will fail otherwise.- Raises
LookupError
raised if no section can be renamed- Returns
Return the input path as an output
- Return type
Path
-
-
class
hammurabi.rules.ini.
SectionExists
(name: str, path: Optional[pathlib.Path] = None, target: Optional[str] = None, options: Iterable[Tuple[str, Any]] = (), add_after: bool = True, **kwargs)[source]¶ Bases:
hammurabi.rules.ini.SingleConfigFileRule
Ensure that the given config section exists. If needed, the rule will create a config section with the given name, and optionally the specified options. In case options are set, the config options will be assigned to that config sections.
Similarly to
hammurabi.rules.text.LineExists
, this rule is able to add a section before or after a target section. The limitation compared toLineExists
is that theSectionExists
rule is only able to add the new entry exactly before or after its target.Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, SectionExists >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> SectionExists( >>> name="Ensure section exists", >>> path=Path("./config.ini"), >>> section="polling", >>> target="add_after_me", >>> options=( >>> ("interval", "2s"), >>> ("abort_on_error", True), >>> ), >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
Warning
When
options
parameter is set, make sure you are using an iterable tuple. The option keys must be strings, but there is no limitation for the value. It can be set to anything what the parser can handle. For more information on the parser, please visit the documentation of configupdater.-
task
() → pathlib.Path[source]¶ Ensure that the given config section exists. If needed, create a config section with the given name, and optionally the specified options.
In case options are set, the config options will be assigned to that config sections. A
LookupError
exception will be raised if the target section can not be found.- Raises
LookupError
raised if no target can be found- Returns
Return the input path as an output
- Return type
Path
-
-
class
hammurabi.rules.ini.
SectionNotExists
(name: str, path: Optional[pathlib.Path] = None, section: Optional[str] = None, **kwargs)[source]¶ Bases:
hammurabi.rules.ini.SingleConfigFileRule
Make sure that the given file not contains the specified line. When a section removed, all the options belonging to it will be removed too.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, SectionNotExists >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> SectionNotExists( >>> name="Ensure section removed", >>> path=Path("./config.ini"), >>> section="invalid", >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
-
class
hammurabi.rules.ini.
SectionRenamed
(name: str, path: Optional[pathlib.Path] = None, new_name: Optional[str] = None, **kwargs)[source]¶ Bases:
hammurabi.rules.ini.SingleConfigFileRule
Ensure that a section is renamed. None of its options will be changed.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, SectionRenamed >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> SectionRenamed( >>> name="Ensure section renamed", >>> path=Path("./config.ini"), >>> section="polling", >>> new_name="fetching", >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
-
task
() → pathlib.Path[source]¶ Rename the given section to a new name. None of its options will be changed. In case a section can not be found, a
LookupError
exception will be raised to stop the execution. The execution must be stopped at this point, because if other rules depending on the rename will fail otherwise.- Raises
LookupError
raised if no section can be renamed- Returns
Return the input path as an output
- Return type
Path
-
-
class
hammurabi.rules.ini.
SingleConfigFileRule
(name: str, path: Optional[pathlib.Path] = None, section: Optional[str] = None, **kwargs)[source]¶ Bases:
hammurabi.rules.common.SinglePathRule
Extend
hammurabi.rules.base.Rule
to handle parsed content manipulations on a single file.-
abstract
task
() → Any[source]¶ Abstract method representing how a
hammurabi.rules.base.Rule.task()
must be parameterized. Any difference in the parameters will result in pylint/mypy errors.For more details please check
hammurabi.rules.base.Rule.task()
.
-
abstract
hammurabi.rules.operations module¶
Operations module contains common file/directory operation which can be handy when need to move, rename or copy files.
-
class
hammurabi.rules.operations.
Copied
(name: str, path: Optional[pathlib.Path] = None, destination: Optional[pathlib.Path] = None, **kwargs)[source]¶ Bases:
hammurabi.rules.common.SinglePathRule
Ensure that the given file or directory is copied to the new path.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, Copied >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> Copied( >>> name="Create backup file", >>> path=Path("./service.yaml"), >>> destination=Path("./service.bkp.yaml") >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
-
class
hammurabi.rules.operations.
Moved
(name: str, path: Optional[pathlib.Path] = None, destination: Optional[pathlib.Path] = None, **kwargs)[source]¶ Bases:
hammurabi.rules.common.SinglePathRule
Move a file or directory from “A” to “B”.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, Moved >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> Moved( >>> name="Move pyproject.toml to its place", >>> path=Path("/tmp/generated/pyproject.toml.template"), >>> destination=Path("./pyproject.toml"), # Notice the rename! >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
-
class
hammurabi.rules.operations.
Renamed
(name: str, path: Optional[pathlib.Path] = None, new_name: Optional[str] = None, **kwargs)[source]¶ Bases:
hammurabi.rules.operations.Moved
This rule is a shortcut for
hammurabi.rules.operations.Moved
. Instead of destination path a new name is required.Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, Renamed >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> Renamed( >>> name="Rename pyproject.toml.bkp", >>> path=Path("/tmp/generated/pyproject.toml.bkp"), >>> new_name="pyproject.toml", >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
hammurabi.rules.text module¶
Text module contains simple but powerful general file content manipulations.
Combined with other simple rules like hammurabi.rules.files.FileExists
or hammurabi.rules.attributes.ModeChanged
almost anything can be
achieved. Although any file’s content can be changed using these rules, for
common file formats like ini
, yaml
or json
dedicated rules are
created.
-
class
hammurabi.rules.text.
LineExists
(name: str, path: Optional[pathlib.Path] = None, text: Optional[str] = None, criteria: Optional[str] = None, target: Optional[str] = None, position: int = 1, respect_indentation: bool = True, **kwargs)[source]¶ Bases:
hammurabi.rules.common.SinglePathRule
Make sure that the given file contains the required line. This rule is capable for inserting the expected text before or after the unique target text respecting the indentation of its context.
The default behaviour is to insert the required text exactly after the target line, and respect its indentation. Please note that
text
,criteria
andtarget
parameters are required.Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, LineExists >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> LineExists( >>> name="Extend gunicorn config", >>> path=Path("./gunicorn.conf.py"), >>> text="keepalive = 65", >>> criteria=r"^keepalive.*", >>> target=r"^bind.*", >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
Note
The indentation of the target text will be extracted by a simple regular expression. If a more complex regexp is required, please inherit from this class.
-
task
() → pathlib.Path[source]¶ Make sure that the given file contains the required line. This rule is capable for inserting the expected rule before or after the unique target text respecting the indentation of its context.
- Raises
LookupError
- Returns
Returns the path of the modified file
- Return type
Path
-
-
class
hammurabi.rules.text.
LineNotExists
(name: str, path: Optional[pathlib.Path] = None, text: Optional[str] = None, **kwargs)[source]¶ Bases:
hammurabi.rules.common.SinglePathRule
Make sure that the given file not contains the specified line.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, LineNotExists >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> LineNotExists( >>> name="Remove keepalive", >>> path=Path("./gunicorn.conf.py"), >>> text="keepalive = 65", >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
-
class
hammurabi.rules.text.
LineReplaced
(name: str, path: Optional[pathlib.Path] = None, text: Optional[str] = None, target: Optional[str] = None, respect_indentation: bool = True, **kwargs)[source]¶ Bases:
hammurabi.rules.common.SinglePathRule
Make sure that the given text is replaced in the given file.
The default behaviour is to replace the required text with the exact same indentation that the target line has. This behaviour can be turned off by setting the
respect_indentation
parameter to False. Please note thattext
andtarget
parameters are required.Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, LineReplaced >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> LineReplaced( >>> name="Replace typo using regex", >>> path=Path("./gunicorn.conf.py"), >>> text="keepalive = 65", >>> target=r"^kepalive.*", >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
Note
The indentation of the target text will be extracted by a simple regular expression. If a more complex regexp is required, please inherit from this class.
Warning
This rule will replace all the matching lines in the given file. Make sure the given target regular expression is tested before the rule used against production code.