summaryrefslogtreecommitdiff
path: root/python-django-scrubber.spec
diff options
context:
space:
mode:
Diffstat (limited to 'python-django-scrubber.spec')
-rw-r--r--python-django-scrubber.spec1592
1 files changed, 1592 insertions, 0 deletions
diff --git a/python-django-scrubber.spec b/python-django-scrubber.spec
new file mode 100644
index 0000000..a39842f
--- /dev/null
+++ b/python-django-scrubber.spec
@@ -0,0 +1,1592 @@
+%global _empty_manifest_terminate_build 0
+Name: python-django-scrubber
+Version: 1.2.0
+Release: 1
+Summary: Data Anonymizer for Django
+License: BSD
+URL: https://github.com/regiohelden/django-scrubber
+Source0: https://mirrors.nju.edu.cn/pypi/web/packages/da/d9/f70f44de002bf2e0368482050c14971e1f4230b91e2161417ef016d3207d/django-scrubber-1.2.0.tar.gz
+BuildArch: noarch
+
+Requires: python3-django-model-utils
+Requires: python3-faker
+
+%description
+# Django Scrubber
+
+[![Build Status](https://github.com/RegioHelden/django-scrubber/workflows/Build/badge.svg)](https://github.com/RegioHelden/django-scrubber/actions)
+[![PyPI](https://img.shields.io/pypi/v/django-scrubber.svg)](https://pypi.org/project/django-scrubber/)
+[![Downloads](https://pepy.tech/badge/django-scrubber)](https://pepy.tech/project/django-scrubber)
+
+`django_scrubber` is a django app meant to help you anonymize your project's database data. It destructively alters data
+directly on the DB and therefore **should not be used on production**.
+
+The main use case is providing developers with realistic data to use during development, without having to distribute
+your customers' or users' potentially sensitive information.
+To accomplish this, `django_scrubber` should be plugged in a step during the creation of your database dumps.
+
+Simply mark the fields you want to anonymize and call the `scrub_data` management command. Data will be replaced based
+on different *scrubbers* (see below), which define how the anonymous content will be generated.
+
+If you want to be sure that you don't forget any fields in the ongoing development progress, you can use the
+management command `scrub_validation` in your CI/CD pipeline to check for any missing fields.
+
+## Installation
+
+Simply run:
+
+```
+pip install django-scrubber
+```
+
+And add `django_scrubber` to your django `INSTALLED_APPS`. I.e.: in `settings.py` add:
+
+```
+INSTALLED_APPS = [
+ ...
+ 'django_scrubber',
+ ...
+]
+```
+
+## Scrubbing data
+
+In order to scrub data, i.e.: to replace DB data with anonymized versions, `django-scrubber` must know which models and
+fields it should act on, and how the data should be replaced.
+
+There are a few different ways to select which data should be scrubbed, namely: explicitly per model field; or globally
+per name or field type.
+
+Adding scrubbers directly to model, matching scrubbers to fields by name:
+
+```python
+class MyModel(Model):
+ somefield = CharField()
+
+ class Scrubbers:
+ somefield = scrubbers.Hash('somefield')
+```
+
+Adding scrubbers globally, either by field name or field type:
+
+```python
+# (in settings.py)
+
+SCRUBBER_GLOBAL_SCRUBBERS = {
+ 'name': scrubbers.Hash,
+ EmailField: scrubbers.Hash,
+}
+```
+
+Model scrubbers override field-name scrubbers, which in turn override field-type scrubbers.
+
+To disable global scrubbing in some specific model, simply set the respective field scrubber to `None`.
+
+Scrubbers defined for non-existing fields will raise a warning but not fail the scubbing process.
+
+Which mechanism will be used to scrub the selected data is determined by using one of the provided scrubbers
+in `django_scrubber.scrubbers`. See below for a list.
+Alternatively, values may be anything that can be used as a value in a `QuerySet.update()` call (like `Func` instances,
+string literals, etc), or any `callable` that returns such an object when called with a `Field` object as argument.
+
+By default, `django_scrubber` will affect all models from all registered apps. This may lead to issues with third-party
+apps if the global scrubbers are too general. This can be avoided with the `SCRUBBER_APPS_LIST` setting. Using this, you
+might for instance split your `INSTALLED_APPS` into multiple `SYSTEM_APPS` and `LOCAL_APPS`, then
+set `SCRUBBER_APPS_LIST = LOCAL_APPS`, to scrub only your own apps.
+
+Finally just run `./manage.py scrub_data` to **destructively** scrub the registered fields.
+
+### Arguments to the scrub_data command
+
+`--model` Scrub only a single model (format <app_label>.<model_name>)
+
+`--keep-sessions` Will NOT truncate all (by definition critical) session data.
+
+`--remove-fake-data` Will truncate the database table storing preprocessed data for the Faker library.
+
+## Built-In scrubbers
+
+### Empty/Null
+
+The simplest scrubbers: replace the field's content with the empty string or `NULL`, respectively.
+
+```python
+class Scrubbers:
+ somefield = scrubbers.Empty
+ someother = scrubbers.Null
+```
+
+These scrubbers have no options.
+
+### Keeper
+
+When running the validation or want to work in strict mode, you maybe want to actively decide to keep certain data
+instead of scrubbing them. In this case, you can just define `scrubbers.Keep`.
+
+```python
+class Scrubbers:
+ non_critical_field = scrubbers.Keep
+```
+
+These scrubber doesn't have any options.
+
+### Hash
+
+Simple hashing of content:
+
+```python
+class Scrubbers:
+ somefield = scrubbers.Hash # will use the field itself as source
+ someotherfield = scrubbers.Hash('somefield') # can optionally pass a different field name as hashing source
+```
+
+Currently, this uses the MD5 hash which is supported in a wide variety of DB engines. Additionally, since security is
+not the main objective, a shorter hash length has a lower risk of being longer than whatever field it is supposed to
+replace.
+
+### Lorem
+
+Simple scrubber meant to replace `TextField` with a static block of text. Has no options.
+
+```python
+class Scrubbers:
+ somefield = scrubbers.Lorem
+```
+
+### Concat
+
+Wrapper around `django.db.functions.Concat` to enable simple concatenation of scrubbers. This is useful if you want to
+ensure a fields uniqueness through composition of, for instance, the `Hash` and `Faker` (see below) scrubbers.
+
+The following will generate random email addresses by hashing the user-part and using `faker` for the domain part:
+
+```python
+class Scrubbers:
+ email = scrubbers.Concat(scrubbers.Hash('email'), models.Value('@'), scrubbers.Faker('domain_name'))
+```
+
+### Faker
+
+Replaces content with the help of [faker](https://pypi.python.org/pypi/Faker).
+
+```python
+class Scrubbers:
+ first_name = scrubbers.Faker('first_name')
+ last_name = scrubbers.Faker('last_name')
+ past_date = scrubbers.Faker('past_date', start_date="-30d", tzinfo=None)
+```
+
+The replacements are done on the database-level and should therefore be able to cope with large amounts of data with
+reasonable performance.
+
+The `Faker` scrubber requires at least one argument: the faker provider used to generate random data.
+All [faker providers](https://faker.readthedocs.io/en/latest/providers.html) are supported, and you can also register
+your own custom providers.<br />
+Any remaining arguments will be passed through to that provider. Please refer to the faker docs if a provider accepts
+arguments and what to do with them.
+
+#### Locales
+
+Faker will be initialized with the current django `LANGUAGE_CODE` and will populate the DB with localized data. If you
+want localized scrubbing, simply set it to some other value.
+
+#### Idempotency
+
+By default, the faker instance used to populate the DB uses a fixed random seed, in order to ensure different scrubbings
+of the same data generate the same output. This is particularly useful if the scrubbed data is imported as a dump by
+developers, since changing data during troubleshooting would otherwise be confusing.
+
+This behaviour can be changed by setting `SCRUBBER_RANDOM_SEED=None`, which ensures every scrubbing will generate random
+source data.
+
+#### Limitations
+
+Scrubbing unique fields may lead to `IntegrityError`s, since there is no guarantee that the random content will not be
+repeated. Playing with different settings for `SCRUBBER_RANDOM_SEED` and `SCRUBBER_ENTRIES_PER_PROVIDER` may alleviate
+the problem.
+Unfortunately, for performance reasons, the source data for scrubbing with faker is added to the database, and
+arbitrarily increasing `SCRUBBER_ENTRIES_PER_PROVIDER` will significantly slow down scrubbing (besides still not
+guaranteeing uniqueness).
+
+When using `django < 2.1` and working on `sqlite` a bug within django causes field-specific scrubbing (
+e.g. `date_object`) to fail. Please consider using a different database backend or upgrade to the latest django version.
+
+## Scrubbing third-party models
+
+Sometimes you just don't have control over some code, but you still want to scrub the data of a given model.
+
+A good example is the Django user model. It contains sensitive data, and you would have to overwrite the whole model
+just to add the scrubber metaclass.
+
+That's the way to go:
+
+1. Define your Scrubber class **somewhere** in your codebase (like a `scrubbers.py`)
+
+```python
+# scrubbers.py
+class UserScrubbers:
+ scrubbers.Faker('de_DE')
+ first_name = scrubbers.Faker('first_name')
+ last_name = scrubbers.Faker('last_name')
+ username = scrubbers.Faker('uuid4')
+ password = scrubbers.Faker('sha1')
+ last_login = scrubbers.Null
+ email = scrubbers.Concat(first_name, models.Value('.'), last_name, models.Value('@'),
+ models.Value(settings.SCRUBBER_DOMAIN))
+````
+
+2. Set up a mapping between your third-party model and your scrubber class
+
+```python
+# settings.py
+SCRUBBER_MAPPING = {
+ "auth.User": "apps.account.scrubbers.UserScrubbers",
+}
+```
+
+## Settings
+
+### `SCRUBBER_GLOBAL_SCRUBBERS`:
+
+Dictionary of global scrubbers. Keys should be either field names as strings or field type classes. Values should be one
+of the scrubbers provided in `django_scrubber.scrubbers`.
+
+Example:
+
+```python
+SCRUBBER_GLOBAL_SCRUBBERS = {
+ 'name': scrubbers.Hash,
+ EmailField: scrubbers.Hash,
+}
+```
+
+### `SCRUBBER_RANDOM_SEED`:
+
+The seed used when generating random content by the Faker scrubber. Setting this to `None` means each scrubbing will
+generate different data.
+
+(default: 42)
+
+### `SCRUBBER_ENTRIES_PER_PROVIDER`:
+
+Number of entries to use as source for Faker scrubber. Increasing this value will increase the randomness of generated
+data, but decrease performance.
+
+(default: 1000)
+
+### `SCRUBBER_SKIP_UNMANAGED`:
+
+Do not attempt to scrub models which are not managed by the ORM.
+
+(default: True)
+
+### `SCRUBBER_APPS_LIST`:
+
+Only scrub models belonging to these specific django apps. If unset, will scrub all installed apps.
+
+(default: None)
+
+### `SCRUBBER_ADDITIONAL_FAKER_PROVIDERS`:
+
+Add additional fake providers to be used by Faker. Must be noted as full dotted path to the provider class.
+
+(default: empty list)
+
+### `SCRUBBER_FAKER_LOCALE`:
+
+Set an alternative locale for Faker used during the scrubbing process.
+
+(default: None, falls back to Django's default locale)
+
+### `SCRUBBER_MAPPING`:
+
+Define a class and a mapper which does not have to live inside the given model. Useful, if you have no control over the
+models code you'd like to scrub.
+
+### `SCRUBBER_STRICT_MODE`:
+
+When strict mode is activated, you have to define a scrubbing policy for every field of every type defined in
+`SCRUBBER_REQUIRED_FIELD_TYPES`. If you have unscrubbed fields and this flag is active, you can't run
+`pyhton manage.py scrub_data`.
+
+### `SCRUBBER_REQUIRED_FIELD_TYPES`:
+
+Defaults to all text-based Django model fields. Usually, privacy-relevant data is only stored in text-fields, numbers
+and booleans (usually) can't contain sensitive personal data. These fields will be checked when running
+`python manage.py scub_validation`.
+
+(default: (models.CharField, models.TextField, models.URLField, models.JSONField, models.GenericIPAddressField,
+ models.EmailField,))
+
+### `SCRUBBER_REQUIRED_FIELD_MODEL_WHITELIST`:
+
+Whitelists a list of models which will not be checked during `scrub_validation` and when
+activating the strict mode. Defaults to the non-privacy-related Django base models.
+
+(default: ['auth.Group', 'auth.Permission', 'contenttypes.ContentType', 'sessions.Session', 'sites.Site',
+'django_scrubber.FakeData',))
+
+````python
+SCRUBBER_MAPPING = {
+ "auth.User": "my_app.scrubbers.UserScrubbers",
+}
+````
+
+(default: {})
+
+## Logging
+
+Scrubber uses the default django logger. The logger name is ``django_scrubber.scrubbers``.
+So if you want to log - for example - to the console, you could set up the logger like this:
+
+````
+LOGGING['loggers']['django_scrubber'] = {
+ 'handlers': ['console'],
+ 'propagate': True,
+ 'level': 'DEBUG',
+}
+````
+
+## Making a new release
+
+[bumpversion](https://github.com/peritus/bumpversion) is used to manage releases.
+
+Add your changes to the [CHANGELOG](./CHANGELOG.md) and run `bumpversion <major|minor|patch>`, then push (including
+tags)
+
+
+# Changelog
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
+and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
+
+<!--
+## [Unreleased]
+-->
+
+## [1.2.0] - 2023-04-01
+### Changed
+- Added scrubber validation - Thanks @GitRon
+- Added strict mode - Thanks @GitRon
+
+## [1.1.0] - 2022-07-11
+### Changed
+- Invalid fields on scrubbers will no longer raise exception but just trigger warnings now
+- Author list completed
+
+## [1.0.0] - 2022-07-11
+### Changed
+- Meta data for python package improved - Thanks @GitRon
+
+## [0.9.0] - 2022-06-27
+### Added
+- Add functionality to scrub third party models like the Django user model, see https://github.com/RegioHelden/django-scrubber#scrubbing-third-party-models - Thanks @GitRon
+- Add tests for Python 3.10 - Thanks @costela
+
+## [0.8.0] - 2022-05-01
+### Added
+- Add `keep-sessions` argument to scrub_data command. Will NOT truncate all (by definition critical) session data. Thanks @GitRon
+- Add `remove-fake-data` argument to scrub_data command. Will truncate the database table storing preprocessed data for the Faker library. Thanks @GitRon
+- Add Django 3.2 and 4.0 to test matrix
+### Changed
+- Remove Python 3.6 from test matrix
+- Remove Django 2.2 and 3.1 from test matrix
+
+## [0.7.0] - 2022-02-24
+### Changed
+- Remove upper boundary for Faker as they release non-breaking major upgrades way too often, please pin a working release in your own app
+
+## [0.6.2] - 2022-02-08
+### Changed
+- Support faker 12.x
+
+## [0.6.1] - 2022-01-25
+### Changed
+- Support faker 11.x
+
+## [0.6.0] - 2021-10-18
+### Added
+- Add support to override Faker locale in scrubber settings
+### Changed
+- Publish coverage only on main repository
+
+## [0.5.6] - 2021-10-08
+### Changed
+- Pin psycopg2 in CI ti 2.8.6 as 2.9+ is incompatible with Django 2.2
+
+## [0.5.5] - 2021-10-08
+### Changed
+- Support faker 9.x
+
+## [0.5.4] - 2021-04-13
+### Changed
+- Support faker 8.x
+
+## [0.5.3] - 2021-02-04
+### Changed
+- Support faker 6.x
+
+## [0.5.2] - 2021-01-12
+### Changed
+- Add tests for Python 3.9
+- Add tests for Django 3.1
+- Support faker 5.x
+- Update dev package requirements
+
+## [0.5.1] - 2020-10-16
+### Changed
+- Fix travis setup
+
+## [0.5.0] - 2020-10-16
+### Added
+- Support for django-model-utils 4.x.x
+### Changed
+- Add compatibility for Faker 3.x.x, remove support for Faker < 0.8.0
+- Remove support for Python 2.7 and 3.5
+- Remove support for Django 1.x
+
+## [0.4.4] - 2019-12-11
+### Fixed
+- add the same version restrictions on faker to setup.py
+
+## [0.4.3] - 2019-12-04
+### Added
+- add empty and null scrubbers
+
+### Changed
+- make `Lorem` scrubber lazy, matching README
+
+### Fixed
+- set more stringent version requirements (faker >= 3 breaks builds)
+
+## [0.4.1] - 2019-11-16
+### Fixed
+- correctly clear fake data model to fix successive calls to `scrub_data` (thanks [Benedikt Bauer](https://github.com/mastacheata))
+
+## [0.4.0] - 2019-11-13
+### Added
+- `Faker` scrubber now supports passing arbitrary arguments to faker providers and also non-text fields (thanks [Benedikt Bauer](https://github.com/mastacheata) and [Ronny Vedrilla](https://github.com/GitRon))
+
+## [0.3.1] - 2018-09-10
+### Fixed
+- [#9](https://github.com/RegioHelden/django-scrubber/pull/9) `Hash` scrubber choking on fields with `max_length=None` - Thanks to [Charlie Denton](https://github.com/meshy)
+
+## [0.3.0] - 2018-09-06
+### Added
+- Finally added some basic tests (thanks [Marco De Felice](https://github.com/md-f))
+- `Hash` scrubber can now also be used on sqlite
+
+### Changed
+- **BREAKING**: scrubbers that are lazily initialized now receive `Field` instances as parameters, instead of field
+ names. If you have custom scrubbers depending on the previous behavior, these should be updated. Accessing the
+ field's name from the object instance is trivial: `field_instance.name`. E.g.: if you have `some_field = MyCustomScrubber`
+ in any of your models' `Scrubbers`, this class must accept a `Field` instance as first parameter.
+ Note that explicitly intializing any of the built-in scrubbers with field names is still supported, so if you were
+ just using built-in scrubbers, you should not be affected by this change.
+- related to the above, `FuncField` derived classes can now do connection-based setup by implementing the
+ `connection_setup` method. This is mostly useful for doing different things based on the DB vendor, and is used to
+ implement `MD5()` on sqlite (see added feature above)
+- Ignore proxy models when scrubbing (thanks [Marco De Felice](https://github.com/md-f))
+- Expand tests to include python 3.7 and django 2.1
+
+## [0.2.1] - 2018-08-14
+### Added
+- Option to scrub only one model from the management command
+- Support loading additional faker providers by config setting SCRUBBER\_ADDITIONAL\_FAKER\_PROVIDERS
+
+### Changed
+- Switched changelog format to the one proposed on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
+
+## [0.2.0] - 2018-08-13
+### Added
+- scrubbers.Concat to make simple concatenation of scrubbers possible
+
+## [0.1.4] - 2018-08-13
+### Changed
+- Make our README look beautiful on PyPI
+
+## [0.1.3] - 2018-08-13
+### Fixed
+- [#1](https://github.com/RegioHelden/django-scrubber/pull/1) badly timed import - Thanks to [Charlie Denton](https://github.com/meshy)
+
+## [0.1.2] - 2018-06-22
+### Changed
+- Use bumpversion and travis to make new releases
+- rename project: django\_scrubber → django-scrubber
+
+## [0.1.0] - 2018-06-22
+### Added
+- Initial release
+
+
+%package -n python3-django-scrubber
+Summary: Data Anonymizer for Django
+Provides: python-django-scrubber
+BuildRequires: python3-devel
+BuildRequires: python3-setuptools
+BuildRequires: python3-pip
+%description -n python3-django-scrubber
+# Django Scrubber
+
+[![Build Status](https://github.com/RegioHelden/django-scrubber/workflows/Build/badge.svg)](https://github.com/RegioHelden/django-scrubber/actions)
+[![PyPI](https://img.shields.io/pypi/v/django-scrubber.svg)](https://pypi.org/project/django-scrubber/)
+[![Downloads](https://pepy.tech/badge/django-scrubber)](https://pepy.tech/project/django-scrubber)
+
+`django_scrubber` is a django app meant to help you anonymize your project's database data. It destructively alters data
+directly on the DB and therefore **should not be used on production**.
+
+The main use case is providing developers with realistic data to use during development, without having to distribute
+your customers' or users' potentially sensitive information.
+To accomplish this, `django_scrubber` should be plugged in a step during the creation of your database dumps.
+
+Simply mark the fields you want to anonymize and call the `scrub_data` management command. Data will be replaced based
+on different *scrubbers* (see below), which define how the anonymous content will be generated.
+
+If you want to be sure that you don't forget any fields in the ongoing development progress, you can use the
+management command `scrub_validation` in your CI/CD pipeline to check for any missing fields.
+
+## Installation
+
+Simply run:
+
+```
+pip install django-scrubber
+```
+
+And add `django_scrubber` to your django `INSTALLED_APPS`. I.e.: in `settings.py` add:
+
+```
+INSTALLED_APPS = [
+ ...
+ 'django_scrubber',
+ ...
+]
+```
+
+## Scrubbing data
+
+In order to scrub data, i.e.: to replace DB data with anonymized versions, `django-scrubber` must know which models and
+fields it should act on, and how the data should be replaced.
+
+There are a few different ways to select which data should be scrubbed, namely: explicitly per model field; or globally
+per name or field type.
+
+Adding scrubbers directly to model, matching scrubbers to fields by name:
+
+```python
+class MyModel(Model):
+ somefield = CharField()
+
+ class Scrubbers:
+ somefield = scrubbers.Hash('somefield')
+```
+
+Adding scrubbers globally, either by field name or field type:
+
+```python
+# (in settings.py)
+
+SCRUBBER_GLOBAL_SCRUBBERS = {
+ 'name': scrubbers.Hash,
+ EmailField: scrubbers.Hash,
+}
+```
+
+Model scrubbers override field-name scrubbers, which in turn override field-type scrubbers.
+
+To disable global scrubbing in some specific model, simply set the respective field scrubber to `None`.
+
+Scrubbers defined for non-existing fields will raise a warning but not fail the scubbing process.
+
+Which mechanism will be used to scrub the selected data is determined by using one of the provided scrubbers
+in `django_scrubber.scrubbers`. See below for a list.
+Alternatively, values may be anything that can be used as a value in a `QuerySet.update()` call (like `Func` instances,
+string literals, etc), or any `callable` that returns such an object when called with a `Field` object as argument.
+
+By default, `django_scrubber` will affect all models from all registered apps. This may lead to issues with third-party
+apps if the global scrubbers are too general. This can be avoided with the `SCRUBBER_APPS_LIST` setting. Using this, you
+might for instance split your `INSTALLED_APPS` into multiple `SYSTEM_APPS` and `LOCAL_APPS`, then
+set `SCRUBBER_APPS_LIST = LOCAL_APPS`, to scrub only your own apps.
+
+Finally just run `./manage.py scrub_data` to **destructively** scrub the registered fields.
+
+### Arguments to the scrub_data command
+
+`--model` Scrub only a single model (format <app_label>.<model_name>)
+
+`--keep-sessions` Will NOT truncate all (by definition critical) session data.
+
+`--remove-fake-data` Will truncate the database table storing preprocessed data for the Faker library.
+
+## Built-In scrubbers
+
+### Empty/Null
+
+The simplest scrubbers: replace the field's content with the empty string or `NULL`, respectively.
+
+```python
+class Scrubbers:
+ somefield = scrubbers.Empty
+ someother = scrubbers.Null
+```
+
+These scrubbers have no options.
+
+### Keeper
+
+When running the validation or want to work in strict mode, you maybe want to actively decide to keep certain data
+instead of scrubbing them. In this case, you can just define `scrubbers.Keep`.
+
+```python
+class Scrubbers:
+ non_critical_field = scrubbers.Keep
+```
+
+These scrubber doesn't have any options.
+
+### Hash
+
+Simple hashing of content:
+
+```python
+class Scrubbers:
+ somefield = scrubbers.Hash # will use the field itself as source
+ someotherfield = scrubbers.Hash('somefield') # can optionally pass a different field name as hashing source
+```
+
+Currently, this uses the MD5 hash which is supported in a wide variety of DB engines. Additionally, since security is
+not the main objective, a shorter hash length has a lower risk of being longer than whatever field it is supposed to
+replace.
+
+### Lorem
+
+Simple scrubber meant to replace `TextField` with a static block of text. Has no options.
+
+```python
+class Scrubbers:
+ somefield = scrubbers.Lorem
+```
+
+### Concat
+
+Wrapper around `django.db.functions.Concat` to enable simple concatenation of scrubbers. This is useful if you want to
+ensure a fields uniqueness through composition of, for instance, the `Hash` and `Faker` (see below) scrubbers.
+
+The following will generate random email addresses by hashing the user-part and using `faker` for the domain part:
+
+```python
+class Scrubbers:
+ email = scrubbers.Concat(scrubbers.Hash('email'), models.Value('@'), scrubbers.Faker('domain_name'))
+```
+
+### Faker
+
+Replaces content with the help of [faker](https://pypi.python.org/pypi/Faker).
+
+```python
+class Scrubbers:
+ first_name = scrubbers.Faker('first_name')
+ last_name = scrubbers.Faker('last_name')
+ past_date = scrubbers.Faker('past_date', start_date="-30d", tzinfo=None)
+```
+
+The replacements are done on the database-level and should therefore be able to cope with large amounts of data with
+reasonable performance.
+
+The `Faker` scrubber requires at least one argument: the faker provider used to generate random data.
+All [faker providers](https://faker.readthedocs.io/en/latest/providers.html) are supported, and you can also register
+your own custom providers.<br />
+Any remaining arguments will be passed through to that provider. Please refer to the faker docs if a provider accepts
+arguments and what to do with them.
+
+#### Locales
+
+Faker will be initialized with the current django `LANGUAGE_CODE` and will populate the DB with localized data. If you
+want localized scrubbing, simply set it to some other value.
+
+#### Idempotency
+
+By default, the faker instance used to populate the DB uses a fixed random seed, in order to ensure different scrubbings
+of the same data generate the same output. This is particularly useful if the scrubbed data is imported as a dump by
+developers, since changing data during troubleshooting would otherwise be confusing.
+
+This behaviour can be changed by setting `SCRUBBER_RANDOM_SEED=None`, which ensures every scrubbing will generate random
+source data.
+
+#### Limitations
+
+Scrubbing unique fields may lead to `IntegrityError`s, since there is no guarantee that the random content will not be
+repeated. Playing with different settings for `SCRUBBER_RANDOM_SEED` and `SCRUBBER_ENTRIES_PER_PROVIDER` may alleviate
+the problem.
+Unfortunately, for performance reasons, the source data for scrubbing with faker is added to the database, and
+arbitrarily increasing `SCRUBBER_ENTRIES_PER_PROVIDER` will significantly slow down scrubbing (besides still not
+guaranteeing uniqueness).
+
+When using `django < 2.1` and working on `sqlite` a bug within django causes field-specific scrubbing (
+e.g. `date_object`) to fail. Please consider using a different database backend or upgrade to the latest django version.
+
+## Scrubbing third-party models
+
+Sometimes you just don't have control over some code, but you still want to scrub the data of a given model.
+
+A good example is the Django user model. It contains sensitive data, and you would have to overwrite the whole model
+just to add the scrubber metaclass.
+
+That's the way to go:
+
+1. Define your Scrubber class **somewhere** in your codebase (like a `scrubbers.py`)
+
+```python
+# scrubbers.py
+class UserScrubbers:
+ scrubbers.Faker('de_DE')
+ first_name = scrubbers.Faker('first_name')
+ last_name = scrubbers.Faker('last_name')
+ username = scrubbers.Faker('uuid4')
+ password = scrubbers.Faker('sha1')
+ last_login = scrubbers.Null
+ email = scrubbers.Concat(first_name, models.Value('.'), last_name, models.Value('@'),
+ models.Value(settings.SCRUBBER_DOMAIN))
+````
+
+2. Set up a mapping between your third-party model and your scrubber class
+
+```python
+# settings.py
+SCRUBBER_MAPPING = {
+ "auth.User": "apps.account.scrubbers.UserScrubbers",
+}
+```
+
+## Settings
+
+### `SCRUBBER_GLOBAL_SCRUBBERS`:
+
+Dictionary of global scrubbers. Keys should be either field names as strings or field type classes. Values should be one
+of the scrubbers provided in `django_scrubber.scrubbers`.
+
+Example:
+
+```python
+SCRUBBER_GLOBAL_SCRUBBERS = {
+ 'name': scrubbers.Hash,
+ EmailField: scrubbers.Hash,
+}
+```
+
+### `SCRUBBER_RANDOM_SEED`:
+
+The seed used when generating random content by the Faker scrubber. Setting this to `None` means each scrubbing will
+generate different data.
+
+(default: 42)
+
+### `SCRUBBER_ENTRIES_PER_PROVIDER`:
+
+Number of entries to use as source for Faker scrubber. Increasing this value will increase the randomness of generated
+data, but decrease performance.
+
+(default: 1000)
+
+### `SCRUBBER_SKIP_UNMANAGED`:
+
+Do not attempt to scrub models which are not managed by the ORM.
+
+(default: True)
+
+### `SCRUBBER_APPS_LIST`:
+
+Only scrub models belonging to these specific django apps. If unset, will scrub all installed apps.
+
+(default: None)
+
+### `SCRUBBER_ADDITIONAL_FAKER_PROVIDERS`:
+
+Add additional fake providers to be used by Faker. Must be noted as full dotted path to the provider class.
+
+(default: empty list)
+
+### `SCRUBBER_FAKER_LOCALE`:
+
+Set an alternative locale for Faker used during the scrubbing process.
+
+(default: None, falls back to Django's default locale)
+
+### `SCRUBBER_MAPPING`:
+
+Define a class and a mapper which does not have to live inside the given model. Useful, if you have no control over the
+models code you'd like to scrub.
+
+### `SCRUBBER_STRICT_MODE`:
+
+When strict mode is activated, you have to define a scrubbing policy for every field of every type defined in
+`SCRUBBER_REQUIRED_FIELD_TYPES`. If you have unscrubbed fields and this flag is active, you can't run
+`pyhton manage.py scrub_data`.
+
+### `SCRUBBER_REQUIRED_FIELD_TYPES`:
+
+Defaults to all text-based Django model fields. Usually, privacy-relevant data is only stored in text-fields, numbers
+and booleans (usually) can't contain sensitive personal data. These fields will be checked when running
+`python manage.py scub_validation`.
+
+(default: (models.CharField, models.TextField, models.URLField, models.JSONField, models.GenericIPAddressField,
+ models.EmailField,))
+
+### `SCRUBBER_REQUIRED_FIELD_MODEL_WHITELIST`:
+
+Whitelists a list of models which will not be checked during `scrub_validation` and when
+activating the strict mode. Defaults to the non-privacy-related Django base models.
+
+(default: ['auth.Group', 'auth.Permission', 'contenttypes.ContentType', 'sessions.Session', 'sites.Site',
+'django_scrubber.FakeData',))
+
+````python
+SCRUBBER_MAPPING = {
+ "auth.User": "my_app.scrubbers.UserScrubbers",
+}
+````
+
+(default: {})
+
+## Logging
+
+Scrubber uses the default django logger. The logger name is ``django_scrubber.scrubbers``.
+So if you want to log - for example - to the console, you could set up the logger like this:
+
+````
+LOGGING['loggers']['django_scrubber'] = {
+ 'handlers': ['console'],
+ 'propagate': True,
+ 'level': 'DEBUG',
+}
+````
+
+## Making a new release
+
+[bumpversion](https://github.com/peritus/bumpversion) is used to manage releases.
+
+Add your changes to the [CHANGELOG](./CHANGELOG.md) and run `bumpversion <major|minor|patch>`, then push (including
+tags)
+
+
+# Changelog
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
+and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
+
+<!--
+## [Unreleased]
+-->
+
+## [1.2.0] - 2023-04-01
+### Changed
+- Added scrubber validation - Thanks @GitRon
+- Added strict mode - Thanks @GitRon
+
+## [1.1.0] - 2022-07-11
+### Changed
+- Invalid fields on scrubbers will no longer raise exception but just trigger warnings now
+- Author list completed
+
+## [1.0.0] - 2022-07-11
+### Changed
+- Meta data for python package improved - Thanks @GitRon
+
+## [0.9.0] - 2022-06-27
+### Added
+- Add functionality to scrub third party models like the Django user model, see https://github.com/RegioHelden/django-scrubber#scrubbing-third-party-models - Thanks @GitRon
+- Add tests for Python 3.10 - Thanks @costela
+
+## [0.8.0] - 2022-05-01
+### Added
+- Add `keep-sessions` argument to scrub_data command. Will NOT truncate all (by definition critical) session data. Thanks @GitRon
+- Add `remove-fake-data` argument to scrub_data command. Will truncate the database table storing preprocessed data for the Faker library. Thanks @GitRon
+- Add Django 3.2 and 4.0 to test matrix
+### Changed
+- Remove Python 3.6 from test matrix
+- Remove Django 2.2 and 3.1 from test matrix
+
+## [0.7.0] - 2022-02-24
+### Changed
+- Remove upper boundary for Faker as they release non-breaking major upgrades way too often, please pin a working release in your own app
+
+## [0.6.2] - 2022-02-08
+### Changed
+- Support faker 12.x
+
+## [0.6.1] - 2022-01-25
+### Changed
+- Support faker 11.x
+
+## [0.6.0] - 2021-10-18
+### Added
+- Add support to override Faker locale in scrubber settings
+### Changed
+- Publish coverage only on main repository
+
+## [0.5.6] - 2021-10-08
+### Changed
+- Pin psycopg2 in CI ti 2.8.6 as 2.9+ is incompatible with Django 2.2
+
+## [0.5.5] - 2021-10-08
+### Changed
+- Support faker 9.x
+
+## [0.5.4] - 2021-04-13
+### Changed
+- Support faker 8.x
+
+## [0.5.3] - 2021-02-04
+### Changed
+- Support faker 6.x
+
+## [0.5.2] - 2021-01-12
+### Changed
+- Add tests for Python 3.9
+- Add tests for Django 3.1
+- Support faker 5.x
+- Update dev package requirements
+
+## [0.5.1] - 2020-10-16
+### Changed
+- Fix travis setup
+
+## [0.5.0] - 2020-10-16
+### Added
+- Support for django-model-utils 4.x.x
+### Changed
+- Add compatibility for Faker 3.x.x, remove support for Faker < 0.8.0
+- Remove support for Python 2.7 and 3.5
+- Remove support for Django 1.x
+
+## [0.4.4] - 2019-12-11
+### Fixed
+- add the same version restrictions on faker to setup.py
+
+## [0.4.3] - 2019-12-04
+### Added
+- add empty and null scrubbers
+
+### Changed
+- make `Lorem` scrubber lazy, matching README
+
+### Fixed
+- set more stringent version requirements (faker >= 3 breaks builds)
+
+## [0.4.1] - 2019-11-16
+### Fixed
+- correctly clear fake data model to fix successive calls to `scrub_data` (thanks [Benedikt Bauer](https://github.com/mastacheata))
+
+## [0.4.0] - 2019-11-13
+### Added
+- `Faker` scrubber now supports passing arbitrary arguments to faker providers and also non-text fields (thanks [Benedikt Bauer](https://github.com/mastacheata) and [Ronny Vedrilla](https://github.com/GitRon))
+
+## [0.3.1] - 2018-09-10
+### Fixed
+- [#9](https://github.com/RegioHelden/django-scrubber/pull/9) `Hash` scrubber choking on fields with `max_length=None` - Thanks to [Charlie Denton](https://github.com/meshy)
+
+## [0.3.0] - 2018-09-06
+### Added
+- Finally added some basic tests (thanks [Marco De Felice](https://github.com/md-f))
+- `Hash` scrubber can now also be used on sqlite
+
+### Changed
+- **BREAKING**: scrubbers that are lazily initialized now receive `Field` instances as parameters, instead of field
+ names. If you have custom scrubbers depending on the previous behavior, these should be updated. Accessing the
+ field's name from the object instance is trivial: `field_instance.name`. E.g.: if you have `some_field = MyCustomScrubber`
+ in any of your models' `Scrubbers`, this class must accept a `Field` instance as first parameter.
+ Note that explicitly intializing any of the built-in scrubbers with field names is still supported, so if you were
+ just using built-in scrubbers, you should not be affected by this change.
+- related to the above, `FuncField` derived classes can now do connection-based setup by implementing the
+ `connection_setup` method. This is mostly useful for doing different things based on the DB vendor, and is used to
+ implement `MD5()` on sqlite (see added feature above)
+- Ignore proxy models when scrubbing (thanks [Marco De Felice](https://github.com/md-f))
+- Expand tests to include python 3.7 and django 2.1
+
+## [0.2.1] - 2018-08-14
+### Added
+- Option to scrub only one model from the management command
+- Support loading additional faker providers by config setting SCRUBBER\_ADDITIONAL\_FAKER\_PROVIDERS
+
+### Changed
+- Switched changelog format to the one proposed on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
+
+## [0.2.0] - 2018-08-13
+### Added
+- scrubbers.Concat to make simple concatenation of scrubbers possible
+
+## [0.1.4] - 2018-08-13
+### Changed
+- Make our README look beautiful on PyPI
+
+## [0.1.3] - 2018-08-13
+### Fixed
+- [#1](https://github.com/RegioHelden/django-scrubber/pull/1) badly timed import - Thanks to [Charlie Denton](https://github.com/meshy)
+
+## [0.1.2] - 2018-06-22
+### Changed
+- Use bumpversion and travis to make new releases
+- rename project: django\_scrubber → django-scrubber
+
+## [0.1.0] - 2018-06-22
+### Added
+- Initial release
+
+
+%package help
+Summary: Development documents and examples for django-scrubber
+Provides: python3-django-scrubber-doc
+%description help
+# Django Scrubber
+
+[![Build Status](https://github.com/RegioHelden/django-scrubber/workflows/Build/badge.svg)](https://github.com/RegioHelden/django-scrubber/actions)
+[![PyPI](https://img.shields.io/pypi/v/django-scrubber.svg)](https://pypi.org/project/django-scrubber/)
+[![Downloads](https://pepy.tech/badge/django-scrubber)](https://pepy.tech/project/django-scrubber)
+
+`django_scrubber` is a django app meant to help you anonymize your project's database data. It destructively alters data
+directly on the DB and therefore **should not be used on production**.
+
+The main use case is providing developers with realistic data to use during development, without having to distribute
+your customers' or users' potentially sensitive information.
+To accomplish this, `django_scrubber` should be plugged in a step during the creation of your database dumps.
+
+Simply mark the fields you want to anonymize and call the `scrub_data` management command. Data will be replaced based
+on different *scrubbers* (see below), which define how the anonymous content will be generated.
+
+If you want to be sure that you don't forget any fields in the ongoing development progress, you can use the
+management command `scrub_validation` in your CI/CD pipeline to check for any missing fields.
+
+## Installation
+
+Simply run:
+
+```
+pip install django-scrubber
+```
+
+And add `django_scrubber` to your django `INSTALLED_APPS`. I.e.: in `settings.py` add:
+
+```
+INSTALLED_APPS = [
+ ...
+ 'django_scrubber',
+ ...
+]
+```
+
+## Scrubbing data
+
+In order to scrub data, i.e.: to replace DB data with anonymized versions, `django-scrubber` must know which models and
+fields it should act on, and how the data should be replaced.
+
+There are a few different ways to select which data should be scrubbed, namely: explicitly per model field; or globally
+per name or field type.
+
+Adding scrubbers directly to model, matching scrubbers to fields by name:
+
+```python
+class MyModel(Model):
+ somefield = CharField()
+
+ class Scrubbers:
+ somefield = scrubbers.Hash('somefield')
+```
+
+Adding scrubbers globally, either by field name or field type:
+
+```python
+# (in settings.py)
+
+SCRUBBER_GLOBAL_SCRUBBERS = {
+ 'name': scrubbers.Hash,
+ EmailField: scrubbers.Hash,
+}
+```
+
+Model scrubbers override field-name scrubbers, which in turn override field-type scrubbers.
+
+To disable global scrubbing in some specific model, simply set the respective field scrubber to `None`.
+
+Scrubbers defined for non-existing fields will raise a warning but not fail the scubbing process.
+
+Which mechanism will be used to scrub the selected data is determined by using one of the provided scrubbers
+in `django_scrubber.scrubbers`. See below for a list.
+Alternatively, values may be anything that can be used as a value in a `QuerySet.update()` call (like `Func` instances,
+string literals, etc), or any `callable` that returns such an object when called with a `Field` object as argument.
+
+By default, `django_scrubber` will affect all models from all registered apps. This may lead to issues with third-party
+apps if the global scrubbers are too general. This can be avoided with the `SCRUBBER_APPS_LIST` setting. Using this, you
+might for instance split your `INSTALLED_APPS` into multiple `SYSTEM_APPS` and `LOCAL_APPS`, then
+set `SCRUBBER_APPS_LIST = LOCAL_APPS`, to scrub only your own apps.
+
+Finally just run `./manage.py scrub_data` to **destructively** scrub the registered fields.
+
+### Arguments to the scrub_data command
+
+`--model` Scrub only a single model (format <app_label>.<model_name>)
+
+`--keep-sessions` Will NOT truncate all (by definition critical) session data.
+
+`--remove-fake-data` Will truncate the database table storing preprocessed data for the Faker library.
+
+## Built-In scrubbers
+
+### Empty/Null
+
+The simplest scrubbers: replace the field's content with the empty string or `NULL`, respectively.
+
+```python
+class Scrubbers:
+ somefield = scrubbers.Empty
+ someother = scrubbers.Null
+```
+
+These scrubbers have no options.
+
+### Keeper
+
+When running the validation or want to work in strict mode, you maybe want to actively decide to keep certain data
+instead of scrubbing them. In this case, you can just define `scrubbers.Keep`.
+
+```python
+class Scrubbers:
+ non_critical_field = scrubbers.Keep
+```
+
+These scrubber doesn't have any options.
+
+### Hash
+
+Simple hashing of content:
+
+```python
+class Scrubbers:
+ somefield = scrubbers.Hash # will use the field itself as source
+ someotherfield = scrubbers.Hash('somefield') # can optionally pass a different field name as hashing source
+```
+
+Currently, this uses the MD5 hash which is supported in a wide variety of DB engines. Additionally, since security is
+not the main objective, a shorter hash length has a lower risk of being longer than whatever field it is supposed to
+replace.
+
+### Lorem
+
+Simple scrubber meant to replace `TextField` with a static block of text. Has no options.
+
+```python
+class Scrubbers:
+ somefield = scrubbers.Lorem
+```
+
+### Concat
+
+Wrapper around `django.db.functions.Concat` to enable simple concatenation of scrubbers. This is useful if you want to
+ensure a fields uniqueness through composition of, for instance, the `Hash` and `Faker` (see below) scrubbers.
+
+The following will generate random email addresses by hashing the user-part and using `faker` for the domain part:
+
+```python
+class Scrubbers:
+ email = scrubbers.Concat(scrubbers.Hash('email'), models.Value('@'), scrubbers.Faker('domain_name'))
+```
+
+### Faker
+
+Replaces content with the help of [faker](https://pypi.python.org/pypi/Faker).
+
+```python
+class Scrubbers:
+ first_name = scrubbers.Faker('first_name')
+ last_name = scrubbers.Faker('last_name')
+ past_date = scrubbers.Faker('past_date', start_date="-30d", tzinfo=None)
+```
+
+The replacements are done on the database-level and should therefore be able to cope with large amounts of data with
+reasonable performance.
+
+The `Faker` scrubber requires at least one argument: the faker provider used to generate random data.
+All [faker providers](https://faker.readthedocs.io/en/latest/providers.html) are supported, and you can also register
+your own custom providers.<br />
+Any remaining arguments will be passed through to that provider. Please refer to the faker docs if a provider accepts
+arguments and what to do with them.
+
+#### Locales
+
+Faker will be initialized with the current django `LANGUAGE_CODE` and will populate the DB with localized data. If you
+want localized scrubbing, simply set it to some other value.
+
+#### Idempotency
+
+By default, the faker instance used to populate the DB uses a fixed random seed, in order to ensure different scrubbings
+of the same data generate the same output. This is particularly useful if the scrubbed data is imported as a dump by
+developers, since changing data during troubleshooting would otherwise be confusing.
+
+This behaviour can be changed by setting `SCRUBBER_RANDOM_SEED=None`, which ensures every scrubbing will generate random
+source data.
+
+#### Limitations
+
+Scrubbing unique fields may lead to `IntegrityError`s, since there is no guarantee that the random content will not be
+repeated. Playing with different settings for `SCRUBBER_RANDOM_SEED` and `SCRUBBER_ENTRIES_PER_PROVIDER` may alleviate
+the problem.
+Unfortunately, for performance reasons, the source data for scrubbing with faker is added to the database, and
+arbitrarily increasing `SCRUBBER_ENTRIES_PER_PROVIDER` will significantly slow down scrubbing (besides still not
+guaranteeing uniqueness).
+
+When using `django < 2.1` and working on `sqlite` a bug within django causes field-specific scrubbing (
+e.g. `date_object`) to fail. Please consider using a different database backend or upgrade to the latest django version.
+
+## Scrubbing third-party models
+
+Sometimes you just don't have control over some code, but you still want to scrub the data of a given model.
+
+A good example is the Django user model. It contains sensitive data, and you would have to overwrite the whole model
+just to add the scrubber metaclass.
+
+That's the way to go:
+
+1. Define your Scrubber class **somewhere** in your codebase (like a `scrubbers.py`)
+
+```python
+# scrubbers.py
+class UserScrubbers:
+ scrubbers.Faker('de_DE')
+ first_name = scrubbers.Faker('first_name')
+ last_name = scrubbers.Faker('last_name')
+ username = scrubbers.Faker('uuid4')
+ password = scrubbers.Faker('sha1')
+ last_login = scrubbers.Null
+ email = scrubbers.Concat(first_name, models.Value('.'), last_name, models.Value('@'),
+ models.Value(settings.SCRUBBER_DOMAIN))
+````
+
+2. Set up a mapping between your third-party model and your scrubber class
+
+```python
+# settings.py
+SCRUBBER_MAPPING = {
+ "auth.User": "apps.account.scrubbers.UserScrubbers",
+}
+```
+
+## Settings
+
+### `SCRUBBER_GLOBAL_SCRUBBERS`:
+
+Dictionary of global scrubbers. Keys should be either field names as strings or field type classes. Values should be one
+of the scrubbers provided in `django_scrubber.scrubbers`.
+
+Example:
+
+```python
+SCRUBBER_GLOBAL_SCRUBBERS = {
+ 'name': scrubbers.Hash,
+ EmailField: scrubbers.Hash,
+}
+```
+
+### `SCRUBBER_RANDOM_SEED`:
+
+The seed used when generating random content by the Faker scrubber. Setting this to `None` means each scrubbing will
+generate different data.
+
+(default: 42)
+
+### `SCRUBBER_ENTRIES_PER_PROVIDER`:
+
+Number of entries to use as source for Faker scrubber. Increasing this value will increase the randomness of generated
+data, but decrease performance.
+
+(default: 1000)
+
+### `SCRUBBER_SKIP_UNMANAGED`:
+
+Do not attempt to scrub models which are not managed by the ORM.
+
+(default: True)
+
+### `SCRUBBER_APPS_LIST`:
+
+Only scrub models belonging to these specific django apps. If unset, will scrub all installed apps.
+
+(default: None)
+
+### `SCRUBBER_ADDITIONAL_FAKER_PROVIDERS`:
+
+Add additional fake providers to be used by Faker. Must be noted as full dotted path to the provider class.
+
+(default: empty list)
+
+### `SCRUBBER_FAKER_LOCALE`:
+
+Set an alternative locale for Faker used during the scrubbing process.
+
+(default: None, falls back to Django's default locale)
+
+### `SCRUBBER_MAPPING`:
+
+Define a class and a mapper which does not have to live inside the given model. Useful, if you have no control over the
+models code you'd like to scrub.
+
+### `SCRUBBER_STRICT_MODE`:
+
+When strict mode is activated, you have to define a scrubbing policy for every field of every type defined in
+`SCRUBBER_REQUIRED_FIELD_TYPES`. If you have unscrubbed fields and this flag is active, you can't run
+`pyhton manage.py scrub_data`.
+
+### `SCRUBBER_REQUIRED_FIELD_TYPES`:
+
+Defaults to all text-based Django model fields. Usually, privacy-relevant data is only stored in text-fields, numbers
+and booleans (usually) can't contain sensitive personal data. These fields will be checked when running
+`python manage.py scub_validation`.
+
+(default: (models.CharField, models.TextField, models.URLField, models.JSONField, models.GenericIPAddressField,
+ models.EmailField,))
+
+### `SCRUBBER_REQUIRED_FIELD_MODEL_WHITELIST`:
+
+Whitelists a list of models which will not be checked during `scrub_validation` and when
+activating the strict mode. Defaults to the non-privacy-related Django base models.
+
+(default: ['auth.Group', 'auth.Permission', 'contenttypes.ContentType', 'sessions.Session', 'sites.Site',
+'django_scrubber.FakeData',))
+
+````python
+SCRUBBER_MAPPING = {
+ "auth.User": "my_app.scrubbers.UserScrubbers",
+}
+````
+
+(default: {})
+
+## Logging
+
+Scrubber uses the default django logger. The logger name is ``django_scrubber.scrubbers``.
+So if you want to log - for example - to the console, you could set up the logger like this:
+
+````
+LOGGING['loggers']['django_scrubber'] = {
+ 'handlers': ['console'],
+ 'propagate': True,
+ 'level': 'DEBUG',
+}
+````
+
+## Making a new release
+
+[bumpversion](https://github.com/peritus/bumpversion) is used to manage releases.
+
+Add your changes to the [CHANGELOG](./CHANGELOG.md) and run `bumpversion <major|minor|patch>`, then push (including
+tags)
+
+
+# Changelog
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
+and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
+
+<!--
+## [Unreleased]
+-->
+
+## [1.2.0] - 2023-04-01
+### Changed
+- Added scrubber validation - Thanks @GitRon
+- Added strict mode - Thanks @GitRon
+
+## [1.1.0] - 2022-07-11
+### Changed
+- Invalid fields on scrubbers will no longer raise exception but just trigger warnings now
+- Author list completed
+
+## [1.0.0] - 2022-07-11
+### Changed
+- Meta data for python package improved - Thanks @GitRon
+
+## [0.9.0] - 2022-06-27
+### Added
+- Add functionality to scrub third party models like the Django user model, see https://github.com/RegioHelden/django-scrubber#scrubbing-third-party-models - Thanks @GitRon
+- Add tests for Python 3.10 - Thanks @costela
+
+## [0.8.0] - 2022-05-01
+### Added
+- Add `keep-sessions` argument to scrub_data command. Will NOT truncate all (by definition critical) session data. Thanks @GitRon
+- Add `remove-fake-data` argument to scrub_data command. Will truncate the database table storing preprocessed data for the Faker library. Thanks @GitRon
+- Add Django 3.2 and 4.0 to test matrix
+### Changed
+- Remove Python 3.6 from test matrix
+- Remove Django 2.2 and 3.1 from test matrix
+
+## [0.7.0] - 2022-02-24
+### Changed
+- Remove upper boundary for Faker as they release non-breaking major upgrades way too often, please pin a working release in your own app
+
+## [0.6.2] - 2022-02-08
+### Changed
+- Support faker 12.x
+
+## [0.6.1] - 2022-01-25
+### Changed
+- Support faker 11.x
+
+## [0.6.0] - 2021-10-18
+### Added
+- Add support to override Faker locale in scrubber settings
+### Changed
+- Publish coverage only on main repository
+
+## [0.5.6] - 2021-10-08
+### Changed
+- Pin psycopg2 in CI ti 2.8.6 as 2.9+ is incompatible with Django 2.2
+
+## [0.5.5] - 2021-10-08
+### Changed
+- Support faker 9.x
+
+## [0.5.4] - 2021-04-13
+### Changed
+- Support faker 8.x
+
+## [0.5.3] - 2021-02-04
+### Changed
+- Support faker 6.x
+
+## [0.5.2] - 2021-01-12
+### Changed
+- Add tests for Python 3.9
+- Add tests for Django 3.1
+- Support faker 5.x
+- Update dev package requirements
+
+## [0.5.1] - 2020-10-16
+### Changed
+- Fix travis setup
+
+## [0.5.0] - 2020-10-16
+### Added
+- Support for django-model-utils 4.x.x
+### Changed
+- Add compatibility for Faker 3.x.x, remove support for Faker < 0.8.0
+- Remove support for Python 2.7 and 3.5
+- Remove support for Django 1.x
+
+## [0.4.4] - 2019-12-11
+### Fixed
+- add the same version restrictions on faker to setup.py
+
+## [0.4.3] - 2019-12-04
+### Added
+- add empty and null scrubbers
+
+### Changed
+- make `Lorem` scrubber lazy, matching README
+
+### Fixed
+- set more stringent version requirements (faker >= 3 breaks builds)
+
+## [0.4.1] - 2019-11-16
+### Fixed
+- correctly clear fake data model to fix successive calls to `scrub_data` (thanks [Benedikt Bauer](https://github.com/mastacheata))
+
+## [0.4.0] - 2019-11-13
+### Added
+- `Faker` scrubber now supports passing arbitrary arguments to faker providers and also non-text fields (thanks [Benedikt Bauer](https://github.com/mastacheata) and [Ronny Vedrilla](https://github.com/GitRon))
+
+## [0.3.1] - 2018-09-10
+### Fixed
+- [#9](https://github.com/RegioHelden/django-scrubber/pull/9) `Hash` scrubber choking on fields with `max_length=None` - Thanks to [Charlie Denton](https://github.com/meshy)
+
+## [0.3.0] - 2018-09-06
+### Added
+- Finally added some basic tests (thanks [Marco De Felice](https://github.com/md-f))
+- `Hash` scrubber can now also be used on sqlite
+
+### Changed
+- **BREAKING**: scrubbers that are lazily initialized now receive `Field` instances as parameters, instead of field
+ names. If you have custom scrubbers depending on the previous behavior, these should be updated. Accessing the
+ field's name from the object instance is trivial: `field_instance.name`. E.g.: if you have `some_field = MyCustomScrubber`
+ in any of your models' `Scrubbers`, this class must accept a `Field` instance as first parameter.
+ Note that explicitly intializing any of the built-in scrubbers with field names is still supported, so if you were
+ just using built-in scrubbers, you should not be affected by this change.
+- related to the above, `FuncField` derived classes can now do connection-based setup by implementing the
+ `connection_setup` method. This is mostly useful for doing different things based on the DB vendor, and is used to
+ implement `MD5()` on sqlite (see added feature above)
+- Ignore proxy models when scrubbing (thanks [Marco De Felice](https://github.com/md-f))
+- Expand tests to include python 3.7 and django 2.1
+
+## [0.2.1] - 2018-08-14
+### Added
+- Option to scrub only one model from the management command
+- Support loading additional faker providers by config setting SCRUBBER\_ADDITIONAL\_FAKER\_PROVIDERS
+
+### Changed
+- Switched changelog format to the one proposed on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
+
+## [0.2.0] - 2018-08-13
+### Added
+- scrubbers.Concat to make simple concatenation of scrubbers possible
+
+## [0.1.4] - 2018-08-13
+### Changed
+- Make our README look beautiful on PyPI
+
+## [0.1.3] - 2018-08-13
+### Fixed
+- [#1](https://github.com/RegioHelden/django-scrubber/pull/1) badly timed import - Thanks to [Charlie Denton](https://github.com/meshy)
+
+## [0.1.2] - 2018-06-22
+### Changed
+- Use bumpversion and travis to make new releases
+- rename project: django\_scrubber → django-scrubber
+
+## [0.1.0] - 2018-06-22
+### Added
+- Initial release
+
+
+%prep
+%autosetup -n django-scrubber-1.2.0
+
+%build
+%py3_build
+
+%install
+%py3_install
+install -d -m755 %{buildroot}/%{_pkgdocdir}
+if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi
+if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi
+if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi
+if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi
+pushd %{buildroot}
+if [ -d usr/lib ]; then
+ find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/lib64 ]; then
+ find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/bin ]; then
+ find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/sbin ]; then
+ find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+touch doclist.lst
+if [ -d usr/share/man ]; then
+ find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst
+fi
+popd
+mv %{buildroot}/filelist.lst .
+mv %{buildroot}/doclist.lst .
+
+%files -n python3-django-scrubber -f filelist.lst
+%dir %{python3_sitelib}/*
+
+%files help -f doclist.lst
+%{_docdir}/*
+
+%changelog
+* Mon May 15 2023 Python_Bot <Python_Bot@openeuler.org> - 1.2.0-1
+- Package Spec generated