Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
A
AlekSIS-Core
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Terraform modules
Monitor
Service Desk
Analyze
Contributor analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
AlekSIS®
Official
AlekSIS-Core
Commits
08c56188
Verified
Commit
08c56188
authored
4 years ago
by
Jonathan Weth
Browse files
Options
Downloads
Patches
Plain Diff
Add docstrings for data check system
parent
9c91d140
No related branches found
No related tags found
1 merge request
!389
Add data check system
Pipeline
#5013
passed
4 years ago
Stage: test
Stage: build
Changes
1
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
aleksis/core/data_checks.py
+117
-1
117 additions, 1 deletion
aleksis/core/data_checks.py
with
117 additions
and
1 deletion
aleksis/core/data_checks.py
+
117
−
1
View file @
08c56188
...
...
@@ -11,6 +11,31 @@ from .util.core_helpers import celery_optional, get_site_preferences
class
SolveOption
:
"""
Define a solve option for one or more data checks.
Solve options are used in order to give the data admin typical
solutions to a data issue detected by a data check.
Example definition
.. code-block:: python
from aleksis.core.data_checks import SolveOption
from django.utils.translation import gettext as _
class DeleteSolveOption(SolveOption):
name =
"
delete
"
# has to be unqiue
verbose_name = _(
"
Delete
"
) # should make use of i18n
@classmethod
def solve(cls, check_result:
"
DataCheckResult
"
):
check_result.related_object.delete()
check_result.delete()
After the solve option has been successfully executed,
the corresponding data check result has to be deleted.
"""
name
:
str
=
"
default
"
verbose_name
:
str
=
""
...
...
@@ -25,11 +50,87 @@ class IgnoreSolveOption(SolveOption):
@classmethod
def
solve
(
cls
,
check_result
:
"
DataCheckResult
"
):
"""
Mark the object as solved without doing anything more.
"""
check_result
.
solved
=
True
check_result
.
save
()
class
DataCheck
:
"""
Define a data check.
Data checks should be used to search objects of
any type which are broken or need some extra action.
Defining data checks
--------------------
Data checks are defined by inheriting from the class DataCheck
and registering the inherited class in the data check registry.
Example:
.. code-block:: python
from aleksis.core.data_checks import DataCheck, DATA_CHECK_REGISTRY
from django.utils.translation import gettext as _
@DATA_CHECK_REGISTRY.register
class ExampleDataCheck(DataCheck):
name =
"
example
"
# has to be unique
verbose_name = _(
"
Ensure that there are no examples.
"
)
problem_name = _(
"
There is an example.
"
) # should both make use of i18n
solve_options = {
IgnoreSolveOption.name: IgnoreSolveOption
}
@classmethod
def check_data(cls):
from example_app.models import ExampleModel
wrong_examples = ExampleModel.objects.filter(wrong_value=True)
for example in wrong_examples:
cls.register_result(example)
Solve options are used in order to give the data admin typical solutions to this specific issue.
They are defined by inheriting from SolveOption.
More information about defining solve options can be find there.
The dictionary ``solve_options`` should include at least the IgnoreSolveOption,
but preferably also own solve options. The keys in this dictionary
have to be ``<YourOption>SolveOption.name``
and the values must be the corresponding solve option classes.
The class method ``check_data`` does the actual work. In this method
your code should find all objects with issues and should register
them in the result database using the class method ``register_result``.
Data checks have to be registered in the central registry.
This can be done by decorating the class with
``@DATA_CHECK_REGISTRY.register`` or adding it later
by ``DATA_CHECK_REGISTRY.register(<YourCheck>DataCheck)``.
Executing data checks
---------------------
The data checks can be executed by using the
celery task named ``aleksis.core.data_checks.check_data``.
We recommend to create a periodic task in the backend
which executes ``check_data`` on a regular base (e. g. every day).
.. warning::
To use the option described above, you must have setup celery properly.
Notifications about results
---------------------------
The data check tasks can notify persons via email
if there are new data issues. You can set these persons
by adding them to the preference
``Email recipients for data checks problem emails`` in the site configuration.
To enable this feature, you also have to activate
the preference ``Send emails if data checks detect problems``.
"""
# noqa: D412
name
:
str
=
""
verbose_name
:
str
=
""
problem_name
:
str
=
""
...
...
@@ -38,15 +139,26 @@ class DataCheck:
@classmethod
def
check_data
(
cls
):
"""
Find all objects with data issues and register them.
"""
pass
@classmethod
def
solve
(
cls
,
check_result
:
"
DataCheckResult
"
,
solve_option
:
str
=
"
default
"
):
def
solve
(
cls
,
check_result
:
"
DataCheckResult
"
,
solve_option
:
str
):
"""
Execute a solve option for an object detected by this check.
:param check_result: The result item from database
:param solve_option: The name of the solve option that should be executed
"""
with
reversion
.
create_revision
():
cls
.
solve_options
[
solve_option
].
solve
(
check_result
)
@classmethod
def
register_result
(
cls
,
instance
)
->
"
DataCheckResult
"
:
"""
Register an object with data issues in the result database.
:param instance: The affected object
:return: The database entry
"""
from
aleksis.core.models
import
DataCheckResult
ct
=
ContentType
.
objects
.
get_for_model
(
instance
)
...
...
@@ -57,12 +169,15 @@ class DataCheck:
class
DataCheckRegistry
:
"""
Create central registry for all data checks in AlekSIS.
"""
def
__init__
(
self
):
self
.
data_checks
=
[]
self
.
data_checks_by_name
=
{}
self
.
data_checks_choices
=
[]
def
register
(
self
,
check
:
DataCheck
):
"""
Add a new data check to the registry.
"""
self
.
data_checks
.
append
(
check
)
self
.
data_checks_by_name
[
check
.
name
]
=
check
self
.
data_checks_choices
.
append
((
check
.
name
,
check
.
verbose_name
))
...
...
@@ -74,6 +189,7 @@ DATA_CHECK_REGISTRY = DataCheckRegistry()
@celery_optional
def
check_data
():
"""
Execute all registered data checks and send email if activated.
"""
for
check
in
DATA_CHECK_REGISTRY
.
data_checks
:
logging
.
info
(
f
"
Run check:
{
check
.
verbose_name
}
"
)
check
.
check_data
()
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment