[
  {
    "path": ".coveragerc",
    "content": "[run]\nsource = django_dynamic_fixture\nomit = */migrations/*\n\n[report]\nexclude_lines =\n    pragma: no cover\n    def __repr__\n    if self.debug:\n    if settings.DEBUG\n    raise AssertionError\n    raise NotImplementedError\n    if 0:\n    if __name__ == .__main__.:\n    def __iter__\n    def __len__\n    __metaclass__\n    def __init__\n    class MetaChoice\n"
  },
  {
    "path": ".flake8",
    "content": "[flake8]\nmax-line-length=200\nexclude=.git,*migrations/*,tmp/*,scripts/*,docs/*,*/tests/*,proto,env/*\nmax-complexity=15\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: [paulocheque]\n#patreon: # Replace with a single Patreon username\n#open_collective: # Replace with a single Open Collective username\n#ko_fi: # Replace with a single Ko-fi username\n#tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel\n#community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry\n#liberapay: # Replace with a single Liberapay username\n#issuehunt: # Replace with a single IssueHunt username\n#lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry\n#polar: # Replace with a single Polar username\n#buy_me_a_coffee: # Replace with a single Buy Me a Coffee username\n#custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Building and Testing\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n    branches:\n      - master\n\njobs:\n  build:\n    runs-on: 'ubuntu-latest'\n    strategy:\n      matrix:\n        python_version:\n          - '3.8'\n          - '3.9'\n          - '3.10'\n          - '3.11'\n        django_version:\n          - '4.0'\n          - '4.1'\n          - '4.2'\n\n    services:\n      postgres:\n        # https://github.com/postgis/docker-postgis/blob/master/15-3.4/alpine/Dockerfile\n        image: postgis/postgis:15-3.4-alpine\n        env:\n          POSTGRES_DB: ddf\n          POSTGRES_USER: ddf_user\n          POSTGRES_PASSWORD: ddf_pass\n        ports:\n          # Random free port\n          - 5432/tcp\n        # Set health checks to wait until postgres has started\n        options: >-\n          --health-cmd pg_isready\n          --health-interval 10s\n          --health-timeout 5s\n          --health-retries 5\n\n    steps:\n      - name: 'Install OS dependencies (Ubuntu)'\n        if: runner.os == 'Linux'\n        run: |\n            # https://docs.djangoproject.com/en/4.2/ref/contrib/gis/install/geolibs/\n            # GDAL_LIBRARY_PATH: /usr/lib/libgdal.so.*\n            # GEOS_LIBRARY_PATH: /usr/lib/libgeos_c.so.*\n            # ln -s /usr/lib/libgdal.so.32 /usr/lib/libgdal.so \\\n            # ln -s /usr/lib/libgeos_c.so.1 /usr/lib/libgeos_c.so\n            # ln -s /usr/lib/libproj.so.25 /usr/lib/libproj.so \\\n            sudo apt-get update \\\n            && sudo apt-get install -y binutils libproj-dev gdal-bin\n\n      - name: 'Set up Python ${{ matrix.python_version }}'\n        uses: actions/setup-python@v4\n        with:\n          python-version: ${{ matrix.python_version }}\n\n      - name: 'Checkout DDF code'\n        uses: actions/checkout@v3\n\n      - name: 'Install Python dependencies'\n        run: |\n          pip install -r requirements.txt\n          pip install -r requirements-dev.txt\n          pip install pytest-django\n          pip install django~=${{ matrix.django_version }}\n          pip install jsonfield==3.1.0\n          pip install django-polymorphic==3.1.0\n\n      - name: 'Testing with SQLite'\n        run: pytest --create-db --reuse-db --no-migrations --ds=settings_sqlite --maxfail=2\n\n      - name: 'Coverage with SQLite'\n        run: pytest --create-db --reuse-db --no-migrations -v --cov=django_dynamic_fixture\n\n      - name: 'Testing with Postgres'\n        env:\n          POSTGRES_HOST: localhost\n          POSTGRES_PORT: ${{ job.services.postgres.ports[5432] }}\n          POSTGRES_DB: ddf\n          POSTGRES_USER: ddf_user\n          POSTGRES_PASSWORD: ddf_pass\n        run: |\n          pip install psycopg2\n          pytest --create-db --reuse-db --no-migrations --ds=settings_postgres --maxfail=2\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\n.idea/\ndist/\nbuild/\ncover/\n.settings\n.project\n.pydevproject\n.settings/org.eclipse.core.resources.prefs\n.settings/org.eclipse.core.runtime.prefs\n.settings/org.eclipse.ltk.core.refactoring.prefs\n.settings/org.eclipse.wst.validation.prefs\n*.bat\n*.sh\n*.coverage\n*.pyc\n*.pyo\n*.log\n.noseids\n*.sqlite\nvirtualenv*\n\ndjango_dynamic_fixture.egg-info\nenv/\nenvpypy\nenv26\nenv27\nenv32\nenv33\nenv34\nenv2.6\nenv2.7\nenv3.2\nenv3.3\nenv3.4\n.tox\ntest_:memory:\n.eggs/\n\nddf_compatibility_report.*\nhtmlcov/*"
  },
  {
    "path": ".pylintrc",
    "content": "[MASTER]\n\n# A comma-separated list of package or module names from where C extensions may\n# be loaded. Extensions are loading into the active Python interpreter and may\n# run arbitrary code.\nextension-pkg-whitelist=\n\n# Add files or directories to the blacklist. They should be base names, not\n# paths.\nignore=CVS\n\n# Add files or directories matching the regex patterns to the blacklist. The\n# regex matches against base names, not paths.\nignore-patterns=\n\n# Python code to execute, usually for sys.path manipulation such as\n# pygtk.require().\n#init-hook=\n\n# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the\n# number of processors available to use.\njobs=1\n\n# Control the amount of potential inferred values when inferring a single\n# object. This can help the performance when dealing with large functions or\n# complex, nested conditions.\nlimit-inference-results=100\n\n# List of plugins (as comma separated values of python module names) to load,\n# usually to register additional checkers.\nload-plugins=\n\n# Pickle collected data for later comparisons.\npersistent=yes\n\n# Specify a configuration file.\n#rcfile=\n\n# When enabled, pylint would attempt to guess common misconfiguration and emit\n# user-friendly hints instead of false-positive error messages.\nsuggestion-mode=yes\n\n# Allow loading of arbitrary C extensions. Extensions are imported into the\n# active Python interpreter and may run arbitrary code.\nunsafe-load-any-extension=no\n\n\n[MESSAGES CONTROL]\n\n# Only show warnings with the listed confidence levels. Leave empty to show\n# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED.\nconfidence=\n\n# Disable the message, report, category or checker with the given id(s). You\n# can either give multiple identifiers separated by comma (,) or put this\n# option multiple times (only on the command line, not in the configuration\n# file where it should appear only once). You can also use \"--disable=all\" to\n# disable everything first and then reenable specific checks. For example, if\n# you want to run only the similarities checker, you can use \"--disable=all\n# --enable=similarities\". If you want to run only the classes checker, but have\n# no Warning level messages displayed, use \"--disable=all --enable=classes\n# --disable=W\".\ndisable=print-statement,\n        parameter-unpacking,\n        unpacking-in-except,\n        old-raise-syntax,\n        backtick,\n        long-suffix,\n        old-ne-operator,\n        old-octal-literal,\n        import-star-module-level,\n        non-ascii-bytes-literal,\n        raw-checker-failed,\n        bad-inline-option,\n        locally-disabled,\n        file-ignored,\n        suppressed-message,\n        useless-suppression,\n        deprecated-pragma,\n        use-symbolic-message-instead,\n        apply-builtin,\n        basestring-builtin,\n        buffer-builtin,\n        cmp-builtin,\n        coerce-builtin,\n        execfile-builtin,\n        file-builtin,\n        long-builtin,\n        raw_input-builtin,\n        reduce-builtin,\n        standarderror-builtin,\n        unicode-builtin,\n        xrange-builtin,\n        coerce-method,\n        delslice-method,\n        getslice-method,\n        setslice-method,\n        no-absolute-import,\n        old-division,\n        dict-iter-method,\n        dict-view-method,\n        next-method-called,\n        metaclass-assignment,\n        indexing-exception,\n        raising-string,\n        reload-builtin,\n        oct-method,\n        hex-method,\n        nonzero-method,\n        cmp-method,\n        input-builtin,\n        round-builtin,\n        intern-builtin,\n        unichr-builtin,\n        map-builtin-not-iterating,\n        zip-builtin-not-iterating,\n        range-builtin-not-iterating,\n        filter-builtin-not-iterating,\n        using-cmp-argument,\n        eq-without-hash,\n        div-method,\n        idiv-method,\n        rdiv-method,\n        exception-message-attribute,\n        invalid-str-codec,\n        sys-max-int,\n        bad-python3-import,\n        deprecated-string-function,\n        deprecated-str-translate-call,\n        deprecated-itertools-function,\n        deprecated-types-field,\n        next-method-defined,\n        dict-items-not-iterating,\n        dict-keys-not-iterating,\n        dict-values-not-iterating,\n        deprecated-operator-function,\n        deprecated-urllib-function,\n        xreadlines-attribute,\n        deprecated-sys-function,\n        exception-escape,\n        comprehension-escape\n\n# Enable the message, report, category or checker with the given id(s). You can\n# either give multiple identifier separated by comma (,) or put this option\n# multiple time (only on the command line, not in the configuration file where\n# it should appear only once). See also the \"--disable\" option for examples.\nenable=c-extension-no-member\n\n\n[REPORTS]\n\n# Python expression which should return a score less than or equal to 10. You\n# have access to the variables 'error', 'warning', 'refactor', and 'convention'\n# which contain the number of messages in each category, as well as 'statement'\n# which is the total number of statements analyzed. This score is used by the\n# global evaluation report (RP0004).\nevaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)\n\n# Template used to display messages. This is a python new-style format string\n# used to format the message information. See doc for all details.\n#msg-template=\n\n# Set the output format. Available formats are text, parseable, colorized, json\n# and msvs (visual studio). You can also give a reporter class, e.g.\n# mypackage.mymodule.MyReporterClass.\noutput-format=text\n\n# Tells whether to display a full report or only the messages.\nreports=no\n\n# Activate the evaluation score.\nscore=yes\n\n\n[REFACTORING]\n\n# Maximum number of nested blocks for function / method body\nmax-nested-blocks=5\n\n# Complete name of functions that never returns. When checking for\n# inconsistent-return-statements if a never returning function is called then\n# it will be considered as an explicit return statement and no message will be\n# printed.\nnever-returning-functions=sys.exit\n\n\n[LOGGING]\n\n# Format style used to check logging format string. `old` means using %\n# formatting, `new` is for `{}` formatting,and `fstr` is for f-strings.\nlogging-format-style=old\n\n# Logging modules to check that the string format arguments are in logging\n# function parameter format.\nlogging-modules=logging\n\n\n[SPELLING]\n\n# Limits count of emitted suggestions for spelling mistakes.\nmax-spelling-suggestions=4\n\n# Spelling dictionary name. Available dictionaries: none. To make it work,\n# install the python-enchant package.\nspelling-dict=\n\n# List of comma separated words that should not be checked.\nspelling-ignore-words=\n\n# A path to a file that contains the private dictionary; one word per line.\nspelling-private-dict-file=\n\n# Tells whether to store unknown words to the private dictionary (see the\n# --spelling-private-dict-file option) instead of raising a message.\nspelling-store-unknown-words=no\n\n\n[MISCELLANEOUS]\n\n# List of note tags to take in consideration, separated by a comma.\nnotes=FIXME,\n      XXX,\n      TODO\n\n\n[TYPECHECK]\n\n# List of decorators that produce context managers, such as\n# contextlib.contextmanager. Add to this list to register other decorators that\n# produce valid context managers.\ncontextmanager-decorators=contextlib.contextmanager\n\n# List of members which are set dynamically and missed by pylint inference\n# system, and so shouldn't trigger E1101 when accessed. Python regular\n# expressions are accepted.\ngenerated-members=\n\n# Tells whether missing members accessed in mixin class should be ignored. A\n# mixin class is detected if its name ends with \"mixin\" (case insensitive).\nignore-mixin-members=yes\n\n# Tells whether to warn about missing members when the owner of the attribute\n# is inferred to be None.\nignore-none=yes\n\n# This flag controls whether pylint should warn about no-member and similar\n# checks whenever an opaque object is returned when inferring. The inference\n# can return multiple potential results while evaluating a Python object, but\n# some branches might not be evaluated, which results in partial inference. In\n# that case, it might be useful to still emit no-member and other checks for\n# the rest of the inferred objects.\nignore-on-opaque-inference=yes\n\n# List of class names for which member attributes should not be checked (useful\n# for classes with dynamically set attributes). This supports the use of\n# qualified names.\nignored-classes=optparse.Values,thread._local,_thread._local\n\n# List of module names for which member attributes should not be checked\n# (useful for modules/projects where namespaces are manipulated during runtime\n# and thus existing member attributes cannot be deduced by static analysis). It\n# supports qualified module names, as well as Unix pattern matching.\nignored-modules=\n\n# Show a hint with possible names when a member name was not found. The aspect\n# of finding the hint is based on edit distance.\nmissing-member-hint=yes\n\n# The minimum edit distance a name should have in order to be considered a\n# similar match for a missing member name.\nmissing-member-hint-distance=1\n\n# The total number of similar names that should be taken in consideration when\n# showing a hint for a missing member.\nmissing-member-max-choices=1\n\n# List of decorators that change the signature of a decorated function.\nsignature-mutators=\n\n\n[VARIABLES]\n\n# List of additional names supposed to be defined in builtins. Remember that\n# you should avoid defining new builtins when possible.\nadditional-builtins=\n\n# Tells whether unused global variables should be treated as a violation.\nallow-global-unused-variables=yes\n\n# List of strings which can identify a callback function by name. A callback\n# name must start or end with one of those strings.\ncallbacks=cb_,\n          _cb\n\n# A regular expression matching the name of dummy variables (i.e. expected to\n# not be used).\ndummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_\n\n# Argument names that match this expression will be ignored. Default to name\n# with leading underscore.\nignored-argument-names=_.*|^ignored_|^unused_\n\n# Tells whether we should check for unused import in __init__ files.\ninit-import=no\n\n# List of qualified module names which can have objects that can redefine\n# builtins.\nredefining-builtins-modules=past.builtins,future.builtins,builtins,io\n\n\n[FORMAT]\n\n# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.\nexpected-line-ending-format=\n\n# Regexp for a line that is allowed to be longer than the limit.\nignore-long-lines=^\\s*(# )?<?https?://\\S+>?$\n\n# Number of spaces of indent required inside a hanging or continued line.\nindent-after-paren=4\n\n# String used as indentation unit. This is usually \"    \" (4 spaces) or \"\\t\" (1\n# tab).\nindent-string='    '\n\n# Maximum number of characters on a single line.\nmax-line-length=200\n\n# Maximum number of lines in a module.\nmax-module-lines=1000\n\n# List of optional constructs for which whitespace checking is disabled. `dict-\n# separator` is used to allow tabulation in dicts, etc.: {1  : 1,\\n222: 2}.\n# `trailing-comma` allows a space between comma and closing bracket: (a, ).\n# `empty-line` allows space-only lines.\nno-space-check=trailing-comma,\n               dict-separator\n\n# Allow the body of a class to be on the same line as the declaration if body\n# contains single statement.\nsingle-line-class-stmt=no\n\n# Allow the body of an if to be on the same line as the test if there is no\n# else.\nsingle-line-if-stmt=no\n\n\n[SIMILARITIES]\n\n# Ignore comments when computing similarities.\nignore-comments=yes\n\n# Ignore docstrings when computing similarities.\nignore-docstrings=yes\n\n# Ignore imports when computing similarities.\nignore-imports=no\n\n# Minimum lines number of a similarity.\nmin-similarity-lines=4\n\n\n[BASIC]\n\n# Naming style matching correct argument names.\nargument-naming-style=snake_case\n\n# Regular expression matching correct argument names. Overrides argument-\n# naming-style.\n#argument-rgx=\n\n# Naming style matching correct attribute names.\nattr-naming-style=snake_case\n\n# Regular expression matching correct attribute names. Overrides attr-naming-\n# style.\n#attr-rgx=\n\n# Bad variable names which should always be refused, separated by a comma.\nbad-names=foo,\n          bar,\n          baz,\n          toto,\n          tutu,\n          tata\n\n# Naming style matching correct class attribute names.\nclass-attribute-naming-style=any\n\n# Regular expression matching correct class attribute names. Overrides class-\n# attribute-naming-style.\n#class-attribute-rgx=\n\n# Naming style matching correct class names.\nclass-naming-style=PascalCase\n\n# Regular expression matching correct class names. Overrides class-naming-\n# style.\n#class-rgx=\n\n# Naming style matching correct constant names.\nconst-naming-style=UPPER_CASE\n\n# Regular expression matching correct constant names. Overrides const-naming-\n# style.\n#const-rgx=\n\n# Minimum line length for functions/classes that require docstrings, shorter\n# ones are exempt.\ndocstring-min-length=-1\n\n# Naming style matching correct function names.\nfunction-naming-style=snake_case\n\n# Regular expression matching correct function names. Overrides function-\n# naming-style.\n#function-rgx=\n\n# Good variable names which should always be accepted, separated by a comma.\ngood-names=i,\n           j,\n           k,\n           ex,\n           Run,\n           _\n\n# Include a hint for the correct naming format with invalid-name.\ninclude-naming-hint=no\n\n# Naming style matching correct inline iteration names.\ninlinevar-naming-style=any\n\n# Regular expression matching correct inline iteration names. Overrides\n# inlinevar-naming-style.\n#inlinevar-rgx=\n\n# Naming style matching correct method names.\nmethod-naming-style=snake_case\n\n# Regular expression matching correct method names. Overrides method-naming-\n# style.\n#method-rgx=\n\n# Naming style matching correct module names.\nmodule-naming-style=snake_case\n\n# Regular expression matching correct module names. Overrides module-naming-\n# style.\n#module-rgx=\n\n# Colon-delimited sets of names that determine each other's naming style when\n# the name regexes allow several styles.\nname-group=\n\n# Regular expression which should only match function or class names that do\n# not require a docstring.\nno-docstring-rgx=^_\n\n# List of decorators that produce properties, such as abc.abstractproperty. Add\n# to this list to register other decorators that produce valid properties.\n# These decorators are taken in consideration only for invalid-name.\nproperty-classes=abc.abstractproperty\n\n# Naming style matching correct variable names.\nvariable-naming-style=snake_case\n\n# Regular expression matching correct variable names. Overrides variable-\n# naming-style.\n#variable-rgx=\n\n\n[STRING]\n\n# This flag controls whether the implicit-str-concat-in-sequence should\n# generate a warning on implicit string concatenation in sequences defined over\n# several lines.\ncheck-str-concat-over-line-jumps=no\n\n\n[IMPORTS]\n\n# List of modules that can be imported at any level, not just the top level\n# one.\nallow-any-import-level=\n\n# Allow wildcard imports from modules that define __all__.\nallow-wildcard-with-all=no\n\n# Analyse import fallback blocks. This can be used to support both Python 2 and\n# 3 compatible code, which means that the block might have code that exists\n# only in one or another interpreter, leading to false positives when analysed.\nanalyse-fallback-blocks=no\n\n# Deprecated modules which should not be used, separated by a comma.\ndeprecated-modules=optparse,tkinter.tix\n\n# Create a graph of external dependencies in the given file (report RP0402 must\n# not be disabled).\next-import-graph=\n\n# Create a graph of every (i.e. internal and external) dependencies in the\n# given file (report RP0402 must not be disabled).\nimport-graph=\n\n# Create a graph of internal dependencies in the given file (report RP0402 must\n# not be disabled).\nint-import-graph=\n\n# Force import order to recognize a module as part of the standard\n# compatibility libraries.\nknown-standard-library=\n\n# Force import order to recognize a module as part of a third party library.\nknown-third-party=enchant\n\n# Couples of modules and preferred modules, separated by a comma.\npreferred-modules=\n\n\n[CLASSES]\n\n# List of method names used to declare (i.e. assign) instance attributes.\ndefining-attr-methods=__init__,\n                      __new__,\n                      setUp,\n                      __post_init__\n\n# List of member names, which should be excluded from the protected access\n# warning.\nexclude-protected=_asdict,\n                  _fields,\n                  _replace,\n                  _source,\n                  _make\n\n# List of valid names for the first argument in a class method.\nvalid-classmethod-first-arg=cls\n\n# List of valid names for the first argument in a metaclass class method.\nvalid-metaclass-classmethod-first-arg=cls\n\n\n[DESIGN]\n\n# Maximum number of arguments for function / method.\nmax-args=5\n\n# Maximum number of attributes for a class (see R0902).\nmax-attributes=7\n\n# Maximum number of boolean expressions in an if statement (see R0916).\nmax-bool-expr=5\n\n# Maximum number of branch for function / method body.\nmax-branches=12\n\n# Maximum number of locals for function / method body.\nmax-locals=15\n\n# Maximum number of parents for a class (see R0901).\nmax-parents=7\n\n# Maximum number of public methods for a class (see R0904).\nmax-public-methods=20\n\n# Maximum number of return / yield for function / method body.\nmax-returns=6\n\n# Maximum number of statements in function / method body.\nmax-statements=50\n\n# Minimum number of public methods for a class (see R0903).\nmin-public-methods=2\n\n\n[EXCEPTIONS]\n\n# Exceptions that will emit a warning when being caught. Defaults to\n# \"BaseException, Exception\".\novergeneral-exceptions=BaseException,\n                       Exception\n"
  },
  {
    "path": ".python-version",
    "content": "3.7.17\n3.8.17\n3.9.17\n3.10.12\n3.11.4\n"
  },
  {
    "path": ".readthedocs.yaml",
    "content": "# https://docs.readthedocs.io/en/stable/config-file/v2.html\nversion: 2\n\nbuild:\n  os: ubuntu-22.04\n  tools:\n    python: \"3.11\"\n\nsphinx:\n  configuration: docs/source/conf.py\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "MIT license: http://opensource.org/licenses/MIT\n\nCopyright (c) <2013> <Paulo Cheque>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n\nApache 2.0\n\nCopyright [2013] [Paulo Cheque]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License."
  },
  {
    "path": "MANIFEST.in",
    "content": ""
  },
  {
    "path": "Makefile",
    "content": "VERSION=4.0.1\n\n# Python env tasks\n\nclean:\n\tclear\n\t@find . -type f -name \"*.py[co]\" -delete\n\t@find . -type d -name \"__pycache__\" -delete\n\trm -rf *.egg\n\trm -rf *.egg-info/\n\trm -rf *.log\n\trm -rf ~*\n\trm -rf data/\n\trm -rf dist/\n\trm -rf build/\n\trm -rf .eggs/\n\trm -rf .tox/\n\t#rm -rf env/\n\nos_deps:\n\tbrew install gdal\n\nprepare:\n\tclear ; python3.11 -m venv env\n\ndeps:\n\tclear\n\tenv/bin/python -m pip install --upgrade pip\n\tenv/bin/python -m pip install --upgrade setuptools wheel\n\tenv/bin/pip install -r requirements.txt\n\tenv/bin/pip install -r requirements-dev.txt\n\tenv/bin/pip list\n\nshell:\n\t#clear ; env/bin/python -i -c \"from ddf import *\"\n\tclear ; env/bin/python manage.py shell\n\t# from ddf import *\n\n# Python code tasks\n\ncompile:\n\tenv/bin/python -OO -m compileall .\n\ntest:\n\t# Run specific test:\n\t# TESTS=django_dynamic_fixture.tests.FILE::CLASS::METHOD make test\n\tclear ; time env/bin/pytest --create-db --reuse-db --no-migrations ${TESTS}\n\ntestfailed:\n\tclear ; env/bin/pytest --create-db --reuse-db --no-migrations ${TESTS} --last-failed\n\nconfig_postgres:\n\tpsql -U postgres -c \"create extension postgis\"\n\t# set up postgresql\n\tpsql -U postgres -c \"create role cacheops login superuser\"\n\t# postgis django backend requires these to exist\n\tpsql -U postgres -c \"create database cacheops\"\n\tpsql -U postgres -c \"create database cacheops_slave\"\n\t# create db and user\n\tpsql -c \"CREATE DATABASE ddf;\" -U postgres\n\tpsql -c \"CREATE USER ddf_user WITH PASSWORD 'ddf_pass';\" -U postgres\n\tpsql -c \"ALTER USER ddf_user CREATEDB;\" -U postgres\n\tpsql -c \"ALTER USER ddf_user WITH SUPERUSER;\" -U postgres\n\ntest_postgres:\n\t# TESTS=django_dynamic_fixture.tests.FILE::CLASS::METHOD make test_postgres\n\tclear ; env/bin/pytest --reuse-db --no-migrations --ds=settings_postgres ${TESTS}\n\ntest_mysql:\n\t# TESTS=django_dynamic_fixture.tests.FILE::CLASS::METHOD make test_mysql\n\tclear ; env/bin/pytest --reuse-db --no-migrations --ds=settings_mysql ${TESTS}\n\ncov:\n\tclear ; env/bin/pytest --create-db --reuse-db --no-migrations -v --cov=django_dynamic_fixture --cov-report html\n\tcp htmlcov/index.html docs/source/_static/coverage.html\n\topen htmlcov/index.html\n\ncode_style:\n\t# Code Style\n\tclear ; env/bin/pylint ddf django_dynamic_fixture queries\n\ncode_checking:\n\t# Code error checking\n\tclear ; env/bin/python -m pyflakes ddf django_dynamic_fixture queries\n\ncode_feedbacks:\n\t# PEP8, code style and circular complexity\n\tclear ; env/bin/flake8 ddf django_dynamic_fixture queries\n\ncode_ruff:\n\tclear ; env/bin/ruff check .\n\t#clear ; env/bin/ruff check . --fix\n\ncheck: code_style code_checking code_feedbacks code_ruff\n\ninstall_precommit_hooks: code_ruff\n\tclear ; env/bin/ruff check .\n\tenv/bin/pre-commit install\n\ndoc: cov\n\tclear ; cd docs ; make clean html ; open build/html/index.html\n\ntox:\n\t#brew update ; brew install pyenv\n\t#pyenv install 3.8 3.9 3.10 3.11\n\t#pyenv versions\n\t#pyenv local 3.7 3.8 3.9 3.10 3.11\n\tclear ; time env/bin/tox --parallel all\n\nbuild: clean os_deps prepare deps test cov\n\n# Python package tasks\n\nlib: clean test cov doc\n\t# \tclear ; env/bin/python setup.py build\n\t# \tclear ; env/bin/python setup.py sdist\n\tclear ; env/bin/python -m build\n\tclear ; env/bin/twine check dist/*\n\npublish: lib\n\t# Fixing Python 3 Certificates\n\t# /Applications/Python\\ 3.7/Install\\ Certificates.command\n\t# Manual upload to PypI\n\t# http://pypi.python.org/pypi/THE-PROJECT\n\t# Go to 'edit' link\n\t# Update version and save\n\t# Go to 'files' link and upload the file\n\tclear ; env/bin/twine upload dist/* --username=UPDATE_ME --password=UPDATE_ME\n\n# Git tasks\n\npush: tox doc\n\tclear ; git push origin `git symbolic-ref --short HEAD`\n\ntag:\n\tgit tag ${VERSION}\n\tgit push origin ${VERSION}\n\nreset_tag:\n\tgit tag -d ${VERSION}\n\tgit push origin :refs/tags/${VERSION}\n\n\n# GitHub Action\n\nact:\n\t#brew install act\n\ttime act --container-architecture linux/amd64 --matrix python_version:3.11 --matrix django_version:4.2\n\nactall:\n\ttime act --container-architecture linux/amd64\n"
  },
  {
    "path": "README.md",
    "content": "Django Dynamic Fixture\n======================\n\n[![Docs Status](https://readthedocs.org/projects/django-dynamic-fixture/badge/?version=latest)](http://django-dynamic-fixture.readthedocs.org/en/latest/index.html)\n[![PyPI version](https://badge.fury.io/py/django-dynamic-fixture.svg)](https://badge.fury.io/py/django-dynamic-fixture)\n![PyPI - Python Version](https://img.shields.io/pypi/pyversions/django-dynamic-fixture)\n![PyPI - Downloads](https://img.shields.io/pypi/dm/django-dynamic-fixture)\n\n**Latest version: 4.0.1 (Sep 2023)**\n\nDjango Dynamic Fixture (DDF) is a complete and simple library to create dynamic model instances for testing purposes.\n\nIt lets you focus on your tests, instead of focusing on generating some dummy data which is boring and polutes the test source code.\n\n* [Basic Examples](#basic-examples)\n* [Cheat Sheet](#cheat-sheet)\n* [Sponsors](#sponsors)\n* <a href=\"http://django-dynamic-fixture.readthedocs.org/en/latest/index.html\" target=\"_blank\">Full Documentation</a>\n\n\nBasic Examples\n--------------\n\n> Customize only the important details of the test:\n\n```python\n    from ddf import G\n    from my_library import Author, Book\n\n    def test_search_book_by_author():\n        author1 = G(Author)\n        author2 = G(Author)\n        book1 = G(Book, authors=[author1])\n        book2 = G(Book, authors=[author2])\n        books = Book.objects.search_by_author(author1.name)\n        assert book1 in books\n        assert book2 not in books\n```\n\n> Using some goodies to keep the test code smaller:\n\n```python\n    from ddf import G\n\n    def test_search_book_by_author():\n        author1, author2 = G('my_library.Author', n=2)\n        book1 = G('my_library.Book', authors=[author1])\n        book2 = G('my_library.Book', authors=[author2])\n        books = Book.objects.search_by_author(author1.name)\n        assert book1 in books\n        assert book2 not in books\n```\n\n> Configuring data from relationship fields:\n\n```python\n    from ddf import G\n\n    def test_search_book_by_author():\n        book1 = G(Book, main_author__name='Eistein')\n        book2 = G(Book)\n        books = Book.objects.search_by_author(book1.main_author.name)\n        assert book1 in books\n        assert book2 not in books\n        assert book1.main_author.name == 'Eistein'\n```\n\nCheat Sheet\n--------------\n\n```python\n# Import the main DDF features\nfrom ddf import N, G, F, M, C, P, teach # meaning: New, Get, ForeignKey, Mask, Copier, Print, teach\n```\n\n```python\n# `N` creates an instance of model without saving it to DB\ninstance = N(Book)\n```\n\n```python\n# `G` creates an instance of model and save it into the DB\ninstance = G(Book)\n```\n\n```python\n# `F` customize relationship objects\ninstance = G(Book, author=F(name='Eistein'))\n# Same as `F`\ninstance = G(Book, author__name='Eistein')\n```\n\n```python\n# `M` receives a data mask and create a random string using it\n# Known symbols: `_`, `#` or `-`\n# To escape known symbols: `!`\ninstance = N(Book, address=M('Street ___, ### !- --'))\nassert instance.address == 'Street TPA, 632 - BR'\n```\n\n```python\n# `C` copies data from one field to another\ninstance = N(Book, address_formatted=C('address'), address=M('Street ___, ### \\- --'))\nassert instance.address_formatted == 'Street TPA, 632 - BR'\n```\n\n```python\n# `teach` teaches DDF in how to build an instance\nteach(Book, address=M('Street ___, ### !- --'))\ninstance = G(Book)\nassert instance.address == 'Street TPA, 632 - BR'\n```\n\n```python\n# `P` print instance values for debugging\nP(instance)\n```\n\n```python\nimport ddf\nddf.__version__\n```\n\n```python\nfrom ddf import ddf_check_models\nsucceeded, errors = ddf_check_models()\nsucceeded, errors = ddf_check_models(print_csv=True)\nsucceeded, errors = ddf_check_models(csv_filename='ddf_compatibility_report.csv')\n```\n\nSponsors\n--------------\n- https://github.com/thnxdev\n"
  },
  {
    "path": "ddf/__init__.py",
    "content": "# Short alias to use: # `from ddf import *` instead of `from django_dynamic_fixture import *`\nfrom django_dynamic_fixture import N, G, F, C, M, P, PRE_SAVE, POST_SAVE, __version__\nfrom django_dynamic_fixture import new, get, fixture, teach, look_up_alias\nfrom django_dynamic_fixture.decorators import skip_for_database, only_for_database\nfrom django_dynamic_fixture.fdf import FileSystemDjangoTestCase\nfrom django_dynamic_fixture.script_ddf_checkings import ddf_check_models\n"
  },
  {
    "path": "django_dynamic_fixture/__init__.py",
    "content": "\n\"\"\"\nThis is the facade of all features of DDF.\nModule that contains wrappers and shortcuts (aliases).\n\"\"\"\nimport warnings\n\nfrom django.apps import apps\n\nfrom django_dynamic_fixture.ddf import DynamicFixture, Copier, Mask, DDFLibrary, \\\n    set_pre_save_receiver, set_post_save_receiver\nfrom django_dynamic_fixture.django_helper import print_field_values, django_greater_than\nfrom django_dynamic_fixture.fixture_algorithms.sequential_fixture import SequentialDataFixture, \\\n    StaticSequentialDataFixture\nfrom django_dynamic_fixture.global_settings import DDF_DEFAULT_DATA_FIXTURE, DDF_FILL_NULLABLE_FIELDS, DDF_FK_MIN_DEPTH, \\\n                                                    DDF_IGNORE_FIELDS, DDF_VALIDATE_MODELS, \\\n                                                    DDF_DEBUG_MODE, DDF_FIELD_FIXTURES\nfrom django_dynamic_fixture.script_ddf_checkings import ddf_check_models\n\n\n__version__ = '4.0.1'\n\n\nif not django_greater_than(4, 0):\n    warnings.warn(\"DDF 4.* officially supports only Django 4 or higher.\", DeprecationWarning)\n\n\nLOOKUP_SEP = '__'\n\ndef look_up_alias(ddf_as_f=True, **kwargs):\n    \"\"\"\n    Example of parameters:\n    a__b__c=1 => {a: {b: {c: 1}}}\n    \"\"\"\n    field_dict = {}\n    params_to_be_skipped = []\n    for alias, value in kwargs.items():\n        parts = alias.split(LOOKUP_SEP)\n        if len(parts) == 1:\n            params_to_be_skipped.append(alias)\n        level_dict = field_dict\n        for part in parts[:-1]:\n            level_dict = level_dict.setdefault(part, {})\n        level_dict[parts[-1]] = value\n    if ddf_as_f:\n        for root, value in field_dict.items():\n            if root in params_to_be_skipped:\n                field_dict[root] = value\n            else:\n                field_dict[root] = dict_to_f(value)\n    return field_dict\n\n\ndef dict_to_f(value):\n    \"\"\"\n    Example:\n    1 => 1\n    {b: 1} => F(b=1)\n    {b: {c: 1}} => F(b=F(c=1))\n    \"\"\"\n    if not isinstance(value, dict):\n        return value\n    else:\n        kwargs = {}\n        for k, v in value.items():\n            if not isinstance(v, dict):\n                kwargs[k] = v\n            else:\n                kwargs[k] = dict_to_f(v)\n        return F(**kwargs)\n\n\ndef fixture(**kwargs):\n    \"\"\"\n    DynamicFixture factory: It instantiate a DynamicFixture using global configurations.\n    Same as F(...)\n    \"\"\"\n    kwargs = look_up_alias(**kwargs)\n    f = DynamicFixture(data_fixture=kwargs.pop('data_fixture', DDF_DEFAULT_DATA_FIXTURE),\n                       fill_nullable_fields=kwargs.pop('fill_nullable_fields', DDF_FILL_NULLABLE_FIELDS),\n                       ignore_fields=kwargs.pop('ignore_fields', []),\n                       fk_min_depth=kwargs.pop('fk_min_depth', DDF_FK_MIN_DEPTH),\n                       validate_models=kwargs.pop('validate_models', DDF_VALIDATE_MODELS),\n                       print_errors=kwargs.pop('print_errors', True),\n                       debug_mode=kwargs.pop('debug_mode', DDF_DEBUG_MODE),\n                       **kwargs)\n    return f\n\n\n# Wrappers\n\ndef _new(model, n=1, ddf_lesson=None, persist_dependencies=False, **kwargs):\n    \"\"\"\n    Return one or many valid instances of Django Models with fields filled with auto generated or customized data.\n    All instances will NOT be persisted in the database, except its dependencies, in case @persist_dependencies is True.\n\n    @model: The class of the Django model. It can be a string `<app_label>.<model_name>`\n    @n: number of instances to be created with the given configuration. Default is 1.\n    @ddf_lesson: use a custom ddf_lesson to build the model object.\n    @persist_dependencies: If True, save internal dependencies, otherwise just instantiate them. Default is False.\n\n    @data_fixture: override DDF_DEFAULT_DATA_FIXTURE configuration. Default is SequentialDataFixture().\n    @fill_nullable_fields: override DDF_FILL_NULLABLE_FIELDS global configuration. Default is True.\n    @ignore_fields: List of fields that will be ignored by DDF. It will be concatenated with the global list DDF_IGNORE_FIELDS. Default is [].\n    @fk_min_depth: override DDF_FK_MIN_DEPTH global configuration. Default 0.\n    @validate_models: override DDF_VALIDATE_MODELS global configuration. Default is False.\n    @print_errors: print on console all instance values if DDF can not generate a valid object with the given configuration.\n\n    Wrapper for the method DynamicFixture.new\n    \"\"\"\n    if isinstance(model, str):\n        model = apps.get_model(model)\n    kwargs = look_up_alias(**kwargs)\n    d = fixture(**kwargs)\n    if n == 1:\n        return d.new(model, ddf_lesson=ddf_lesson, persist_dependencies=persist_dependencies, **kwargs)\n    instances = []\n    for _ in range(n):\n        instances.append(d.new(model, ddf_lesson=ddf_lesson, persist_dependencies=persist_dependencies, **kwargs))\n    return instances\n\n\ndef _get(model, n=1, ddf_lesson=None, **kwargs):\n    \"\"\"\n    Return one or many valid instances of Django Models with fields filled with auto generated or customized data.\n    All instances will be persisted in the database.\n\n    @model: The class of the Django model. It can be a string `<app_label>.<model_name>`\n    @n: number of instances to be created with the given configuration. Default is 1.\n    @ddf_lesson: use a custom ddf_lesson to build the model object.\n\n    @data_fixture: override DDF_DEFAULT_DATA_FIXTURE configuration. Default is SequentialDataFixture().\n    @fill_nullable_fields: override DDF_FILL_NULLABLE_FIELDS global configuration. Default is True.\n    @ignore_fields: List of fields that will be ignored by DDF. It will be concatenated with the global list DDF_IGNORE_FIELDS. Default is [].\n    @fk_min_depth: override DDF_FK_MIN_DEPTH global configuration. Default 0.\n    @validate_models: override DDF_VALIDATE_MODELS global configuration. Default is False.\n    @print_errors: print on console all instance values if DDF can not generate a valid object with the given configuration.\n\n    Wrapper for the method DynamicFixture.get\n    \"\"\"\n    if isinstance(model, str):\n        model = apps.get_model(model)\n    kwargs = look_up_alias(**kwargs)\n    d = fixture(**kwargs)\n    if n == 1:\n        return d.get(model, ddf_lesson=ddf_lesson, **kwargs)\n    instances = []\n    for _ in range(n):\n        instances.append(d.get(model, ddf_lesson=ddf_lesson, **kwargs))\n    return instances\n\n\ndef _teach(model, ddf_lesson=None, **kwargs):\n    '''\n    @model: The class of the Django model. It can be a string `<app_label>.<model_name>`\n    @ddf_lesson: Name of custom ddf_lesson to be created.\n\n    @raise an CantOverrideddf_lesson error if the same model/ddf_lesson were called twice.\n\n    Sometimes DDF can't create an model instance because the particularities of the model.\n    The workaround for this is to teach DDF how to create it.\n    Basically, we use the same object creation approach that will be saved as a template\n    for the next DDF calls.\n\n    Use this method to teach DDF how to create an instance.\n\n    New metaphor for the shelve/library feature.\n    `Shelve` becomes `Teach`\n    `Library` becomes `Lessons`\n    '''\n    if isinstance(model, str):\n        model = apps.get_model(model)\n    kwargs = look_up_alias(**kwargs)\n    d = fixture(**kwargs)\n    return d.teach(model, ddf_lesson=ddf_lesson, **kwargs)\n\n\n# Shortcuts\nN = new = _new\nG = get = _get\nT = teach = _teach\nF = fixture\nC = Copier\nM = Mask\nP = print_field_values\nDDFLibrary = DDFLibrary\nPRE_SAVE = set_pre_save_receiver\nPOST_SAVE = set_post_save_receiver\n\nimport typing\n\nINSTANCE_TYPE = typing.TypeVar('INSTANCE')\n\ndef new(model: typing.Type[INSTANCE_TYPE], n: int = 1, ddf_lesson = None, persist_dependencies: bool = True, **kwargs) -> INSTANCE_TYPE:\n    return _new(model, n=n, ddf_lesson=ddf_lesson, persist_dependencies=persist_dependencies, **kwargs)\n\ndef get(model: typing.Type[INSTANCE_TYPE], n: int=1, ddf_lesson=None, **kwargs) -> INSTANCE_TYPE | typing.List[INSTANCE_TYPE]:\n    return _get(model, n=n, ddf_lesson=ddf_lesson, **kwargs)\n\ndef teach(model: typing.Type[INSTANCE_TYPE], ddf_lesson=None, **kwargs):\n    return _teach(model, ddf_lesson=ddf_lesson, **kwargs)\n\nN = new\nG = get\nT = teach\n"
  },
  {
    "path": "django_dynamic_fixture/ddf.py",
    "content": "\nimport inspect\nimport logging\nimport re\nimport sys\n\nfrom django.core.files import File\nfrom django.db.models import Field\n\ntry:\n    from importlib import import_module\nexcept ImportError:\n    from django.utils.importlib import import_module\n\nfrom django_dynamic_fixture.django_helper import get_related_model, \\\n    field_has_choices, field_has_default_value, get_fields_from_model, \\\n    print_field_values, get_many_to_many_fields_from_model, \\\n    get_unique_model_name, get_unique_field_name, is_model_abstract, \\\n    field_is_a_parent_link, get_field_by_name_or_raise, get_app_name_of_model, \\\n    is_model_class, is_relationship_field, is_file_field, is_key_field, \\\n    model_has_the_field, enable_auto_now, disable_auto_now, enable_auto_now_add, disable_auto_now_add\n\n\nLOGGER = logging.getLogger('DDFLog')\n_PRE_SAVE = {} # receivers to be executed before saving a instance;\n_POST_SAVE = {} # receivers to be executed after saving a instance;\n\n\nclass UnsupportedFieldError(Exception):\n    \"DynamicFixture does not support this field.\"\n\n\nclass InvalidCopierExpressionError(Exception):\n    \"The specified expression used in a Copier is invalid.\"\n\n\nclass InvalidConfigurationError(Exception):\n    \"The specified configuration for the field can not be applied or it is bugged.\"\n\n\nclass InvalidManyToManyConfigurationError(Exception):\n    \"M2M attribute configuration must be a number or a list of DynamicFixture or model instances.\"\n\n\nclass BadDataError(Exception):\n    \"The data passed to a field has some problem (not unique or invalid) or a required attribute is in ignore list.\"\n\n\nclass InvalidModelError(Exception):\n    \"Invalid Model: The class is not a model or it is abstract.\"\n\n\nclass InvalidReceiverError(Exception):\n    \"Receiver is not a function that receive only the instance as parameter.\"\n\n\nclass PendingField(Exception):\n    \"Internal exception to control pending fields when using Copier.\"\n\n\ndef _validate_model(model_class):\n    if not is_model_class(model_class):\n        raise InvalidReceiverError(model_class, 'Invalid model')\n\n\ndef _validate_function(model_class, callback_function):\n    if not inspect.isfunction(callback_function) or not callback_function:\n        raise InvalidReceiverError(model_class, 'Invalid function')\n    if callback_function:\n        args = len(inspect.getfullargspec(callback_function).args)\n    if args != 1:\n        raise InvalidReceiverError(model_class, 'Invalid number of function arguments')\n\n\ndef set_pre_save_receiver(model_class, callback_function):\n    '''\n    :model_class: a model_class can have only one receiver. Do not complicate yourself.\n    :callback_function must be a function that receive the instance as unique parameter.\n    '''\n    _validate_model(model_class)\n    _validate_function(model_class, callback_function)\n    _PRE_SAVE[model_class] = callback_function\n\n\ndef set_post_save_receiver(model_class, callback_function):\n    '''\n    :model_class: a model_class can have only one receiver. Do not complicate yourself.\n    :callback_function must be a function that receive the instance as unique parameter.\n    '''\n    _validate_model(model_class)\n    _validate_function(model_class, callback_function)\n    _POST_SAVE[model_class] = callback_function\n\n\nclass DataFixture:\n    '''\n    Responsibility: return a valid data for a Django Field, according to its type, model class, constraints etc.\n\n    You must create a separated method to generate data for an specific field. For a field called 'MyField',\n    the method must be:\n\n    def myfield_config(self, field, key): return 'some value'\n\n    :field: Field object.\n    :key: string that represents a unique name for a Field, considering app, model and field names.\n    '''\n    def __init__(self):\n        self.plugins = {}\n\n    def _field_fixture_template(self, field_class):\n        return f'{field_class.__name__.lower()}_config'\n\n    def _field_fixture_factory(self, field_class):\n        try:\n            fixture = self._field_fixture_template(field_class)\n            getattr(self, fixture)\n            return fixture\n        except AttributeError:\n            if len(field_class.__bases__) > 0:\n                # Pick the first parent class that inherits Field (or use the first parent class)\n                field_subclasses = (cls for cls in field_class.__bases__ if issubclass(cls, Field))\n                parent_class = next(field_subclasses, field_class.__bases__[0])\n                return self._field_fixture_factory(parent_class)\n            else:\n                return None\n\n    def generate_data(self, field):\n        '''Get a unique and valid data for the field.'''\n        field_fullname = field.__module__ + \".\" + field.__class__.__name__\n        fixture = self.plugins.get(field_fullname, {})\n        if type(fixture) == dict:\n            fixture = fixture.get('ddf_fixture', None)\n        if fixture and callable(fixture):\n            return fixture()\n        config = self._field_fixture_factory(field.__class__)\n        is_supported_field = config != None\n        if is_supported_field:\n            key = get_unique_field_name(field)\n            data = eval(f'self.{config}(field, \"{key}\")')\n        else:\n            if field.null:\n                data = None # a workaround for versatility\n            else:\n                raise(UnsupportedFieldError(get_unique_field_name(field) + ' (%s)' % (field_fullname)))\n        return data\n\n\nclass Copier:\n    '''\n    Wrapper of an expression in the format 'field' or 'field.field' or 'field.field.field' etc\n    This expression will be interpreted to copy the value of the specified field to the current field.\n    Example of usage: G(MyModel, x=C('y.z')) => the value 'z' of field 'y' will be copied to field 'x'.\n    '''\n    def __init__(self, expression):\n        self.expression = expression\n\n    def __str__(self):\n        return \"C('%s')\" % self.expression\n\n    def immediate_field_name(self, instance):\n        model_class = instance.__class__\n        field_name = self.expression.split('.')[0]\n        get_field_by_name_or_raise(model_class, field_name)\n        return field_name\n\n    def eval_expression(self, instance):\n        try:\n            current_instance = instance\n            fields = self.expression.split('.')\n            for field in fields:\n                current_instance = getattr(current_instance, field)\n            return current_instance\n        except Exception as e:\n            raise InvalidCopierExpressionError(self.expression, e)\n\n\nclass Mask:\n    '''\n    Wrapper for an expression mask that will be used to generate a random string with a custom format.\n\n    The expression mask supports 4 special characters:\n    - `#` for random numbers;\n    - `-` for random uppercase chars;\n    - `_` for random lowercase chars;\n    - `!` to escape special chars;\n\n    Other characters will not be interpreted and it will be considered part of the final string.\n\n    Example of usage: D('###.___!----') => '510.kap-NGK'\n    '''\n    def __init__(self, expression):\n        self.expression = expression\n\n    def __str__(self):\n        return \"D('%s')\" % self.expression\n\n    def evaluate(self):\n        import random\n        import string\n        chars = []\n        escaped = False\n        for char in self.expression:\n            if escaped:\n                c = char\n                escaped = False\n            elif char == '#':\n                c = random.choice(string.digits)\n            elif char == '-':\n                c = random.choice(string.ascii_uppercase)\n            elif char == '_':\n               c = random.choice(string.ascii_lowercase)\n            elif char == '!':\n                escaped = True\n                continue\n            else:\n                c = char\n            chars.append(c)\n        return ''.join(chars)\n\n\nclass DDFLibrary:\n    instance = None\n    DEFAULT_KEY = 'ddf_default'\n\n    def __init__(self):\n        self.configs = {} # {Model: {name: config}}\"\n\n    def __str__(self):\n        return '\\n'.join([f'{key} = {value}' for key, value in self.configs.items()])\n\n    @classmethod\n    def get_instance(cls):\n        if not cls.instance:\n            cls.instance = DDFLibrary()\n        return cls.instance\n\n    def add_configuration(self, model_class, kwargs, name=None):\n        import os\n        import warnings\n        if name in [None, True]:\n            name = self.DEFAULT_KEY\n        model_class = self._get_concrete_model(model_class)\n        if model_class in self.configs and name in self.configs[model_class]:\n            if not os.getenv('DDF_SHELL_MODE'):\n                msg = \"Override a lesson is an anti-pattern and will turn your test suite very hard to understand.\"\n                msg = f'A lesson {name} has already been saved for the model {model_class}. {msg}'\n                warnings.warn(msg, RuntimeWarning)\n        model_class_config = self.configs.setdefault(model_class, {})\n        model_class_config[name] = kwargs\n\n    def get_configuration(self, model_class, name=None):\n        if name is None:\n            name = self.DEFAULT_KEY\n        model_class = self._get_concrete_model(model_class)\n        # copy is important because this dict will be updated every time in the algorithm.\n        config = self.configs.get(model_class, {})\n        if name != self.DEFAULT_KEY and name not in config.keys():\n            raise InvalidConfigurationError('There is no lesson for model {} with the name \"{}\"'.format(get_unique_model_name(model_class), name))\n        return config.get(name, {}).copy() # default configuration never raises an error\n\n    def _get_concrete_model(self, model_class):\n        if hasattr(model_class, '_meta') and model_class._meta.proxy:\n            return model_class._meta.concrete_model or model_class\n        else:\n            return model_class\n\n    def clear(self):\n        '''Remove all lessons of the library. Util for the DDF tests.'''\n        self.configs = {}\n\n    def clear_configuration(self, model_class):\n        '''Remove from the library an specific configuration of a model.'''\n        if model_class in self.configs.keys():\n            del self.configs[model_class]\n\n\nclass DynamicFixture:\n    '''\n    Responsibility: create a valid model instance according to the given configuration.\n    '''\n\n    _DDF_CONFIGS = ['fill_nullable_fields', 'ignore_fields', 'data_fixture', 'fk_min_depth',\n                    'validate_models', 'print_errors']\n\n    def __init__(self, data_fixture, fill_nullable_fields=False, ignore_fields=[], fk_min_depth=0,\n                 validate_models=False, print_errors=True, debug_mode=False, **kwargs):\n        '''\n        :data_fixture: algorithm to fill field data.\n        :fill_nullable_fields: flag to decide if nullable fields must be filled with data.\n        :ignore_fields: list of field names that must not be filled with data.\n        :fk_min_depth: how deep DDF should go to create non-required FKs fields from the main model.\n        :validate_models: flag to decide if the model_instance.full_clean() must be called before saving the object.\n        :print_errors: flag to determine if the model data must be printed to console on errors. For some scripts is interesting to disable it.\n        '''\n        from django_dynamic_fixture.global_settings import DDF_IGNORE_FIELDS\n        from django_dynamic_fixture.fixture_algorithms import FixtureFactory\n        # custom config of fixtures\n        self.data_fixture = FixtureFactory.get(data_fixture)\n\n        self.fill_nullable_fields = fill_nullable_fields\n        self.ignore_fields = ignore_fields\n        # extend ignore_fields with globally declared ignore_fields\n        self.ignore_fields.extend(DDF_IGNORE_FIELDS)\n        self.fk_min_depth = fk_min_depth\n        # other ddfs configs\n        self.validate_models = validate_models\n        self.print_errors = print_errors\n        # internal logic\n        self.pending_fields = []\n        self.fields_processed = []\n        self.debug_mode = debug_mode\n        self.kwargs = kwargs\n        self.fields_to_disable_auto_now = []\n        self.fields_to_disable_auto_now_add = []\n\n    def __str__(self):\n        return 'F(%s)' % (', '.join(f'{key}={value}' for key, value in self.kwargs.items()))\n\n    def __eq__(self, that):\n        return isinstance(that, self.__class__) and self.kwargs == that.kwargs\n\n    def _get_data_from_custom_dynamic_fixture(self, field, fixture, persist_dependencies):\n        '''return data of a Dynamic Fixture: field=F(...)'''\n        next_model = get_related_model(field)\n        if persist_dependencies:\n            data = fixture.get(next_model)\n        else:\n            data = fixture.new(next_model, persist_dependencies=persist_dependencies)\n        return data\n\n    def _get_data_from_custom_copier(self, instance, field, fixture):\n        '''return data of a Copier: field=C(...)'''\n        field_name = fixture.immediate_field_name(instance)\n        if field_name in self.fields_processed:\n            data = fixture.eval_expression(instance)\n        else:\n            self.pending_fields.append(field.name)\n            raise PendingField('%s' % field.name)\n        return data\n\n    def _get_data_from_data_fixture(self, field, fixture):\n        '''return data of a Data Fixture: field=DataFixture()'''\n        next_model = get_related_model(field)\n        return fixture.generate_data(next_model)\n\n    def _get_data_from_a_custom_function(self, field, fixture):\n        '''Returns data of a custom function: field=lambda field: field.name'''\n        data = fixture(field)\n        return data\n\n    def _get_data_from_static_data(self, field, fixture):\n        '''return date from a static value: field=3'''\n        if hasattr(field, 'auto_now_add') and field.auto_now_add:\n            self.fields_to_disable_auto_now_add.append(field)\n        if hasattr(field, 'auto_now') and field.auto_now:\n            self.fields_to_disable_auto_now.append(field)\n        return fixture\n\n    def _process_field_with_customized_fixture(self, instance, field, fixture, persist_dependencies):\n        '''Set a custom value to a field.'''\n        if isinstance(fixture, DynamicFixture): # DynamicFixture (F)\n            data = self._get_data_from_custom_dynamic_fixture(field, fixture, persist_dependencies)\n        elif isinstance(fixture, Copier): # Copier (C)\n            data = self._get_data_from_custom_copier(instance, field, fixture)\n        elif isinstance(fixture, Mask): # Mask (M)\n            data = fixture.evaluate()\n        elif isinstance(fixture, DataFixture): # DataFixture\n            data = self._get_data_from_data_fixture(field, fixture)\n        elif callable(fixture): # callable with the field as parameters\n            data = self._get_data_from_a_custom_function(field, fixture)\n        else: # attribute value\n            data = self._get_data_from_static_data(field, fixture)\n        return data\n\n    def _process_foreign_key(self, model_class, field, persist_dependencies):\n        '''\n        Returns auto-generated value for a field ForeignKey or OneToOneField.\n        '''\n        if field_is_a_parent_link(field):\n            return None\n        next_model = get_related_model(field)\n\n        # 1. Propagate ignored_fields only for self references\n        if model_class == next_model: # self reference\n            ignore_fields = self.ignore_fields\n        else:\n            ignore_fields = []\n        # 2. It needs a new DynamicFixture to control the cycles and ignored fields.\n        fixture = DynamicFixture(data_fixture=self.data_fixture,\n                                 fill_nullable_fields=self.fill_nullable_fields,\n                                 ignore_fields=ignore_fields,\n                                 fk_min_depth=self.fk_min_depth - 1, # Depth decreased\n                                 validate_models=self.validate_models,\n                                 print_errors=self.print_errors)\n        # 3. Persist it\n        if persist_dependencies:\n            data = fixture.get(next_model)\n        else:\n            data = fixture.new(next_model, persist_dependencies=persist_dependencies)\n        return data\n\n    def _process_field_with_default_fixture(self, field, model_class, persist_dependencies):\n        '''\n        The field has no custom value (F, C, static, Lessons...), so the default behavior of the tool is applied.\n        - DDF behavior priority for common fields:\n        1. Use `null` if possible (considering the `fill_nullable_fields` settings)\n        2. Use the `default` value\n        3. Use the first option of `choices`\n        - DDF behavior priority for relationship fields:\n        1. Use the `default` value\n        2. Use `null` if possible, or consider the `fk_min_depth` value\n        3. Create a new FK model\n        '''\n        if is_relationship_field(field):\n            if field_has_default_value(field):\n                # datetime default can receive a function: datetime.now\n                data = field.default() if callable(field.default) else field.default\n            else:\n                if (not field.null) or self.fk_min_depth > 0:\n                    data = self._process_foreign_key(model_class, field, persist_dependencies)\n                else:\n                    data = None\n        else:\n            if field_has_default_value(field):\n                # datetime default can receive a function: datetime.now\n                data = field.default() if callable(field.default) else field.default\n            elif field.null and not self.fill_nullable_fields:\n                data = None\n            elif field_has_choices(field):\n                data = field.flatchoices[0][0] # key of the first choice\n            else:\n                data = self.data_fixture.generate_data(field)\n        return data\n\n    def set_data_for_a_field(self, model_class, __instance, __field, persist_dependencies=True, **kwargs):\n        if __field.name in kwargs:\n            config = kwargs[__field.name]\n            try:\n                data = self._process_field_with_customized_fixture(__instance, __field, config, persist_dependencies)\n            except PendingField:\n                return # ignore this field for a while.\n            except Exception as e:\n                raise InvalidConfigurationError(get_unique_field_name(__field), e)\n        else:\n            data = self._process_field_with_default_fixture(__field, model_class, persist_dependencies)\n\n        if is_file_field(__field) and data:\n            django_file = data\n            if isinstance(django_file, File):\n                setattr(__instance, __field.name, data.name) # set the attribute\n                if hasattr(django_file.file, 'mode') and django_file.file.mode != 'rb':\n                    django_file.file.close() # this file may be open in another mode, for example, in a+b\n                    opened_file = open(django_file.file.name, 'rb') # to save the file it must be open in rb mode\n                    django_file.file = opened_file # we update the reference to the rb mode opened file\n\n                # https://github.com/paulocheque/django-dynamic-fixture/issues/10\n                # getattr(__instance, __field.name).save(django_file.name, django_file) # save the file into the file storage system\n                # django_file.close()\n                getattr(__instance, __field.name).save(django_file.name, django_file, save=False)\n\n            else: # string (saving just a name in the file, without saving the file to the storage file system\n                setattr(__instance, __field.name, data) # Model.field = data\n        else:\n            if self.debug_mode:\n                LOGGER.debug(f'{get_unique_model_name(model_class)}.{__field.name} = {data}')\n            try:\n                setattr(__instance, __field.name, data) # Model.field = data\n            except (ValueError, AttributeError) as e:\n                if is_relationship_field(__field):\n                    # Handle AttributeError for compatibility with django-polymorphic\n                    # https://github.com/paulocheque/django-dynamic-fixture/issues/88\n                    field_value = data.id if data and isinstance(e, AttributeError) else data\n                    setattr(__instance, \"%s_id\" % __field.name, field_value) # Model.field = data\n                else:\n                    raise e\n        self.fields_processed.append(__field.name)\n\n    def _validate_kwargs(self, model_class, kwargs):\n        '''validate all kwargs match Model.fields.'''\n        for field_name in kwargs.keys():\n            if field_name in self._DDF_CONFIGS:\n                continue\n            if not model_has_the_field(model_class, field_name):\n                raise InvalidConfigurationError('Field \"%s\" does not exist.' % field_name)\n\n    def _configure_params(self, model_class, ddf_lesson, **kwargs):\n        '''\n        1) validate kwargs\n        2) load default fixture from DDF library. Store default fixture in DDF library.\n        3) Load fixtures defined in F attributes.\n        '''\n        self._validate_kwargs(model_class, kwargs)\n\n        library = DDFLibrary.get_instance()\n        configuration = {}\n        # 1. Load the default/global lesson for the model.\n        configuration_default = library.get_configuration(model_class, name=DDFLibrary.DEFAULT_KEY)\n        configuration.update(configuration_default) # always use default configuration\n        # 2. Load a custom lesson for the model.\n        if ddf_lesson:\n            configuration_custom = library.get_configuration(model_class, name=ddf_lesson)\n            configuration.update(configuration_custom) # override default configuration\n        # 3. Load the custom `kwargs` attributes.\n        configuration.update(kwargs) # override the configuration with current configuration\n        configuration.update(self.kwargs) # Used by F: kwargs are passed by constructor, not by get.\n\n        return configuration\n\n    def new(self, model_class, ddf_lesson=None, persist_dependencies=True, **kwargs):\n        '''\n        Create an instance filled with data without persist it.\n        1) validate all kwargs match Model.fields.\n        2) validate model is a model.Model class.\n        3) Iterate model fields: for each field, fill it with data.\n\n        :ddf_lesson: the lesson that will be used to create the model instance, if exists.\n        :persist_dependencies: tell if internal dependencies will be saved in the database or not.\n        '''\n        if self.debug_mode:\n            LOGGER.debug('>>> [%s] Generating instance.' % get_unique_model_name(model_class))\n        configuration = self._configure_params(model_class, ddf_lesson, **kwargs)\n        try:\n            instance = model_class()\n        except TypeError:\n            raise InvalidModelError(get_unique_model_name(model_class))\n        if not is_model_class(instance):\n            raise InvalidModelError(get_unique_model_name(model_class))\n\n        try:\n            # https://github.com/paulocheque/django-dynamic-fixture/pull/112\n            from polymorphic import PolymorphicModel\n            is_polymorphic = isinstance(instance, PolymorphicModel)\n        except ImportError:\n            # Django-polymorphic is not installed so the model can't be polymorphic.\n            is_polymorphic = False\n        for field in get_fields_from_model(model_class):\n            if is_key_field(field) and field.name not in configuration: continue\n            if field.name not in self.kwargs and self._is_ignored_field(field.name): continue\n            if is_polymorphic and (field.name == 'polymorphic_ctype' or field.primary_key): continue\n            self.set_data_for_a_field(model_class, instance, field, persist_dependencies=persist_dependencies, **configuration)\n        number_of_pending_fields = len(self.pending_fields)\n        # For Copier fixtures: dealing with pending fields that need to receive values of another fields.\n        i = 0\n        while self.pending_fields != []:\n            field_name = self.pending_fields.pop(0)\n            field = get_field_by_name_or_raise(model_class, field_name)\n            self.set_data_for_a_field(model_class, instance, field, persist_dependencies=persist_dependencies, **configuration)\n            i += 1\n            if i > 2 * number_of_pending_fields: # dealing with infinite loop too.\n                raise InvalidConfigurationError(get_unique_field_name(field), 'Cyclic dependency of Copiers.')\n        if self.debug_mode:\n            LOGGER.debug('<<< [%s] Instance created.' % get_unique_model_name(model_class))\n        return instance\n\n    def _is_ignored_field(self, field_name):\n        '''\n        Return `True` if the given field name should be ignored according to\n        this class's `self.ignored_fields`. Both literal field names and\n        names with wildcard '*' and '?' characters are supported.\n        '''\n        # Do fast check for literal field name first\n        if field_name in self.ignore_fields:\n            return True\n        # If any ignored field names contain wildcards, check them against the\n        # given field name\n        for ignore_spec in self.ignore_fields:\n            if '*' in ignore_spec or '?' in ignore_spec:\n                # Replace wildcard characters with regexp equivalents\n                re_spec = ignore_spec.replace('?', '.').replace('*', '.*')\n                # Update regexp to match entire field name, not just a portion\n                re_spec = r'^%s$' % re_spec\n                if re.match(re_spec, field_name):\n                    return True\n        return False\n\n    def _process_many_to_many_field(self, field, manytomany_field, fixture, instance):\n        '''\n        Set ManyToManyField fields with or without 'trough' option.\n\n        :field: model field.\n        :manytomany_field: ManyRelatedManager of the field.\n        :fixture: value passed by user.\n        '''\n        next_model = get_related_model(field)\n        if isinstance(fixture, int):\n            amount = fixture\n            for _ in range(amount):\n                next_instance = self.get(next_model)\n                self._create_manytomany_relationship(manytomany_field, instance, next_instance)\n        elif isinstance(fixture, (list, tuple)):\n            items = fixture\n            for item in items:\n                if isinstance(item, DynamicFixture):\n                    next_instance = item.get(next_model, **item.kwargs) # need to pass F.kwargs recursively.\n                else:\n                    next_instance = item\n\n                self._create_manytomany_relationship(manytomany_field, instance, next_instance)\n        else:\n            raise InvalidManyToManyConfigurationError('Field: %s' % field.name, str(fixture))\n\n    def _create_manytomany_relationship(self, manytomany_field, instance, next_instance):\n        try:\n            manytomany_field.add(next_instance)\n        except AttributeError:\n            next_instance.save()\n\n            # Create an instance of the \"through\" model using the current data fixture\n            through_model = manytomany_field.through\n            through_instance = DynamicFixture(data_fixture=self.data_fixture) \\\n                    .get(through_model, **{\n                        manytomany_field.source_field_name: instance,\n                        manytomany_field.target_field_name: next_instance\n                    })\n\n    def _save_the_instance(self, instance):\n        for field in self.fields_to_disable_auto_now:\n            disable_auto_now(field)\n        for field in self.fields_to_disable_auto_now_add:\n            disable_auto_now_add(field)\n        instance.save()\n        for field in self.fields_to_disable_auto_now:\n            enable_auto_now(field)\n        for field in self.fields_to_disable_auto_now_add:\n            enable_auto_now_add(field)\n\n    def get(self, model_class, ddf_lesson=None, **kwargs):\n        '''\n        Create an instance with data and persist it.\n\n        :ddf_lesson: a custom lesson that will be used to create the model object.\n        '''\n        instance = self.new(model_class, ddf_lesson=ddf_lesson, **kwargs)\n        if is_model_abstract(model_class):\n            raise InvalidModelError(get_unique_model_name(model_class))\n        try:\n            if self.validate_models:\n                instance.full_clean()\n            if model_class in _PRE_SAVE:\n                try:\n                    _PRE_SAVE[model_class](instance)\n                except Exception as e:\n                    raise InvalidReceiverError(e)\n            self._save_the_instance(instance)\n            if model_class in _POST_SAVE:\n                try:\n                    _POST_SAVE[model_class](instance)\n                except Exception as e:\n                    raise InvalidReceiverError(e)\n        except Exception as e:\n            if self.print_errors:\n                print_field_values(instance)\n            raise BadDataError(get_unique_model_name(model_class), e)\n        self.fields_processed = [] # TODO: need more tests for M2M and Copier\n        self.pending_fields = []\n        for field in get_many_to_many_fields_from_model(model_class):\n            if field.name in kwargs.keys(): # TODO: library\n                manytomany_field = getattr(instance, field.name)\n                fixture = kwargs[field.name]\n                try:\n                    self._process_many_to_many_field(field, manytomany_field, fixture, instance)\n                except InvalidManyToManyConfigurationError as e:\n                    raise e\n                except Exception as e:\n                    raise InvalidManyToManyConfigurationError(get_unique_field_name(field), e)\n        return instance\n\n    def teach(self, model_class, ddf_lesson=None, **kwargs):\n        library = DDFLibrary.get_instance()\n        for field_name in kwargs.keys():\n            if field_name in self._DDF_CONFIGS:\n                continue\n            field = get_field_by_name_or_raise(model_class, field_name)\n            if field.unique and not _is_dynamic_value(kwargs[field_name]):\n                raise InvalidConfigurationError('It is not possible to store static values for fields with unique=True (%s). Try using a lambda function instead.' % get_unique_field_name(field))\n        library.add_configuration(model_class, kwargs, name=ddf_lesson)\n\n\ndef _is_dynamic_value(fixture):\n    return isinstance(fixture, (DynamicFixture, Copier, DataFixture, Mask)) or callable(fixture)\n"
  },
  {
    "path": "django_dynamic_fixture/decorators.py",
    "content": "\nfrom django.conf import settings\n\n\nDATABASE_ENGINE = settings.DATABASES['default']['ENGINE']\n\nSQLITE3 = 'sqlite3'\nPOSTGRES = 'postgresql'\nMYSQL = 'mysql'\nORACLE = 'oracle'\nSQLSERVER = 'pyodbc'\n\n\ndef skip_for_database(database):\n    def main_decorator(testcase_function):\n        def wrapper(*args, **kwargs):\n            if database not in DATABASE_ENGINE:\n                testcase_function(*args, **kwargs)\n        return wrapper\n    return main_decorator\n\n\ndef only_for_database(database):\n    def main_decorator(testcase_function):\n        def wrapper(*args, **kwargs):\n            if database in DATABASE_ENGINE:\n                testcase_function(*args, **kwargs)\n        return wrapper\n    return main_decorator\n"
  },
  {
    "path": "django_dynamic_fixture/django_helper.py",
    "content": "\"\"\"\nModule to wrap dirty stuff of django core.\n\"\"\"\nimport django\nfrom django.apps import apps\nfrom django.db import models  # noqa\nfrom django.db.models import *\nfrom django.db.models.fields import NOT_PROVIDED, AutoField\nfrom django.db.models.base import ModelBase\nfrom django.db.models.query import QuerySet\ntry:\n    from django.db.models.fields import FieldDoesNotExist\nexcept ImportError:\n    from django.core.exceptions import FieldDoesNotExist\n\n\ndef django_greater_than(major, minor=0):\n    return django.VERSION[:2] > (major, minor)\n\n\n# Apps\ndef get_apps(application_labels=[], exclude_application_labels=[]):\n    \"\"\"\n    - if not @application_labels and not @exclude_application_labels, it returns all applications.\n    - if @application_labels is not None, it returns just these applications,\n    except applications with label in exclude_application_labels.\n    @Returns an array of application labels.\n    \"\"\"\n    if application_labels:\n        applications = []\n        for app_label in application_labels:\n            app_config = apps.get_app_config(app_label)\n            applications.append(app_config.label)\n    else:\n        applications = [\n            app_config.label\n            for app_config in apps.get_app_configs()\n        ]\n    if exclude_application_labels:\n        for app_label in exclude_application_labels:\n            if app_label:\n                if app_label in applications:\n                    applications.remove(app_label)\n                else:\n                    raise ValueError(\n                        f\"Excluded application with label '{app_label}' \"\n                        \"is not installed.\")\n    return applications\n\n\ndef get_app_name(app_module):\n    \"\"\"\n    app is the object (python module) returned by get_apps method\n    \"\"\"\n    return app_module.__name__.split('.')[0]\n\n\ndef get_models_of_an_app(app_label):\n    \"\"\"\n    app_module is the object returned by get_apps method (python module)\n    \"\"\"\n    app_config = apps.get_app_config(app_label)\n    return list(app_config.get_models())\n\n\n# Models\ndef get_app_name_of_model(model_class):\n    return model_class.__module__.split('.')[0]\n\n\ndef get_model_name(model_class):\n    \"Example: ModelName\"\n    return model_class.__name__\n\n\ndef get_unique_model_name(model_class):\n    \"Example: app.packages.ModelName\"\n    return model_class.__module__ + '.' + model_class.__name__\n\n\ndef get_fields_from_model(model_class):\n    \"Returns all fields, including inherited fields but ignoring M2M fields.\"\n    return model_class._meta.fields\n\n\ndef get_local_fields(model):\n    \"Returns all local fields!?\"\n    return model._meta.local_fields\n\n\ndef get_many_to_many_fields_from_model(model_class):\n    \"Return only M2M fields, including inherited ones?\"\n    return model_class._meta.many_to_many\n    #_meta.local_many_to_many\n\n\ndef get_all_fields_of_model(model_class):\n    fields1 = get_fields_from_model(model_class)\n    fields2 = get_many_to_many_fields_from_model(model_class)\n    fields1.extend(fields2)\n    return fields1\n\n\ndef get_field_names_of_model(model_class):\n    \"Get field names, including inherited fields, except M2M fields.\"\n    fields = get_fields_from_model(model_class)\n    return [field.name for field in fields]\n\n\ndef get_field_by_name_or_raise(model_class, field_name):\n    \"Get field by name, including inherited fields and M2M fields.\"\n    return model_class._meta.get_field(field_name)\n\n\ndef is_model_class(instance_or_model_class):\n    \"True if model_class is a Django Model.\"\n    return isinstance(instance_or_model_class, Model) or instance_or_model_class.__class__ == ModelBase\n\n\ndef is_model_abstract(model):\n    \"True if abstract is True in Meta class\"\n    return model._meta.abstract\n\n\ndef is_model_managed(model):\n    \"True if managed is True in Meta class\"\n    return model._meta.managed\n\n\ndef model_has_the_field(model_class, field_name):\n    \"\"\n    try:\n        get_field_by_name_or_raise(model_class, field_name)\n        return True\n    except FieldDoesNotExist:\n        return False\n\n\n# Fields\ndef get_unique_field_name(field):\n    if hasattr(field, 'model'):\n        return get_unique_model_name(field.model) + '.' + field.name\n    return field.name or ''\n\n\ndef get_related_model(field):\n    return field.remote_field.model if hasattr(field, 'remote_field') else field.rel.to\n\n\ndef field_is_a_parent_link(field):\n    # FIXME\n    #return hasattr(field, 'rel') and hasattr(field.rel, 'parent_link') and field.rel.parent_link\n    return hasattr(field, 'parent_link') and field.parent_link\n\n\ndef field_has_choices(field):\n    \"\"\"field.choices may be a tee, which we can't count without converting\n    it to a list, or it may be a large database queryset, in which case we\n    don't want to convert it to a list. We only care if the list is empty\n    or not, so just try to access the first element and return True if that\n    doesn't throw an exception.\"\"\"\n    if not field.choices:\n        return False\n    for i in field.choices:\n        return True\n    return False\n\n\ndef field_has_default_value(field):\n    return field.default != NOT_PROVIDED\n\n\ndef field_is_unique(field):\n    return field.unique\n\n\ndef is_key_field(field):\n    return isinstance(field, AutoField)\n\n\ndef is_relationship_field(field):\n    return isinstance(field, (ForeignKey, OneToOneField))\n\n\ndef is_file_field(field):\n    return isinstance(field, FileField)\n\n\ndef print_field_values_of_a_model(model_instance):\n    \"Print values from all fields of a model instance.\"\n    if model_instance == None:\n        print('\\n:: Model Unknown: None')\n    else:\n        print('\\n:: Model %s (%s)' % (get_unique_model_name(model_instance.__class__), model_instance.pk))\n        for field in get_fields_from_model(model_instance.__class__):\n            try:\n                value = getattr(model_instance, field.name)\n            except Exception as e:\n                value = repr(e)\n            print('%s: %s' % (field.name, value))\n        if model_instance.pk is not None:\n            for field in get_many_to_many_fields_from_model(model_instance.__class__):\n                print('%s: %s' % (field.name, getattr(model_instance, field.name).all()))\n\n\ndef print_field_values(model_instance_or_list_of_model_instances_or_queryset):\n    \"Print values from all fields of a model instance or a list of model instances.\"\n    if isinstance(model_instance_or_list_of_model_instances_or_queryset, (list, tuple, QuerySet)):\n        for model_instance in model_instance_or_list_of_model_instances_or_queryset:\n            print_field_values_of_a_model(model_instance)\n    else:\n        model_instance = model_instance_or_list_of_model_instances_or_queryset\n        print_field_values_of_a_model(model_instance)\n\n\ndef enable_auto_now(field):\n    if hasattr(field, 'auto_now'):\n        field.auto_now = True\n\ndef disable_auto_now(field):\n    if hasattr(field, 'auto_now'):\n        field.auto_now = False\n\ndef enable_auto_now_add(field):\n    if hasattr(field, 'auto_now_add'):\n        field.auto_now_add = True\n\ndef disable_auto_now_add(field):\n    if hasattr(field, 'auto_now_add'):\n        field.auto_now_add = False\n\n\n\ndef is_boolean(field):\n    return isinstance(field, (BooleanField, NullBooleanField))\n\ndef is_string(field):\n    return isinstance(field, (CharField, EmailField, IPAddressField, SlugField, URLField))\n\ndef is_number(field):\n    return isinstance(field, (IntegerField, SmallIntegerField, PositiveIntegerField,\n        PositiveSmallIntegerField, BigIntegerField, CommaSeparatedIntegerField, DecimalField, FloatField))\n\ndef is_datetime(field):\n    return isinstance(field, (DateTimeField, DateField, TimeField))\n\ndef is_file(field):\n    return isinstance(field, (FileField, FilePathField))\n\ndef is_binary(field):\n    return isinstance(field, (BinaryField))\n"
  },
  {
    "path": "django_dynamic_fixture/fdf.py",
    "content": "\nimport os\nimport tempfile\n\nfrom shutil import rmtree, copy2\nfrom django.core.files import File\n\nfrom django.test import TestCase\nfrom django.conf import settings\nfrom django.core.files.storage import FileSystemStorage\n\n\nTEMP_PATH = tempfile.gettempdir() or os.environ.get('TEMP')\nTEMP_PATH_DDF = os.path.join(TEMP_PATH, 'DDF_TEMP')\n\n\nclass CustomFileSystemStorage(FileSystemStorage):\n    def __init__(self, *args, **kwargs):\n        super().\\\n        __init__(location=TEMP_PATH_DDF, *args, **kwargs)\n\n\nclass FileSystemDjangoTestCase(TestCase):\n    TEAR_DOWN_ENABLED = True\n\n    def setUp(self):\n        self.fdf_setup()\n\n    def tearDown(self):\n        self.fdf_teardown()\n\n    def _pre_setup(self):\n        super()._pre_setup()\n        self.fdf_setup()\n\n    def _post_teardown(self):\n        \"Try to remove all files and directories created by the test.\"\n        super()._post_teardown()\n        self.fdf_teardown()\n\n    def fdf_setup(self):\n        self.directories = []\n        self.files = {}\n        setattr(settings, 'DEFAULT_FILE_STORAGE', 'django_dynamic_fixture.fdf.CustomFileSystemStorage')\n\n    def fdf_teardown(self):\n        if self.TEAR_DOWN_ENABLED:\n            while self.files:\n                self.remove_temp_file(next(iter(self.files.keys())))\n            while self.directories:\n                self.remove_temp_directory(self.directories[0])\n            if os.path.exists(TEMP_PATH_DDF):\n                rmtree(TEMP_PATH_DDF)\n\n    def create_temp_directory(self, prefix='file_system_test_case_dir_'):\n        \"Create a temporary directory and returns the directory pathname.\"\n        directory = tempfile.mkdtemp(prefix=prefix)\n        self.directories.append(directory)\n        return directory\n\n    def remove_temp_directory(self, directory_pathname):\n        \"Remove a directory.\"\n        rmtree(directory_pathname)\n        if directory_pathname in self.directories:\n            try:\n                self.directories.remove(directory_pathname)\n            except WindowsError:\n                pass\n\n    def create_temp_file(self, directory=None, prefix='file_system_test_case_file_', suffix='.tmp'):\n        \"\"\"\n        Create a temporary file with a option prefix and suffix in a temporary or custom directory.\n        Returns the filepath\n        \"\"\"\n        tmp_file = tempfile.mkstemp(prefix=prefix, dir=directory, suffix=suffix)\n        file_obj = os.fdopen(tmp_file[0])\n        self.files[tmp_file[1]] = file_obj\n        return tmp_file[1]\n\n    def create_temp_file_with_name(self, directory, name):\n        \"Create a temporary file with a specified name.\"\n        filepath = os.path.join(directory, name)\n        file_obj = open(filepath, 'wb')\n        file_obj.close()\n        self.files[filepath] = file_obj\n        return filepath\n\n    def rename_temp_file(self, filepath, name):\n        \"Rename an existent file. 'name' is not a file path, so it must not include the directory path name.\"\n        directory = self.get_directory_of_the_file(filepath)\n        new_filepath = os.path.join(directory, name)\n        os.rename(filepath, new_filepath)\n        if filepath in self.files.keys():\n            self.files.pop(filepath)\n        self.files[new_filepath] = open(new_filepath, 'a+b')\n        self.files[new_filepath].close()\n        return new_filepath\n\n    def remove_temp_file(self, filepath):\n        \"Remove a file.\"\n        if filepath in self.files.keys():\n            fileobj = self.files.pop(filepath)\n            fileobj.close()\n        if os.path.exists(filepath):\n            try:\n                os.unlink(filepath)\n            except WindowsError:\n                pass\n\n    def copy_file_to_dir(self, filepath, directory):\n        \"Copy a file to a specified directory.\"\n        copy2(filepath, directory)\n        return self.get_filepath(directory, self.get_filename(filepath))\n\n    def add_text_to_file(self, filepath, content):\n        \"Add text to an existent file.\"\n        file = open(filepath, 'a')\n        file.write(content)\n        file.close()\n\n    def get_directory_of_the_file(self, filepath):\n        \"Get the directory path name of a file.\"\n        return os.path.dirname(filepath)\n\n    def get_filename(self, filepath):\n        \"Get the filename of a file.\"\n        return os.path.basename(filepath)\n\n    def get_filepath(self, directory, filename):\n        \"Get the file path of a file with a defined name in a directory.\"\n        return os.path.join(directory, filename)\n\n    def get_content_of_file(self, filepath):\n        \"Returns the content of a file.\"\n        file = open(filepath, 'r')\n        content = file.read()\n        file.close()\n        return content\n\n    def create_django_file_with_temp_file(self, name, content=None, dir=None, prefix='file_system_test_case_file_', suffix='.tmp'):\n        \"Create and returns a django.core.files.File\"\n        file = open(self.create_temp_file(directory=dir, prefix=prefix, suffix=suffix), 'w')\n        file.close()\n        django_file = File(file, name=name)\n        self.files[django_file.file.name] = open(django_file.file.name, 'a+b')\n        if content:\n            self.files[django_file.file.name].write(content)\n        self.files[django_file.file.name].close()\n        return django_file\n\n    def create_django_file_using_file(self, filepath):\n        \"Create and returns a django.core.files.File\"\n        new_filepath = self.copy_file_to_dir(filepath, self.create_temp_directory())\n        the_file = open(new_filepath, 'rb')\n        django_file = File(the_file, name=os.path.basename(new_filepath))\n        self.files[django_file.file.name] = the_file\n        #self.files[django_file.file.name].close()\n        return django_file\n\n    def assertFileExists(self, filepath):\n        assert os.path.exists(filepath), '%s does not exist' % filepath\n\n    def assertFileDoesNotExists(self, filepath):\n        assert os.path.exists(filepath) is False, '%s exist' % filepath\n\n    def assertDirectoryExists(self, directory):\n        \"@directory must be the directory path\"\n        assert os.path.exists(directory), '%s does not exist' % directory\n\n    def assertDirectoryDoesNotExists(self, directory):\n        \"@directory must be the directory path\"\n        assert os.path.exists(directory) is False, '%s exist' % directory\n\n    def assertDirectoryContainsFile(self, directory, filename):\n        filepath = os.path.join(directory, filename)\n        self.assertFileExists(filepath)\n\n    def assertDirectoryDoesNotContainsFile(self, directory, filename):\n        filepath = os.path.join(directory, filename)\n        self.assertFileDoesNotExists(filepath)\n\n    def assertFilesHaveEqualLastModificationTimestamps(self, filepath1, filepath2):\n        assert os.path.getmtime(filepath1) - os.path.getmtime(filepath2) == 0\n\n    def assertFilesHaveNotEqualLastModificationTimestamps(self, filepath1, filepath2):\n        assert os.path.getmtime(filepath1) - os.path.getmtime(filepath2) != 0\n\n    def assertNumberOfFiles(self, directory, number_of_files):\n        filenames = [filename for filename in os.listdir(directory) if os.path.isfile(os.path.join(directory, filename))]\n        assert len(filenames) == number_of_files, '[%s] %s' % (len(filenames), filenames)\n"
  },
  {
    "path": "django_dynamic_fixture/fields.py",
    "content": "import json\n\nfrom django.conf import settings\nfrom django.contrib.postgres.fields import (\n    JSONField as DjangoJSONField,\n    ArrayField as DjangoArrayField,\n)\nfrom django.db.models import Field\n\n\nclass JSONField(DjangoJSONField):\n    pass\n\n\nclass ArrayField(DjangoArrayField):\n    pass\n\n\nif 'sqlite' in settings.DATABASES['default']['ENGINE']:\n    class JSONField(Field):\n        def db_type(self, connection):\n            return 'text'\n\n        def from_db_value(self, value, expression, connection):\n            if value is not None:\n                return self.to_python(value)\n            return value\n\n        def to_python(self, value):\n            if value is not None:\n                try:\n                    return json.loads(value)\n                except (TypeError, ValueError):\n                    return value\n            return value\n\n        def get_prep_value(self, value):\n            if value is not None:\n                return str(json.dumps(value))\n            return value\n\n        def value_to_string(self, obj):\n            return self.value_from_object(obj)\n\n\n    class ArrayField(JSONField):\n        def __init__(self, base_field, size=None, **kwargs):\n            \"\"\"Care for DjanroArrayField's kwargs.\"\"\"\n            self.base_field = base_field\n            self.size = size\n            return super().__init__(**kwargs)\n\n        def deconstruct(self):\n            \"\"\"Need to create migrations properly.\"\"\"\n            name, path, args, kwargs = super().deconstruct()\n            kwargs.update({\n                'base_field': self.base_field.clone(),\n                'size': self.size,\n            })\n            return name, path, args, kwargs\n"
  },
  {
    "path": "django_dynamic_fixture/fixture_algorithms/__init__.py",
    "content": "from django_dynamic_fixture.fixture_algorithms.sequential_fixture import SequentialDataFixture, StaticSequentialDataFixture\nfrom django_dynamic_fixture.fixture_algorithms.random_fixture import RandomDataFixture\n\n\nclass FixtureFactory:\n    @staticmethod\n    def get(data_fixture):\n        if data_fixture == 'static_sequential':\n            return SequentialDataFixture()\n        elif data_fixture == 'sequential':\n            return SequentialDataFixture()\n        elif data_fixture == 'random':\n            return RandomDataFixture()\n        return data_fixture"
  },
  {
    "path": "django_dynamic_fixture/fixture_algorithms/default_fixture.py",
    "content": "# -*- coding: utf-8 -*-\nfrom datetime import datetime, date, timedelta\nfrom decimal import Decimal\nimport random\nimport string\nimport uuid\n\nfrom django.core.exceptions import ImproperlyConfigured\n\n\ntry:\n    from django.utils.timezone import now\nexcept ImportError:\n    now = datetime.now\n\ntry:\n    from django.contrib.gis.geos import *\nexcept ImproperlyConfigured:\n    pass  # environment without geo libs\nexcept Exception:\n    pass # Avoid errors like GDALException\n\n\nfrom django_dynamic_fixture.ddf import DataFixture\n\n\nclass BaseDataFixture(DataFixture):\n    # Django >= 1.6\n    def binaryfield_config(self, field, key):\n        return b'\\x00\\x46\\xFE'\n\n    # Django >= 1.8\n    def uuidfield_config(self, field, key):\n        return uuid.uuid4()\n\n    # Django >= 1.4\n    def genericipaddressfield_config(self, field, key):\n        return self.ipaddressfield_config(field, key)\n\n    # POSTGRES\n    def  jsonfield_config(self, field, key):\n        return {}\n\n\n# GIS/GeoDjango\nclass GeoDjangoFixtureMixin:\n    def create_point(self, x=None, y=None):\n        # latitude: [-90,90], longitude: [-180,180]\n        latitude = x or random.randint(-90, 90)\n        longitude = y or random.randint(-180, 180)\n        return Point(longitude, latitude)\n\n    def create_points(self, n=3, closed=True):\n        points = [self.create_point() for i in range(n)]\n        if closed: # LinearRing\n            points.append(points[0])\n        return points\n\n    def geometryfield_config(self, field, key):\n        return GEOSGeometry('POINT(%s %s)' % self.create_point().coords)\n\n    def pointfield_config(self, field, key):\n        return self.create_point()\n\n    def linestringfield_config(self, field, key, n=3):\n        return LineString(self.create_points(n))\n\n    def polygonfield_config(self, field, key, n=3):\n        return Polygon(self.create_points(n))\n\n    def multipointfield_config(self, field, key, n=3):\n        return MultiPoint(self.create_points(n))\n\n    def multilinestringfield_config(self, field, key, n=3):\n        lines = [self.linestringfield_config(field, key, n) for i in range(n)]\n        return MultiLineString(lines)\n\n    def multipolygonfield_config(self, field, key, n=3):\n        polygons = [self.polygonfield_config(field, key, n) for i in range(n)]\n        return MultiPolygon(polygons)\n\n    def geometrycollectionfield_config(self, field, key, n=3):\n        polygons = [self.polygonfield_config(field, key, n) for i in range(n)]\n        return GeometryCollection(polygons)\n\n\n# Postgres fields\n# https://docs.djangoproject.com/en/1.8/ref/contrib/postgres/fields/\nclass PostgresFixtureMixin:\n    def arrayfield_config(self, field, key, n=1):\n        data = [self.generate_data(field.base_field) for i in range(n)]\n        return data\n"
  },
  {
    "path": "django_dynamic_fixture/fixture_algorithms/random_fixture.py",
    "content": "from datetime import datetime, date, timedelta\nfrom decimal import Decimal\nimport random\nimport string\n\nfrom django.core.exceptions import ImproperlyConfigured\n\ntry:\n    from django.utils.timezone import now\nexcept ImportError:\n    now = datetime.now\n\ntry:\n    from django.contrib.gis.geos import *\nexcept ImproperlyConfigured:\n    pass  # environment without geo libs\nexcept Exception:\n    pass # Avoid errors like GDALException\n\nfrom django_dynamic_fixture.fixture_algorithms.default_fixture import BaseDataFixture, GeoDjangoFixtureMixin, PostgresFixtureMixin\n\n\nclass RandomDataFixture(BaseDataFixture, GeoDjangoFixtureMixin, PostgresFixtureMixin):\n    def random_string(self, n):\n        return ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(n))\n\n    # NUMBERS\n    def integerfield_config(self, field, key, start=1, end=10 ** 6):\n        return random.randint(start, end)\n\n    def smallintegerfield_config(self, field, key):\n        # Values from -32768 to 32767 are safe in all databases supported by Django.\n        return self.integerfield_config(field, key, -2 ** 15, 2 ** 15 - 1)\n\n    def positiveintegerfield_config(self, field, key):\n        return self.integerfield_config(field, key)\n\n    def positivesmallintegerfield_config(self, field, key):\n        # Values up to 32767 are safe in all databases supported by Django.\n        return self.integerfield_config(field, key, end=2 ** 15 - 1)\n\n    def bigintegerfield_config(self, field, key):\n        return self.integerfield_config(field, key)\n\n    def floatfield_config(self, field, key):\n        return float(self.integerfield_config(field, key))\n\n    def decimalfield_config(self, field, key):\n        data = self.integerfield_config(field, key)\n        number_of_digits = field.max_digits - field.decimal_places\n        max_value = 10 ** number_of_digits\n        data = data % max_value\n        return Decimal(str(data))\n\n    # STRINGS\n    def charfield_config(self, field, key):\n        if field.max_length:\n            length = field.max_length\n        else:\n            length = 10\n        return self.random_string(length)\n\n    def textfield_config(self, field, key):\n        return self.charfield_config(field, key)\n\n    def slugfield_config(self, field, key):\n        return self.charfield_config(field, key)\n\n    def commaseparatedintegerfield_config(self, field, key):\n        return str(random.randint(1, field.max_length)) #FIXME:\n\n    # BOOLEAN\n    def booleanfield_config(self, field, key):\n        return random.randint(0, 1) == 0\n\n    def nullbooleanfield_config(self, field, key):\n        values = {0: None, 1: False, 2: True}\n        return values[random.randint(0, 2)]\n\n    # DATE/TIME RELATED\n    def datefield_config(self, field, key):\n        return date.today() - timedelta(days=random.randint(1, 36500))\n\n    def timefield_config(self, field, key):\n        return (now() - timedelta(seconds=random.randint(1, 36500))).time()\n\n    def datetimefield_config(self, field, key):\n        return now() - timedelta(seconds=random.randint(1, 36500))\n\n    # FORMATTED STRINGS\n    def emailfield_config(self, field, key):\n        return f'a{self.random_string(10)}@dynamicfixture.com'\n\n    def urlfield_config(self, field, key):\n        return f'http://dynamicfixture{self.random_string(10)}.com'\n\n    # Deprecated in Django >= 1.7\n    def ipaddressfield_config(self, field, key):\n        a = random.randint(1, 255)\n        b = random.randint(1, 255)\n        c = random.randint(1, 255)\n        d = random.randint(1, 255)\n        return f'{a}.{b}.{c}.{d}'\n\n    def xmlfield_config(self, field, key):\n        return f'<a>{self.random_string(5)}</a>'\n\n    # FILES\n    def filepathfield_config(self, field, key):\n        return self.random_string(10)\n\n    def filefield_config(self, field, key):\n        return self.random_string(10)\n\n    def imagefield_config(self, field, key):\n        return self.random_string(10)\n"
  },
  {
    "path": "django_dynamic_fixture/fixture_algorithms/sequential_fixture.py",
    "content": "from datetime import datetime, date, timedelta\nfrom decimal import Decimal\nimport threading\n\nfrom django.core.exceptions import ImproperlyConfigured\n\ntry:\n    from django.utils.timezone import now\nexcept ImportError:\n    now = datetime.now\n\ntry:\n    from django.contrib.gis.geos import *\nexcept ImproperlyConfigured:\n    pass  # environment without geo libs\nexcept Exception:\n    pass # Avoid errors like GDALException\n\nfrom django_dynamic_fixture.fixture_algorithms.default_fixture import BaseDataFixture, GeoDjangoFixtureMixin, PostgresFixtureMixin\nfrom django_dynamic_fixture.django_helper import field_is_unique\n\n\nclass AutoDataFiller:\n    \"\"\"\n    Responsibility: generate a unique and sequential value for each key.\n    \"\"\"\n\n    def __init__(self):\n        self.__data_controller_map = {} # key => counter\n        self.__locks = {} # key => lock\n\n    # synchronized by key\n    def next(self, key):\n        if key not in self.__data_controller_map:\n            self.__data_controller_map[key] = 0\n            self.__locks[key] = threading.RLock()\n        self.__locks[key].acquire()\n        self.__data_controller_map[key] += 1\n        value = self.__data_controller_map[key]\n        self.__locks[key].release()\n        return value\n\n    def current(self, key):\n        if key not in self.__data_controller_map:\n            self.next(key)\n        return self.__data_controller_map[key]\n\n\nclass SequentialDataFixture(BaseDataFixture, GeoDjangoFixtureMixin, PostgresFixtureMixin):\n\n    def __init__(self):\n        super().__init__()\n        self.filler = AutoDataFiller()\n\n    def get_value(self, field, key):\n        return self.filler.next(key)\n\n    # NUMBERS\n    def integerfield_config(self, field, key):\n        return self.get_value(field, key)\n\n    def smallintegerfield_config(self, field, key):\n        return self.integerfield_config(field, key)\n\n    def positiveintegerfield_config(self, field, key):\n        return self.integerfield_config(field, key)\n\n    def positivesmallintegerfield_config(self, field, key):\n        return self.integerfield_config(field, key)\n\n    def bigintegerfield_config(self, field, key):\n        return self.integerfield_config(field, key)\n\n    def floatfield_config(self, field, key):\n        return float(self.get_value(field, key))\n\n    def decimalfield_config(self, field, key):\n        data = self.get_value(field, key)\n        number_of_digits = field.max_digits - field.decimal_places\n        max_value = 10 ** number_of_digits\n        data = data % max_value\n        return Decimal(str(data))\n\n    # STRINGS\n    def charfield_config(self, field, key):\n        data = self.get_value(field, key)\n        if field.max_length:\n            max_value = (10 ** field.max_length) - 1\n            data = str(data % max_value)\n            data = data[:field.max_length]\n        else:\n            data = str(data)\n        return data\n\n    def textfield_config(self, field, key):\n        return self.charfield_config(field, key)\n\n    def slugfield_config(self, field, key):\n        return self.charfield_config(field, key)\n\n    def commaseparatedintegerfield_config(self, field, key):\n        return self.charfield_config(field, key)\n\n    # BOOLEAN\n    def booleanfield_config(self, field, key):\n        return False\n\n    def nullbooleanfield_config(self, field, key):\n        return None\n\n    # DATE/TIME RELATED\n    def datefield_config(self, field, key):\n        data = self.get_value(field, key)\n        return date.today() - timedelta(days=data)\n\n    def timefield_config(self, field, key):\n        data = self.get_value(field, key)\n        return (now() - timedelta(seconds=data)).time()\n\n    def datetimefield_config(self, field, key):\n        data = self.get_value(field, key)\n        return now() - timedelta(seconds=data)\n\n    # FORMATTED STRINGS\n    def emailfield_config(self, field, key):\n        return f'a{self.get_value(field, key)}@dynamicfixture.com'\n\n    def urlfield_config(self, field, key):\n        return f'http://dynamicfixture{self.get_value(field, key)}.com'\n\n    # Deprecated in Django >= 1.7\n    def ipaddressfield_config(self, field, key):\n        # TODO: better workaround (this suppose ip field is not unique)\n        data = self.get_value(field, key)\n        a = '1'\n        b = '1'\n        c = '1'\n        d = data % 256\n        return f'{a}.{b}.{c}.{d}'\n\n    def xmlfield_config(self, field, key):\n        return f'<a>{self.get_value(field, key)}</a>'\n\n    # FILES\n    def filepathfield_config(self, field, key):\n        return str(self.get_value(field, key))\n\n    def filefield_config(self, field, key):\n        return str(self.get_value(field, key))\n\n    def imagefield_config(self, field, key):\n        return str(self.get_value(field, key))\n\n\nclass GlobalSequentialDataFixture(SequentialDataFixture):\n    def get_value(self, field, key):\n        return self.filler.next('ddf-global-key')\n\n\nclass StaticSequentialDataFixture(SequentialDataFixture):\n    def get_value(self, field, key):\n        if field_is_unique(field):\n            return self.filler.next(key)\n        else:\n            return self.filler.current(key)\n"
  },
  {
    "path": "django_dynamic_fixture/fixture_algorithms/tests/__init__.py",
    "content": "\n"
  },
  {
    "path": "django_dynamic_fixture/fixture_algorithms/tests/abstract_test_generic_fixture.py",
    "content": "\nfrom django.db import models\n\nfrom datetime import datetime, date, time\nfrom decimal import Decimal\n\n\nclass DataFixtureTestCase:\n    def setUp(self):\n        self.fixture = None\n\n    def test_numbers(self):\n        assert isinstance(self.fixture.generate_data(models.IntegerField()), int)\n        assert isinstance(self.fixture.generate_data(models.SmallIntegerField()), int)\n        assert isinstance(self.fixture.generate_data(models.PositiveIntegerField()), int)\n        assert isinstance(self.fixture.generate_data(models.PositiveSmallIntegerField()), int)\n        assert isinstance(self.fixture.generate_data(models.BigIntegerField()), int)\n        assert isinstance(self.fixture.generate_data(models.FloatField()), float)\n        assert isinstance(self.fixture.generate_data(models.DecimalField(max_digits=1, decimal_places=1)), Decimal)\n\n    def test_it_must_deal_with_decimal_max_digits(self):\n        # value 10 must be a problem, need to restart the counter: 10.0 has 3 digits\n        for _ in range(11):\n            assert isinstance(self.fixture.generate_data(models.DecimalField(max_digits=1, decimal_places=1)), Decimal)\n            assert isinstance(self.fixture.generate_data(models.DecimalField(max_digits=2, decimal_places=1)), Decimal)\n\n    def test_strings(self):\n        assert isinstance(self.fixture.generate_data(models.CharField(max_length=1)), str)\n        assert isinstance(self.fixture.generate_data(models.TextField()), str)\n        assert isinstance(self.fixture.generate_data(models.SlugField(max_length=1)), str)\n        assert isinstance(self.fixture.generate_data(models.CommaSeparatedIntegerField(max_length=1)), str)\n\n    def test_new_truncate_strings_to_max_length(self):\n        for _ in range(12): # truncate start after the 10 object\n            assert isinstance(self.fixture.generate_data(models.CharField(max_length=1)), str)\n\n    def test_boolean(self):\n        assert isinstance(self.fixture.generate_data(models.BooleanField()), bool)\n        value = self.fixture.generate_data(models.NullBooleanField())\n        assert isinstance(value, bool) or value is None\n\n    def test_date_time_related(self):\n        assert isinstance(self.fixture.generate_data(models.DateField()), date)\n        assert isinstance(self.fixture.generate_data(models.TimeField()), time)\n        assert isinstance(self.fixture.generate_data(models.DateTimeField()), datetime)\n\n    def test_formatted_strings(self):\n        assert isinstance(self.fixture.generate_data(models.EmailField(max_length=100)), str)\n        assert isinstance(self.fixture.generate_data(models.URLField(max_length=100)), str)\n        assert isinstance(self.fixture.generate_data(models.IPAddressField(max_length=100)), str)\n        assert isinstance(self.fixture.generate_data(models.GenericIPAddressField(max_length=100)), str)\n\n    def test_files(self):\n        assert isinstance(self.fixture.generate_data(models.FilePathField(max_length=100)), str)\n        assert isinstance(self.fixture.generate_data(models.FileField()), str)\n        try:\n            import pil\n            # just test it if the PIL package is installed\n            assert isinstance(self.fixture.generate_data(models.ImageField(max_length=100)), str)\n        except ImportError:\n            pass\n\n"
  },
  {
    "path": "django_dynamic_fixture/fixture_algorithms/tests/test_default_fixture.py",
    "content": "import uuid\n\nfrom django.db import models\nfrom django.conf import settings\nfrom django.core.exceptions import ImproperlyConfigured\n\n\ntry:\n    from django.contrib.gis.geos import *\n    from django.contrib.gis.db import models as geomodels\nexcept ImproperlyConfigured:\n    pass  # environment without geo libs\n\n\nfrom django.test import TestCase\n\nfrom django_dynamic_fixture.fixture_algorithms.default_fixture import BaseDataFixture\n\n\nclass BaseDataFixtureTestCase(TestCase):\n    def setUp(self):\n        self.fixture = BaseDataFixture()\n\n    def test_uuid(self):\n        assert isinstance(self.fixture.generate_data(models.UUIDField()), uuid.UUID)\n\n\nif (hasattr(settings, 'DDF_TEST_GEODJANGO') and settings.DDF_TEST_GEODJANGO):\n    from django_dynamic_fixture.fixture_algorithms.default_fixture import GeoDjangoFixtureMixin\n\n    # Mixing for tests\n    class GeoDjangoFixtureMixin(BaseDataFixture, GeoDjangoFixtureMixin):\n        pass\n\n    class GeoDjangoDataFixtureTestCase(TestCase):\n        def setUp(self):\n            self.fixture = GeoDjangoFixtureMixin()\n\n        def test_geometryfield_config(self):\n            assert isinstance(self.fixture.generate_data(geomodels.GeometryField()), GEOSGeometry)\n\n        def test_pointfield_config(self):\n            assert isinstance(self.fixture.generate_data(geomodels.PointField()), Point)\n\n        def test_linestringfield_config(self):\n            assert isinstance(self.fixture.generate_data(geomodels.LineStringField()), LineString)\n\n        def test_polygonfield_config(self):\n            assert isinstance(self.fixture.generate_data(geomodels.PolygonField()), Polygon)\n\n        def test_multipointfield_config(self):\n            assert isinstance(self.fixture.generate_data(geomodels.MultiPointField()), MultiPoint)\n\n        def test_multilinesstringfield_config(self):\n            assert isinstance(self.fixture.generate_data(geomodels.MultiLineStringField()), MultiLineString)\n\n        def test_multipolygonfield_config(self):\n            assert isinstance(self.fixture.generate_data(geomodels.MultiPolygonField()), MultiPolygon)\n\n        def test_geometrycollectionfield_config(self):\n            assert isinstance(self.fixture.generate_data(geomodels.GeometryCollectionField()), GeometryCollection)\n"
  },
  {
    "path": "django_dynamic_fixture/fixture_algorithms/tests/test_default_fixture_postgres.py",
    "content": "from datetime import datetime\n\nfrom django.db import models\nfrom django.test import TestCase\n\nfrom django_dynamic_fixture.fixture_algorithms.default_fixture import PostgresFixtureMixin\nfrom django_dynamic_fixture.fixture_algorithms.sequential_fixture import SequentialDataFixture, StaticSequentialDataFixture\nfrom django_dynamic_fixture.fixture_algorithms.random_fixture import RandomDataFixture\nfrom django_dynamic_fixture.fixture_algorithms.unique_random_fixture import UniqueRandomDataFixture\n\ntry:\n    import psycopg2\n    from django.contrib.postgres.fields import ArrayField\n\n    class PostgresDataFixtureTestMixin:\n        def test_arrayfield_integer_config(self):\n            data = self.fixture.generate_data(ArrayField(models.IntegerField()))\n            assert isinstance(data, list)\n            assert isinstance(data[0], int)\n\n        def test_arrayfield_char_config(self):\n            data = self.fixture.generate_data(ArrayField(models.CharField()))\n            assert isinstance(data, list)\n            assert isinstance(data[0], str)\n\n        def test_arrayfield_datetime_config(self):\n            data = self.fixture.generate_data(ArrayField(models.DateTimeField()))\n            assert isinstance(data, list)\n            assert isinstance(data[0], datetime)\n\n        def test_arrayfield_email_config(self):\n            data = self.fixture.generate_data(ArrayField(models.EmailField(max_length=100)))\n            assert isinstance(data, list)\n            assert isinstance(data[0], str)\n\n\n    class PostgresSequentialDataFixtureTestCase(TestCase, PostgresDataFixtureTestMixin):\n        def setUp(self):\n            class CustomFixture(SequentialDataFixture, PostgresFixtureMixin):\n                pass\n            self.fixture = CustomFixture()\n\n    class PostgresStaticSequentialDataFixtureTestCase(TestCase, PostgresDataFixtureTestMixin):\n        def setUp(self):\n            class CustomFixture(StaticSequentialDataFixture, PostgresFixtureMixin):\n                pass\n            self.fixture = CustomFixture()\n\n    class PostgresRandomDataFixtureTestCase(TestCase, PostgresDataFixtureTestMixin):\n        def setUp(self):\n            class CustomFixture(RandomDataFixture, PostgresFixtureMixin):\n                pass\n            self.fixture = CustomFixture()\n\n    class PostgresUniqueRandomDataFixtureTestCase(TestCase, PostgresDataFixtureTestMixin):\n        def setUp(self):\n            class CustomFixture(UniqueRandomDataFixture, PostgresFixtureMixin):\n                pass\n            self.fixture = CustomFixture()\n\nexcept (ImportError, ModuleNotFoundError):\n    print('Skipping Postgres tests because psycopg2 has not been installed.')\n"
  },
  {
    "path": "django_dynamic_fixture/fixture_algorithms/tests/test_random_fixture.py",
    "content": "\nfrom django.test import TestCase\n\nfrom django_dynamic_fixture.fixture_algorithms.tests.abstract_test_generic_fixture import DataFixtureTestCase\nfrom django_dynamic_fixture.fixture_algorithms.random_fixture import RandomDataFixture\n\n\nclass RandomDataFixtureTestCase(TestCase, DataFixtureTestCase):\n    def setUp(self):\n        self.fixture = RandomDataFixture()\n"
  },
  {
    "path": "django_dynamic_fixture/fixture_algorithms/tests/test_sequential_fixture.py",
    "content": "from django.db import models\n\nfrom django.test import TestCase\n\nfrom django_dynamic_fixture.fixture_algorithms.tests.abstract_test_generic_fixture import DataFixtureTestCase\nfrom django_dynamic_fixture.fixture_algorithms.sequential_fixture import SequentialDataFixture, StaticSequentialDataFixture\n\n\nclass SequentialDataFixtureTestCase(TestCase, DataFixtureTestCase):\n    def setUp(self):\n        self.fixture = SequentialDataFixture()\n\n    def test_it_must_fill_integer_fields_sequencially_by_attribute(self):\n        assert self.fixture.generate_data(models.IntegerField()) == 1\n        field = models.IntegerField()\n        field.name = 'x'\n        assert self.fixture.generate_data(field) == 1\n        assert self.fixture.generate_data(field) == 2\n\n    def test_it_must_fill_string_with_sequences_of_numbers_by_attribute(self):\n        assert self.fixture.generate_data(models.CharField(max_length=1)) == '1'\n        field = models.CharField(max_length=1)\n        field.name = 'x'\n        assert self.fixture.generate_data(field) == '1'\n        assert self.fixture.generate_data(field) == '2'\n\n\nclass StaticSequentialDataFixtureTestCase(TestCase, DataFixtureTestCase):\n    def setUp(self):\n        self.fixture = StaticSequentialDataFixture()\n\n    def test_it_must_fill_fields_sequencially_by_attribute_if_field_is_unique(self):\n        field = models.IntegerField(unique=True)\n        field.name = 'x'\n        assert self.fixture.generate_data(field) == 1\n        assert self.fixture.generate_data(field) == 2\n\n    def test_it_must_fill_fields_with_static_value_by_attribute_if_field_is_not_unique(self):\n        field = models.IntegerField(unique=False)\n        field.name = 'x'\n        assert self.fixture.generate_data(field) == 1\n        assert self.fixture.generate_data(field) == 1\n\n"
  },
  {
    "path": "django_dynamic_fixture/fixture_algorithms/tests/test_unique_random_fixture.py",
    "content": "from warnings import catch_warnings\n\nfrom django.db import models\nfrom django.test import TestCase\n\nfrom django_dynamic_fixture.fixture_algorithms.tests.abstract_test_generic_fixture import DataFixtureTestCase\nfrom django_dynamic_fixture.fixture_algorithms.unique_random_fixture import \\\n    UniqueRandomDataFixture\n\n\nclass RandomDataFixtureTestCase(TestCase, DataFixtureTestCase):\n    def setUp(self):\n        self.fixture = UniqueRandomDataFixture()\n\n    def test_generated_strings_are_unique(self):\n        results = set()\n        for _ in range(self.fixture.OBJECT_COUNT):\n            results.add(\n                self.fixture.generate_data(models.CharField(max_length=10))\n            )\n        assert len(results) == self.fixture.OBJECT_COUNT\n\n    def test_generated_signed_integers_are_unique(self):\n        results = set()\n        prev = 0\n        for _ in range(self.fixture.OBJECT_COUNT):\n            integer = self.fixture.generate_data(models.IntegerField())\n            results.add(integer)\n            assert abs(integer) > abs(prev)\n            prev = integer\n        assert len(results) == self.fixture.OBJECT_COUNT\n\n    def test_generated_unsigned_integers_are_unique(self):\n        results = set()\n        prev = 0\n        for _ in range(self.fixture.OBJECT_COUNT):\n            integer = self.fixture.generate_data(models.PositiveIntegerField())\n            results.add(integer)\n            assert integer > prev\n            prev = integer\n        assert len(results) == self.fixture.OBJECT_COUNT\n\n    def test_warning(self):\n        with catch_warnings(record=True) as w:\n            for _ in range(self.fixture.OBJECT_COUNT + 1):\n                self.fixture.generate_data(models.CharField(max_length=10))\n            warning = w[-1]\n            assert issubclass(warning.category, RuntimeWarning)\n            expected_message = (\n                self.fixture.WARNING_MESSAGE_TMPL % self.fixture.OBJECT_COUNT\n            )\n            assert expected_message in str(warning.message)\n"
  },
  {
    "path": "django_dynamic_fixture/fixture_algorithms/unique_random_fixture.py",
    "content": "from datetime import datetime, date, timedelta\nfrom decimal import Decimal\nfrom itertools import chain\nimport random\nimport socket\nimport string\nimport struct\nfrom warnings import warn\n\nfrom django.core.exceptions import ImproperlyConfigured\n\ntry:\n    from django.utils.timezone import now\nexcept ImportError:\n    now = datetime.now\n\ntry:\n    from django.contrib.gis.geos import *\nexcept ImproperlyConfigured:\n    pass  # environment without geo libs\nexcept Exception:\n    pass # Avoid errors like GDALException\n\nfrom django_dynamic_fixture.fixture_algorithms.sequential_fixture import AutoDataFiller\nfrom django_dynamic_fixture.fixture_algorithms.default_fixture import BaseDataFixture, GeoDjangoFixtureMixin, PostgresFixtureMixin\n\n\nclass UniqueRandomDataFixture(BaseDataFixture, GeoDjangoFixtureMixin, PostgresFixtureMixin):\n    DEFAULT_LENGTH = 10\n    OBJECT_COUNT = 512\n    WARNING_MESSAGE_TMPL = (\n        'Maximum number of objects (%d) is exceeded in '\n        'unique_random_fixture. Uniqueness is not guaranteed.'\n    )\n\n    def __init__(self):\n        super().__init__()\n        self.filler = AutoDataFiller()\n\n    def get_counter(self, field, key):\n        result = self.filler.next(key)\n        if result > self.OBJECT_COUNT:\n            warn(self.WARNING_MESSAGE_TMPL % self.OBJECT_COUNT, RuntimeWarning)\n        return result\n\n    def random_string(self, field, key, n=None):\n        counter = str(self.get_counter(field, key))\n        length = n or self.DEFAULT_LENGTH\n        result = counter\n        result += ''.join(\n            random.choice(string.ascii_letters)\n            for _ in range(length - len(counter))\n        )\n        return result\n\n    def random_integer(self, field, key, signed=True):\n        counter = self.get_counter(field, key) - 1\n        counter %= self.OBJECT_COUNT\n        if not signed:\n            MAX_INT = 2 ** 16\n            multiplier = MAX_INT // self.OBJECT_COUNT\n            return random.randrange(\n                multiplier * counter + 1, multiplier * (counter + 1)\n            )\n\n        MAX_SIGNED_INT = 2 ** 15\n        multiplier = MAX_SIGNED_INT // self.OBJECT_COUNT\n        positive_range = range(\n            multiplier * counter + 1, multiplier * (counter + 1)\n        )\n        negative_range = range(\n            (-multiplier) * (counter + 1), (-multiplier) * counter\n        )\n        return random.choice(list(chain(positive_range, negative_range)))\n\n    # NUMBERS\n    def integerfield_config(self, field, key):\n        return self.random_integer(field, key)\n\n    def smallintegerfield_config(self, field, key):\n        return self.random_integer(field, key)\n\n    def bigintegerfield_config(self, field, key):\n        return self.random_integer(field, key)\n\n    def positiveintegerfield_config(self, field, key):\n        return self.random_integer(field, key, signed=False)\n\n    def positivesmallintegerfield_config(self, field, key):\n        return self.random_integer(field, key, signed=False)\n\n    def floatfield_config(self, field, key):\n        return float(self.random_integer(field, key)) + random.random()\n\n    def decimalfield_config(self, field, key):\n        number_of_digits = field.max_digits - field.decimal_places\n        max_value = 10 ** number_of_digits\n        value = self.random_integer(field, key) % max_value\n        value = float(value) + random.random()\n        return Decimal(str(value))\n\n    # STRINGS\n    def charfield_config(self, field, key):\n        return self.random_string(field, key, field.max_length)\n\n    def textfield_config(self, field, key):\n        return self.charfield_config(field, key)\n\n    def slugfield_config(self, field, key):\n        return self.charfield_config(field, key)\n\n    def commaseparatedintegerfield_config(self, field, key):\n        return self.charfield_config(field, key)\n\n    # BOOLEAN\n    def booleanfield_config(self, field, key):\n        counter = self.get_counter(field, key)\n        if counter == 1:\n            return True\n        elif counter == 2:\n            return False\n        return random.choice((True, False))\n\n    def nullbooleanfield_config(self, field, key):\n        counter = self.get_counter(field, key)\n        if counter == 1:\n            return None\n        elif counter == 2:\n            return True\n        elif counter == 3:\n            return False\n        return random.choice((None, True, False))\n\n    # DATE/TIME RELATED\n    def datefield_config(self, field, key):\n        integer = self.random_integer(field, key, signed=False)\n        return date.today() - timedelta(days=integer)\n\n    def timefield_config(self, field, key):\n        integer = self.random_integer(field, key, signed=False)\n        return (now() - timedelta(seconds=integer)).time()\n\n    def datetimefield_config(self, field, key):\n        integer = self.random_integer(field, key, signed=False)\n        return now() - timedelta(seconds=integer)\n\n    # FORMATTED STRINGS\n    def emailfield_config(self, field, key):\n        return f'a{self.random_string(field, key)}@dynamicfixture.com'\n\n    def urlfield_config(self, field, key):\n        return f'http://dynamicfixture{self.random_string(field, key)}.com'\n\n    # Deprecated in Django >= 1.7\n    def ipaddressfield_config(self, field, key):\n        MAX_IP = 2 ** 32 - 1\n\n        integer = self.random_integer(field, key, signed=False)\n        integer %= MAX_IP\n        return str(socket.inet_ntoa(struct.pack('!L', integer)))\n\n    def xmlfield_config(self, field, key):\n        return f'<a>{self.random_string(field, key)}</a>'\n\n    # FILES\n    def filepathfield_config(self, field, key):\n        return self.random_string(field, key)\n\n    def filefield_config(self, field, key):\n        return self.random_string(field, key)\n\n    def imagefield_config(self, field, key):\n        return self.random_string(field, key)\n"
  },
  {
    "path": "django_dynamic_fixture/global_settings.py",
    "content": "\n\"\"\"\nModule that contains wrappers and shortcuts.\nThis is the facade of all features of DDF.\n\"\"\"\nimport os\nimport sys\nimport warnings\n\nfrom django.conf import settings\nfrom django.urls import get_mod_func\ntry:\n    from importlib import import_module\nexcept ImportError:\n    from django.utils.importlib import import_module\n\nfrom django_dynamic_fixture.fixture_algorithms.sequential_fixture import SequentialDataFixture, StaticSequentialDataFixture, GlobalSequentialDataFixture\nfrom django_dynamic_fixture.fixture_algorithms.random_fixture import RandomDataFixture\n\n\nclass DDFImproperlyConfigured(Exception):\n    \"DDF is improperly configured. Some global settings has bad value in django settings.\"\n\n\ndef get_ddf_config(name, default, cast=None, options=None, msg=''):\n    try:\n        value = os.getenv(name) # Priority for Env variables\n        if not value:\n            value = getattr(settings, name) if hasattr(settings, name) else default\n        value = cast(value) if cast else value\n        if options and value not in options:\n            # to educate users to use the property correctly.\n            raise DDFImproperlyConfigured()\n        return value\n    except Exception as e:\n        raise DDFImproperlyConfigured(f'{name}=\"{value}\": {msg} ({e})')\n\n\ndef get_boolean_config(config_name, default=False):\n    return get_ddf_config(config_name, default, options=[True, False], msg='it must be True or False')\n\n\ndef get_data_fixture(default='sequential'):\n    # It must be 'sequential', 'static_sequential', 'global_sequential', 'random' or 'path.to.CustomDataFixtureClass'\n    try:\n        INTERNAL_DATA_FIXTURES = {'sequential': SequentialDataFixture(),\n                                  'static_sequential': StaticSequentialDataFixture(),\n                                  'global_sequential': GlobalSequentialDataFixture(),\n                                  'random': RandomDataFixture()}\n        if hasattr(settings, 'DDF_DEFAULT_DATA_FIXTURE'):\n            if settings.DDF_DEFAULT_DATA_FIXTURE in INTERNAL_DATA_FIXTURES.keys():\n                return INTERNAL_DATA_FIXTURES[settings.DDF_DEFAULT_DATA_FIXTURE]\n            else:\n                # path.to.CustomDataFixtureClass\n                mod_name, obj_name = get_mod_func(settings.DDF_DEFAULT_DATA_FIXTURE)\n                module = import_module(mod_name)\n                custom_data_fixture = getattr(module, obj_name)\n                return custom_data_fixture()\n        else:\n            return INTERNAL_DATA_FIXTURES[default]\n    except:\n        raise DDFImproperlyConfigured(\n            f\"DDF_DEFAULT_DATA_FIXTURE ({settings.DDF_DEFAULT_DATA_FIXTURE}) must be \"\n            \"'sequential', 'static_sequential', 'global_sequential', 'random' or 'path.to.CustomDataFixtureClass'.\"\n        )\n\n\nDDF_DEFAULT_DATA_FIXTURE = get_data_fixture(default='sequential')\nDDF_IGNORE_FIELDS = get_ddf_config('DDF_IGNORE_FIELDS', default=[], cast=list, msg='it must be a list of strings')\nDDF_FK_MIN_DEPTH = get_ddf_config('DDF_FK_MIN_DEPTH', default=0, cast=int, msg='it must be a integer number')\nif hasattr(settings, 'DDF_NUMBER_OF_LAPS'):\n    warnings.warn(\n        \"The old DDF_NUMBER_OF_LAPS settings was replaced by the new DDF_FK_MIN_DEPTH.\",\n        DeprecationWarning\n    )\nDDF_FIELD_FIXTURES = get_ddf_config('DDF_FIELD_FIXTURES', default={}, cast=dict, msg='it must be a dict')\nDDF_DEFAULT_DATA_FIXTURE.plugins = DDF_FIELD_FIXTURES\nDDF_FILL_NULLABLE_FIELDS = get_boolean_config('DDF_FILL_NULLABLE_FIELDS', default=False)\nDDF_VALIDATE_MODELS = get_boolean_config('DDF_VALIDATE_MODELS', default=False)\nDDF_DEBUG_MODE = get_boolean_config('DDF_DEBUG_MODE', default=False)\n"
  },
  {
    "path": "django_dynamic_fixture/models.py",
    "content": "from django.conf import settings\n\nimport_models = getattr(settings, 'IMPORT_DDF_MODELS', False)\n\nif import_models:\n    from django_dynamic_fixture.models_test import *\n"
  },
  {
    "path": "django_dynamic_fixture/models_sample_app.py",
    "content": "from django.db import models\n\n\nclass Publisher(models.Model):\n    name = models.CharField(max_length=100, unique=True)\n\nclass Author(models.Model):\n    name = models.CharField(max_length=100)\n    description = models.TextField(null=True)\n\nclass Category(models.Model):\n    name = models.CharField(max_length=100, unique=True)\n    parent = models.ForeignKey('self', on_delete=models.DO_NOTHING, null=True, blank=True)\n\nclass Book(models.Model):\n    isb = models.CharField(max_length=100, unique=True)\n    name = models.CharField(max_length=100)\n    main_author = models.ForeignKey(Author, related_name='books', on_delete=models.DO_NOTHING)\n    authors = models.ManyToManyField('Author', related_name='m2m')\n    categories = models.ManyToManyField('Category', related_name='m2m')\n    from .fields import JSONField\n    metadata = JSONField(null=True)\n\nclass BookPublisher(models.Model):\n    book_edition = models.ForeignKey('BookEdition', on_delete=models.DO_NOTHING)\n    publisher = models.ForeignKey('Publisher', on_delete=models.DO_NOTHING)\n    comments = models.TextField(max_length=100)\n\nclass BookEdition(models.Model):\n    book = models.ForeignKey(Book, related_name='editions', on_delete=models.DO_NOTHING)\n    publishers = models.ManyToManyField('Publisher', related_name='edition_publishers', through=BookPublisher)\n    year = models.IntegerField()\n"
  },
  {
    "path": "django_dynamic_fixture/models_test.py",
    "content": "#!/usr/bin/env python\n\n# https://docs.djangoproject.com/en/3.0/ref/models/fields\nimport django\nfrom django.conf import settings\nfrom django.db import models\nfrom django.core.exceptions import ValidationError\nfrom django.core.validators import RegexValidator\n\nfrom django_dynamic_fixture.models_sample_app import *\nfrom django_dynamic_fixture.models_third_party import *\n\n\nclass EmptyModel(models.Model):\n    class Meta:\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelWithNumbers(models.Model):\n    #id is a models.AutoField()\n    integer = models.IntegerField(unique=True)\n    smallinteger = models.SmallIntegerField(unique=True)\n    positiveinteger = models.PositiveIntegerField(unique=True)\n    positivesmallinteger = models.PositiveSmallIntegerField(unique=True)\n    biginteger = models.BigIntegerField(unique=True)\n    float = models.FloatField(unique=True)\n    decimal = models.DecimalField(max_digits=2, decimal_places=1, unique=False)\n\n    class Meta:\n        verbose_name = 'Numbers'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelWithStrings(models.Model):\n    char = models.CharField(max_length=1, unique=True)\n    string = models.CharField(max_length=50, unique=True)\n    text = models.TextField(unique=True)\n    slug = models.SlugField(unique=True)\n    commaseparated = models.CommaSeparatedIntegerField(max_length=100, unique=True)\n\n    class Meta:\n        verbose_name = 'Strings'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelWithBooleans(models.Model):\n    # https://docs.djangoproject.com/en/1.6/ref/models/fields/#booleanfield\n    # Django 1.6 changed the default value of BooleanField from False to None\n    boolean = models.BooleanField(default=False)\n    nullboolean = models.NullBooleanField()\n\n    class Meta:\n        verbose_name = 'Booleans'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelWithDateTimes(models.Model):\n    date = models.DateField(unique=True)\n    datetime = models.DateTimeField(unique=True)\n    time = models.TimeField(unique=True)\n\n    class Meta:\n        verbose_name = 'DateTimes'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelWithBinary(models.Model):\n    binary = models.BinaryField()\n    class Meta:\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelWithFieldsWithCustomValidation(models.Model):\n    email = models.EmailField(unique=True)\n    url = models.URLField(unique=True)\n    ip = models.IPAddressField(unique=False)\n    ipv6 = models.GenericIPAddressField(unique=False)\n\n    class Meta:\n        verbose_name = 'Custom validation'\n        app_label = 'django_dynamic_fixture'\n\nclass ModelWithFileFields(models.Model):\n    filepath = models.FilePathField(unique=True, blank=True)\n    file = models.FileField(upload_to='.')\n\n    try:\n        import pil\n        # just test it if the PIL package is installed\n        image = models.ImageField(upload_to='.')\n    except ImportError:\n        pass\n\n    class Meta:\n        verbose_name = 'File fields'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelWithDefaultValues(models.Model):\n    integer_with_default = models.IntegerField(default=3)\n    string_with_choices = models.CharField(max_length=5, choices=(('a', 'A'), ('b', 'B')))\n    string_with_choices_and_default = models.CharField(max_length=5, default='b', choices=(('a', 'A'), ('b', 'B')))\n    string_with_optgroup_choices = models.CharField(max_length=5, choices=(('group1', (('a', 'A'), ('b', 'B'))), ('group2', (('c', 'C'), ('d', 'D')))))\n    foreign_key_with_default = models.ForeignKey(EmptyModel, null=True, default=None, on_delete=models.DO_NOTHING)\n\n    class Meta:\n        verbose_name = 'Default values'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelForNullable(models.Model):\n    nullable = models.IntegerField(null=True)\n    not_nullable = models.IntegerField(null=False)\n\n    class Meta:\n        verbose_name = 'Nullable'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelForIgnoreList2(models.Model):\n    nullable = models.IntegerField(null=True)\n    non_nullable = models.IntegerField()\n\n    class Meta:\n        verbose_name = 'Ignore list 2'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelForIgnoreList(models.Model):\n    required = models.IntegerField(null=False)\n    required_with_default = models.IntegerField(null=False, default=1)\n    not_required = models.IntegerField(null=True)\n    not_required_with_default = models.IntegerField(default=1)\n    self_reference = models.ForeignKey('ModelForIgnoreList', on_delete=models.DO_NOTHING, null=True)\n    different_reference = models.ForeignKey(ModelForIgnoreList2, on_delete=models.DO_NOTHING)\n\n    class Meta:\n        verbose_name = 'Ignore list'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelRelated(models.Model):\n    selfforeignkey = models.ForeignKey('self', on_delete=models.DO_NOTHING, null=True, blank=True)\n    integer = models.IntegerField(null=True)\n    integer_b = models.IntegerField(null=True)\n\n    class Meta:\n        verbose_name = 'Related'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelRelatedThrough(models.Model):\n    related = models.ForeignKey('ModelRelated', on_delete=models.DO_NOTHING)\n    relationship = models.ForeignKey('ModelWithRelationships', on_delete=models.DO_NOTHING)\n\n    class Meta:\n        app_label = 'django_dynamic_fixture'\n\ndef default_fk_value():\n    try:\n        return ModelRelated.objects.get(id=1)\n    except ModelRelated.DoesNotExist:\n        ModelRelated.objects.create()\n        return ModelRelated.objects.all()[0]\n\n\ndef default_fk_id():\n    return default_fk_value().pk\n\n\nclass ModelWithRelationships(models.Model):\n    # relationship\n    selfforeignkey = models.ForeignKey('self', on_delete=models.DO_NOTHING, null=True, blank=True)\n    foreignkey = models.ForeignKey('ModelRelated', related_name='fk', on_delete=models.DO_NOTHING)\n    onetoone = models.OneToOneField('ModelRelated', related_name='o2o', on_delete=models.DO_NOTHING)\n    manytomany = models.ManyToManyField('ModelRelated', related_name='m2m')\n    manytomany_through = models.ManyToManyField('ModelRelated', related_name='m2m_through', through=ModelRelatedThrough)\n\n    foreignkey_with_default = models.ForeignKey('ModelRelated', related_name='fk2', default=default_fk_value, on_delete=models.DO_NOTHING)\n    foreignkey_with_id_default = models.ForeignKey('ModelRelated', related_name='fk3', default=default_fk_id, on_delete=models.DO_NOTHING)\n\n    integer = models.IntegerField(null=True)\n    integer_b = models.IntegerField(null=True)\n    # generic field\n    # TODO\n\n    class Meta:\n        verbose_name = 'Relationships'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelWithCyclicDependency(models.Model):\n    model_b = models.ForeignKey('ModelWithCyclicDependency2', on_delete=models.DO_NOTHING, null=True)\n\n    class Meta:\n        verbose_name = 'Cyclic dependency'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelWithCyclicDependency2(models.Model):\n    model_a = models.ForeignKey(ModelWithCyclicDependency, on_delete=models.DO_NOTHING, null=True)\n\n    class Meta:\n        verbose_name = 'Cyclic dependency 2'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelAbstract(models.Model):\n    integer = models.IntegerField(unique=True)\n    class Meta:\n        abstract = True\n        verbose_name = 'Abstract'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelParent(ModelAbstract):\n    class Meta:\n        verbose_name = 'Parent'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelChild(ModelParent):\n    class Meta:\n        verbose_name = 'Child'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelChildWithCustomParentLink(ModelParent):\n    my_custom_ref = models.OneToOneField(ModelParent, parent_link=True, related_name='my_custom_ref_x', on_delete=models.DO_NOTHING)\n\n    class Meta:\n        verbose_name = 'Custom child'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelWithRefToParent(models.Model):\n    parent = models.ForeignKey(ModelParent, on_delete=models.DO_NOTHING)\n\n    class Meta:\n        verbose_name = 'Child with parent'\n        app_label = 'django_dynamic_fixture'\n\n\nclass CustomDjangoField(models.IntegerField):\n    pass\n\n\nclass CustomDjangoField2(models.IntegerField):\n    pass\n\n\nclass CustomDjangoFieldMixin:\n    pass\n\n\nclass CustomDjangoFieldMultipleInheritance(CustomDjangoFieldMixin, models.IntegerField):\n    pass\n\n\nclass NewField(models.Field):\n    # Avoid OperationalError(\"table has no column named ...\") errors\n    def db_type(self, connection):\n        return 'char(25)'\n\n\nclass ModelWithCustomFields(models.Model):\n    x = CustomDjangoField(null=False)\n    y = NewField(null=True)\n\n    class Meta:\n        verbose_name = 'Custom fields'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelWithCustomFieldsMultipleInheritance(models.Model):\n    x = CustomDjangoFieldMultipleInheritance(null=False)\n    y = NewField(null=True)\n\n    class Meta:\n        verbose_name = 'Custom fields with multiple inheritance'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelWithUnsupportedField(models.Model):\n    z = NewField(null=False)\n\n    class Meta:\n        verbose_name = 'Unsupported field'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelWithValidators(models.Model):\n    field_validator = models.CharField(max_length=3, validators=[RegexValidator(regex=r'ok')])\n    clean_validator = models.CharField(max_length=3)\n\n    class Meta:\n        verbose_name = 'Validators'\n        app_label = 'django_dynamic_fixture'\n\n    def clean(self):\n        if self.clean_validator != 'ok':\n            raise ValidationError('ops')\n\n\nclass ModelWithAutoDateTimes(models.Model):\n    auto_now_add = models.DateField(auto_now_add=True)\n    auto_now = models.DateField(auto_now=True)\n    manytomany = models.ManyToManyField('ModelWithAutoDateTimes', related_name='m2m')\n\n    class Meta:\n        verbose_name = 'Auto DateTime'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelForCopy2(models.Model):\n    int_e = models.IntegerField()\n\n    class Meta:\n        verbose_name = 'Copy 2'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelForCopy(models.Model):\n    int_a = models.IntegerField()\n    int_b = models.IntegerField(null=None)\n    int_c = models.IntegerField()\n    int_d = models.IntegerField()\n    e = models.ForeignKey(ModelForCopy2, on_delete=models.DO_NOTHING)\n\n    class Meta:\n        verbose_name = 'Copy'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelForLibrary2(models.Model):\n    integer = models.IntegerField(null=True)\n    integer_unique = models.IntegerField(unique=True)\n\n    class Meta:\n        verbose_name = 'Library 2'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelForLibrary(models.Model):\n    integer = models.IntegerField(null=True)\n    integer_unique = models.IntegerField(unique=True)\n    selfforeignkey = models.ForeignKey('self', on_delete=models.DO_NOTHING, null=True, blank=True)\n    foreignkey = models.ForeignKey('ModelForLibrary2', related_name='fk', on_delete=models.DO_NOTHING)\n\n    class Meta:\n        verbose_name = 'Library'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ProxyModelForLibrary(ModelForLibrary):\n    class Meta:\n        proxy = True\n        verbose_name = 'Proxy Library'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelWithUniqueCharField(models.Model):\n    text_unique = models.CharField(max_length=20, unique=True)\n\n    class Meta:\n        verbose_name = 'Unique char field'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelWithClean(models.Model):\n    integer = models.IntegerField()\n\n    class Meta:\n        verbose_name = 'Clean'\n        app_label = 'django_dynamic_fixture'\n\n    def clean(self):\n        if self.integer != 9999: # just for testing\n            raise ValidationError('integer is not 9999')\n\n\nclass ModelForSignals(models.Model):\n    class Meta:\n        verbose_name = 'Signals'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelForSignals2(models.Model):\n    class Meta:\n        verbose_name = 'Signals 2'\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelForFieldPlugins(models.Model):\n    # aaa = CustomDjangoField(null=False) # defined in settings.py\n    # bbb = models.IntegerField(null=False)\n    custom_field_custom_fixture = CustomDjangoField(null=False) # defined in settings.py\n    custom_field_custom_fixture2 = CustomDjangoField2(null=False) # defined in settings.py\n    class Meta:\n        app_label = 'django_dynamic_fixture'\n\nclass ModelWithCommonNames(models.Model):\n    instance = models.IntegerField(null=False)\n    field = models.IntegerField(null=False)\n    class Meta:\n        app_label = 'django_dynamic_fixture'\n\n\nclass ModelWithNamedPrimaryKey(models.Model):\n    named_pk = models.AutoField(primary_key=True)\n\nif (hasattr(settings, 'DDF_TEST_GEODJANGO') and settings.DDF_TEST_GEODJANGO):\n    from django.contrib.gis.db import models as geomodels\n    class ModelForGeoDjango(geomodels.Model):\n        geometry = geomodels.GeometryField()\n        point = geomodels.PointField()\n        line_string = geomodels.LineStringField()\n        polygon = geomodels.PolygonField()\n        multi_point = geomodels.MultiPointField()\n        multi_line_string = geomodels.MultiLineStringField()\n        multi_polygon = geomodels.MultiPolygonField()\n        geometry_collection = geomodels.GeometryCollectionField()\n        class Meta:\n            app_label = 'django_dynamic_fixture'\n\n\nclass ModelForUUID(models.Model):\n    uuid = models.UUIDField()\n    class Meta:\n        app_label = 'django_dynamic_fixture'\n\n"
  },
  {
    "path": "django_dynamic_fixture/models_third_party.py",
    "content": "from django.db import models\n\n\ntry:\n    from django.contrib.postgres.fields import JSONField\n    class ModelForPostgresFields(models.Model):\n        nullable_json_field = JSONField(null=True)\n        json_field = JSONField(null=False)\n        class Meta:\n            app_label = 'django_dynamic_fixture'\nexcept ImportError:\n    pass\n\ntry:\n    from jsonfield import JSONField\n    from jsonfield import JSONCharField\n    class ModelForPlugins1(models.Model):\n        json_field1 = JSONCharField(max_length=10)\n        json_field2 = JSONField()\n        class Meta:\n            app_label = 'django_dynamic_fixture'\nexcept ImportError:\n    print('Library `jsonfield` not installed. Skipping.')\n\n\ntry:\n    from json_field import JSONField as JSONField2\n    class ModelForPlugins2(models.Model):\n        json_field1 = JSONField2()\n        class Meta:\n            app_label = 'django_dynamic_fixture'\nexcept ImportError:\n    print('Library `django-json-field` not installed. Skipping.')\n\n\ntry:\n    from polymorphic.models import PolymorphicModel\n    class ModelPolymorphic(PolymorphicModel):\n        class Meta:\n            verbose_name = 'Polymorphic Model'\n\n\n    class ModelPolymorphic2(ModelPolymorphic):\n        class Meta:\n            verbose_name = 'Polymorphic Model 2'\n\n\n    class ModelPolymorphic3(ModelPolymorphic):\n        class CannotSave(Exception):\n            pass\n\n        def save(self):\n            raise self.CannotSave\nexcept ImportError:\n    print('Library `django_polymorphic` not installed. Skipping.')\n"
  },
  {
    "path": "django_dynamic_fixture/script_ddf_checkings.py",
    "content": "import csv\n\nfrom django.db import transaction\n\nfrom django_dynamic_fixture.django_helper import get_apps, get_models_of_an_app\n\n\ndef color(color, string):\n    return '\\033[1;{}m{}\\033[0m'.format(color, string)\n\ndef white(string):\n    return color('37', string)\n\ndef red(string):\n    return color('91', string)\n\ndef green(string):\n    return color('92', string)\n\ndef yellow(string):\n    return color('93', string)\n\n\ndef ddf_check_models(application_labels=[], exclude_application_labels=[], print_csv=False, csv_filename=None):\n    from django_dynamic_fixture import get\n\n    succeeded = {}\n    errors = {}\n    for app_label in get_apps(application_labels, exclude_application_labels):\n        models = get_models_of_an_app(app_label)\n        for model_class in models:\n            ref = '{}.{}'.format(app_label, model_class.__name__)\n            try:\n                with transaction.atomic():\n                    get(model_class)\n                succeeded[ref] = None\n            except Exception as e:\n                errors[ref] = '[{}] {}'.format(type(e), str(e))\n\n    console_report(succeeded, errors)\n    if print_csv or csv_filename:\n        content = csv_report(succeeded, errors)\n        if print_csv:\n            print(yellow('\\nCSV Report.\\n'))\n            print(content)\n        if csv_filename:\n            print(yellow('\\nCSV Report file created: {}.\\n'.format(csv_filename)))\n            save_csv(content, filename=csv_filename)\n    return succeeded, errors\n\n\ndef console_report(succeeded, errors):\n    print(green('\\nModels that DDF can create using the default settings.\\n'))\n    for i, (ref, _) in enumerate(succeeded.items(), start=1):\n        i = str(i).zfill(3)\n        print(white('{}. {}: '.format(i, ref)) + green('succeeded'))\n\n    print(red('\\nModels that requires some customisation.\\n'))\n    for i, (ref, error) in enumerate(errors.items(), start=1):\n        i = str(i).zfill(3)\n        print(white('{}. {}: '.format(i, ref)) + red(error))\n\n\ndef csv_report(succeeded, errors):\n    SEP = '\\t'\n    LN = '\\n'\n    lines = []\n    lines.append(SEP.join(['#', 'Model', 'Succeeded']))\n    for i, (ref, _) in enumerate(succeeded.items(), start=1):\n        lines.append(SEP.join([str(i), ref, 'succeeded']))\n\n    lines.append(SEP.join(['#', 'Model', 'Error']))\n    for i, (ref, error) in enumerate(errors.items(), start=1):\n        lines.append(SEP.join([str(i), ref, error]))\n    return LN.join(lines)\n\n\ndef save_csv(content, filename):\n    with open(filename, 'w') as f:\n        f.write(content)\n"
  },
  {
    "path": "django_dynamic_fixture/tests/__init__.py",
    "content": "\n"
  },
  {
    "path": "django_dynamic_fixture/tests/conftest.py",
    "content": "# PyTest file for global set up.\n\n# Django initialisation\nimport django\ndjango.setup()\n\n# Give DB access to PyTests\nimport pytest\npytest.mark.django_db\n\n# MonkeyPatch Django-Test teardown\nfrom django.test import utils\noriginal_teardown_test_environment = utils.teardown_test_environment\ndef fixed_teardown_test_environment():\n    try:\n        original_teardown_test_environment()\n    except TypeError:\n        # Ignore some Django or PyTest-Django bug\n        pass\nutils.teardown_test_environment = fixed_teardown_test_environment\n\nprint(':: PyTest conftest.py loaded.')\n"
  },
  {
    "path": "django_dynamic_fixture/tests/test_ddf.py",
    "content": "from datetime import datetime, date\nfrom decimal import Decimal\nimport uuid\n\nfrom django.test import TestCase\nimport pytest\n\nfrom django_dynamic_fixture.models_test import *\nfrom django_dynamic_fixture.ddf import *\nfrom django_dynamic_fixture.fixture_algorithms.sequential_fixture import SequentialDataFixture\n\n\ndata_fixture = SequentialDataFixture()\n\n\nclass DDFTestCase(TestCase):\n    def setUp(self):\n        self.ddf = DynamicFixture(data_fixture)\n\n\nclass NewCreateAModelInstanceTest(DDFTestCase):\n    def test_new_create_a_non_saved_instance_of_the_model(self):\n        instance = self.ddf.new(EmptyModel)\n        assert isinstance(instance, EmptyModel)\n        assert instance.id is None\n\n\nclass GetDealWithPrimaryKeyTest(DDFTestCase):\n    def test_get_use_database_id_by_default(self):\n        instance = self.ddf.get(EmptyModel)\n        assert instance.id is not None\n        assert instance.pk is not None\n\n    def test_get_use_given_id(self):\n        instance = self.ddf.new(EmptyModel, id=99998)\n        assert instance.id == 99998\n        assert instance.pk == 99998\n\n    def test_get_use_given_named_id(self):\n        instance = self.ddf.get(ModelWithNamedPrimaryKey, named_pk=99998)\n        assert instance.named_pk == 99998\n        assert instance.pk == 99998\n\n\nclass NewFullFillAttributesWithAutoDataTest(DDFTestCase):\n    def test_new_fill_number_fields_with_numbers(self):\n        instance = self.ddf.new(ModelWithNumbers)\n        assert isinstance(instance.integer, int)\n        assert isinstance(instance.smallinteger, int)\n        assert isinstance(instance.positiveinteger, int)\n        assert isinstance(instance.positivesmallinteger, int)\n        assert isinstance(instance.biginteger, int)\n        assert isinstance(instance.float, float)\n\n    def test_new_fill_string_fields_with_text_type_strings(self):\n        instance = self.ddf.new(ModelWithStrings)\n        assert isinstance(instance.string, str)\n        assert isinstance(instance.text, str)\n        assert isinstance(instance.slug, str)\n        assert isinstance(instance.commaseparated, str)\n\n    def test_new_fill_boolean_fields_with_False_and_None(self):\n        instance = self.ddf.new(ModelWithBooleans)\n        assert instance.boolean is False\n        assert instance.nullboolean is None\n\n    def test_new_fill_time_related_fields_with_current_values(self):\n        instance = self.ddf.new(ModelWithDateTimes)\n        assert date.today() >= instance.date\n        assert datetime.now().time() >= instance.time\n        assert datetime.now() >= instance.datetime\n\n    def test_new_fill_formatted_strings_fields_with_basic_values(self):\n        instance = self.ddf.new(ModelWithFieldsWithCustomValidation)\n        assert isinstance(instance.email, str)\n        assert isinstance(instance.url, str)\n        assert isinstance(instance.ip, str)\n        assert isinstance(instance.ipv6, str)\n\n    def test_new_fill_file_fields_with_basic_strings(self):\n        instance = self.ddf.new(ModelWithFileFields)\n        assert isinstance(instance.filepath, str)\n        assert isinstance(instance.file.path, str)\n        try:\n            import pil\n            # just test it if the PIL package is installed\n            assert isinstance(instance.image, str)\n        except ImportError:\n            pass\n\n    def test_new_fill_binary_fields_with_basic_data(self):\n        value = b'\\x00\\x46\\xFE'\n        instance = self.ddf.new(ModelWithBinary, binary=value)\n        assert bytes(instance.binary) == bytes(value)\n\n        instance = self.ddf.get(ModelWithBinary)\n        assert isinstance(instance.binary, bytes), type(instance.binary)\n\n\nclass NewFullFillAttributesWithDefaultDataTest(DDFTestCase):\n    def test_fill_field_with_default_data(self):\n        instance = self.ddf.new(ModelWithDefaultValues)\n        assert instance.integer_with_default == 3\n\n    def test_fill_field_with_possible_choices(self):\n        instance = self.ddf.new(ModelWithDefaultValues)\n        assert instance.string_with_choices == 'a'\n\n    def test_fill_field_with_default_value_even_if_field_is_foreign_key(self):\n        instance = self.ddf.new(ModelWithDefaultValues)\n        assert instance.foreign_key_with_default is None\n\n    def test_fill_field_with_default_data_and_choices_must_consider_default_data_instead_choices(self):\n        instance = self.ddf.new(ModelWithDefaultValues)\n        assert instance.string_with_choices_and_default == 'b'\n\n    def test_fill_field_with_possible_optgroup_choices(self):\n        instance = self.ddf.new(ModelWithDefaultValues)\n        assert instance.string_with_optgroup_choices == 'a'\n\n\nclass NewFullFillAttributesWithCustomDataTest(DDFTestCase):\n    def test_fields_are_filled_with_custom_attributes(self):\n        assert self.ddf.new(ModelWithNumbers, integer=9).integer == 9\n        assert self.ddf.new(ModelWithStrings, string='7').string == '7'\n        assert self.ddf.new(ModelWithBooleans, boolean=True).boolean\n\n    def test_decimal_can_be_filled_by_an_string(self):\n        self.ddf.get(ModelWithNumbers, decimal='9.5')\n        assert ModelWithNumbers.objects.latest('id').decimal == Decimal('9.5')\n\n    def test_fields_can_be_filled_by_functions(self):\n        instance = self.ddf.new(ModelWithStrings, string=lambda field: field.name)\n        assert instance.string == 'string'\n\n    def test_invalid_configuration_raise_an_error(self):\n        with pytest.raises(InvalidConfigurationError):\n            self.ddf.new(ModelWithNumbers, integer=lambda x: ''.invalidmethod())\n\n    def test_bad_data_raise_an_error(self):\n        self.ddf.get(ModelWithNumbers, integer=50000)\n        with pytest.raises(BadDataError):\n            self.ddf.get(ModelWithNumbers, integer=50000)\n\n\nclass NewIgnoringNullableFieldsTest(DDFTestCase):\n    def test_new_do_not_fill_nullable_fields_if_we_do_not_want_to(self):\n        self.ddf = DynamicFixture(data_fixture, fill_nullable_fields=False)\n        instance = self.ddf.new(ModelForNullable)\n        assert instance.not_nullable is not None\n        assert instance.nullable is None\n\n\nclass NewIgnoreFieldsInIgnoreListTest(DDFTestCase):\n    def test_new_do_not_fill_ignored_fields(self):\n        self.ddf = DynamicFixture(data_fixture, ignore_fields=['not_required', 'not_required_with_default'])\n        instance = self.ddf.new(ModelForIgnoreList)\n        assert instance.not_required is None\n        assert instance.not_required_with_default is not None\n        # not ignored fields\n        assert instance.required is not None\n        assert instance.required_with_default is not None\n\n    def test_get_raise_an_error_if_a_required_field_is_in_ignore_list(self):\n        self.ddf = DynamicFixture(data_fixture, ignore_fields=['required', 'required_with_default'])\n        with pytest.raises(BadDataError):\n            self.ddf.get(ModelForIgnoreList)\n\n    def test_ignore_fields_are_propagated_to_self_references(self):\n        self.ddf = DynamicFixture(data_fixture, ignore_fields=['not_required'], fk_min_depth=1, not_required=10)\n        instance = self.ddf.new(ModelForIgnoreList)\n        assert instance.not_required == 10\n        assert instance.self_reference is not None\n        assert instance.self_reference.not_required is None\n\n    def test_ignore_fields_are_not_propagated_to_different_references(self):\n        self.ddf = DynamicFixture(data_fixture, ignore_fields=['non_nullable'], different_reference=DynamicFixture(data_fixture))\n        instance = self.ddf.new(ModelForIgnoreList)\n        assert instance.different_reference is not None\n        assert instance.different_reference.non_nullable is not None\n\n    def test_ignore_fields_are_not_ignored_if_explicitely_given(self):\n        self.ddf = DynamicFixture(data_fixture, not_required=3, ignore_fields=['not_required', 'nullable'])\n        instance = self.ddf.new(ModelForIgnoreList)\n        assert instance.not_required == 3\n\n\nclass NewAlsoCreatesRelatedObjectsTest(DDFTestCase):\n    def test_new_fill_foreignkey_fields(self):\n        instance = self.ddf.new(ModelWithRelationships)\n        assert isinstance(instance.foreignkey, ModelRelated)\n\n    def test_new_fill_onetoone_fields(self):\n        instance = self.ddf.new(ModelWithRelationships)\n        assert isinstance(instance.onetoone, ModelRelated)\n\n    def test_new_deal_with_default_values(self):\n        instance = self.ddf.new(ModelWithRelationships)\n        assert isinstance(instance.foreignkey_with_default, ModelRelated), str(type(instance.foreignkey_with_default))\n\n    def test_new_deal_with_id_default_values(self):\n        instance = self.ddf.new(ModelWithRelationships)\n        assert isinstance(instance.foreignkey_with_id_default, ModelRelated), str(type(instance.foreignkey_with_default))\n\n#        TODO\n#    def test_new_fill_genericrelations_fields(self):\n#        instance = self.ddf.new(ModelWithRelationships)\n#        assert isinstance(instance.foreignkey, ModelRelated)\n\n\nclass NewCanCreatesCustomizedRelatedObjectsTest(DDFTestCase):\n    def test_customizing_nullable_fields_for_related_objects(self):\n        instance = self.ddf.new(ModelWithRelationships, selfforeignkey=DynamicFixture(data_fixture, fill_nullable_fields=True))\n        assert instance.integer is None\n        assert isinstance(instance.selfforeignkey.integer, int)\n\n\nclass NewDealWithSelfReferencesTest(DDFTestCase):\n    def test_new_create_by_default_no_self_fks(self):\n        instance = self.ddf.new(ModelWithRelationships, fill_nullable_fields=False)\n        assert instance.selfforeignkey is None # no cycle\n        instance = self.ddf.new(ModelWithRelationships, fill_nullable_fields=True)\n        assert instance.selfforeignkey is None # no cycle\n\n    def test_new_create_only_1_lap_in_cycle(self):\n        self.ddf = DynamicFixture(data_fixture, fk_min_depth=1)\n        instance = self.ddf.new(ModelWithRelationships)\n        assert instance.selfforeignkey is not None # 1 cycle\n        assert instance.selfforeignkey.selfforeignkey is None # 2 cycles\n\n    def test_new_create_with_min_depth_2(self):\n        self.ddf = DynamicFixture(data_fixture, fk_min_depth=2)\n        instance = self.ddf.new(ModelWithRelationships)\n        assert instance.selfforeignkey is not None # 1 cycle\n        assert instance.selfforeignkey.selfforeignkey is not None # 2 cycles\n        assert instance.selfforeignkey.selfforeignkey.selfforeignkey is None # 3 cycles\n\n    def test_number_of_fk_cycles_does_not_break_default_non_null_fk(self):\n        self.ddf = DynamicFixture(data_fixture, fk_min_depth=0)\n        instance = self.ddf.new(ModelWithRefToParent)\n        assert instance.parent is not None\n\n\nclass GetFullFilledModelInstanceAndPersistTest(DDFTestCase):\n    def test_get_create_and_save_a_full_filled_instance_of_the_model(self):\n        instance = self.ddf.get(ModelWithRelationships)\n        assert isinstance(instance, ModelWithRelationships)\n        assert instance.id is not None\n        # checking unique problems\n        another_instance = self.ddf.get(ModelWithRelationships)\n        assert isinstance(another_instance, ModelWithRelationships)\n        assert another_instance.id is not None\n\n    def test_get_create_and_save_related_fields(self):\n        instance = self.ddf.get(ModelWithRelationships)\n        assert instance.selfforeignkey is None\n        assert instance.foreignkey is not None\n        assert instance.onetoone is not None\n        self.ddf = DynamicFixture(data_fixture, fk_min_depth=1)\n        instance = self.ddf.get(ModelWithRelationships)\n        assert instance.selfforeignkey is not None\n\n\nclass ManyToManyRelationshipTest(DDFTestCase):\n    def test_new_ignore_many_to_many_configuratios(self):\n        instance = self.ddf.new(ModelWithRelationships, manytomany=3)\n        instance.save()\n        assert instance.manytomany.all().count() == 0\n\n    def test_get_ignore_many_to_many_configuratios(self):\n        instance = self.ddf.get(ModelWithRelationships, manytomany=3)\n        assert instance.manytomany.all().count() == 3\n\n    def test_many_to_many_configuratios_accept_list_of_dynamic_filters(self):\n        instance = self.ddf.get(ModelWithRelationships, manytomany=[DynamicFixture(data_fixture, integer=1000), DynamicFixture(data_fixture, integer=1001)])\n        assert instance.manytomany.all().count() == 2\n        assert instance.manytomany.all()[0].integer == 1000\n        assert instance.manytomany.all()[1].integer == 1001\n\n    def test_many_to_many_configuratios_accept_list_of_instances(self):\n        b1 = self.ddf.get(ModelRelated, integer=1000)\n        b2 = self.ddf.get(ModelRelated, integer=1001)\n        instance = self.ddf.get(ModelWithRelationships, manytomany=[b1, b2])\n        assert instance.manytomany.all().count() == 2\n        objs = instance.manytomany.all().order_by('integer')\n        assert objs[0].integer == 1000\n        assert objs[1].integer == 1001\n\n    def test_invalid_many_to_many_configuration(self):\n        with pytest.raises(InvalidManyToManyConfigurationError):\n            self.ddf.get(ModelWithRelationships, manytomany='a')\n\n    def test_many_to_many_through(self):\n        b1 = self.ddf.get(ModelRelated, integer=1000)\n        b2 = self.ddf.get(ModelRelated, integer=1001)\n        instance = self.ddf.get(ModelWithRelationships, manytomany_through=[b1, b2])\n        objs = instance.manytomany_through.all().order_by('integer')\n        assert objs.count() == 2\n        assert objs[0].integer == 1000\n        assert objs[1].integer == 1001\n\n\nclass NewDealWithCyclicDependenciesTest(DDFTestCase):\n    def test_new_create_by_default_no_cycles(self):\n        a = self.ddf.new(ModelWithCyclicDependency)\n        assert a.model_b is None\n\n    def test_new_create_only_1_lap_in_fk_cycle(self):\n        self.ddf = DynamicFixture(data_fixture, fk_min_depth=1)\n        a = self.ddf.get(ModelWithCyclicDependency)\n        assert a.model_b.model_a is None\n\n    def test_new_create_with_min_depth_2(self):\n        self.ddf = DynamicFixture(data_fixture, fk_min_depth=2)\n        a = self.ddf.get(ModelWithCyclicDependency)\n        assert a.model_b.model_a.model_b is None\n\n\nclass NewDealWithInheritanceTest(DDFTestCase):\n    def test_get_must_raise_an_error_if_model_is_abstract(self):\n        with pytest.raises(InvalidModelError):\n            self.ddf.get(ModelAbstract)\n\n    def test_get_must_fill_parent_fields_too(self):\n        instance = self.ddf.get(ModelParent)\n        assert isinstance(instance.integer, int)\n        assert ModelParent.objects.count() == 1\n\n    def test_get_must_fill_grandparent_fields_too(self):\n        instance = self.ddf.get(ModelChild)\n        assert isinstance(instance.integer, int)\n        assert ModelParent.objects.count() == 1\n        assert ModelChild.objects.count() == 1\n\n    def test_get_must_ignore_parent_link_attributes_but_the_parent_object_must_be_created(self):\n        instance = self.ddf.get(ModelChildWithCustomParentLink)\n        assert isinstance(instance.integer, int)\n        assert ModelParent.objects.count() == 1\n        assert ModelChildWithCustomParentLink.objects.count() == 1\n        assert instance.my_custom_ref.id is not None\n        assert instance.my_custom_ref.my_custom_ref_x.id is not None\n\n    # TODO: need to check these tests. Here we are trying to simulate a bug with parent_link attribute\n    def test_get_0(self):\n        instance = self.ddf.get(ModelWithRefToParent)\n        assert ModelWithRefToParent.objects.count() == 1\n        assert ModelParent.objects.count() == 1\n        assert isinstance(instance.parent, ModelParent)\n\n    def test_get_1(self):\n        instance = self.ddf.get(ModelWithRefToParent, parent=self.ddf.get(ModelChild))\n        assert ModelWithRefToParent.objects.count() == 1\n        assert ModelParent.objects.count() == 1\n        assert ModelChild.objects.count() == 1\n        assert isinstance(instance.parent, ModelChild)\n\n    def test_get_2(self):\n        instance = self.ddf.get(ModelWithRefToParent, parent=self.ddf.get(ModelChildWithCustomParentLink))\n        assert ModelWithRefToParent.objects.count() == 1\n        assert ModelParent.objects.count() == 1\n        assert ModelChildWithCustomParentLink.objects.count() == 1\n        assert isinstance(instance.parent, ModelChildWithCustomParentLink)\n\n\nclass ComplexFieldsTest(DDFTestCase):\n    def test_x(self):\n        instance = self.ddf.new(ModelForUUID)\n        assert isinstance(instance.uuid, uuid.UUID)\n\n\nclass ModelValidatorsTest(DDFTestCase):\n    def test_it_must_create_if_validation_is_disabled(self):\n        instance = self.ddf.get(ModelWithValidators, field_validator='nok', clean_validator='nok')\n        self.ddf.validate_models = False\n        assert instance.field_validator == 'nok'\n        assert instance.clean_validator == 'nok'\n\n    def test_it_must_create_if_there_is_no_validation_errors(self):\n        instance = self.ddf.get(ModelWithValidators, field_validator='ok', clean_validator='ok')\n        self.ddf.validate_models = True\n        assert instance.field_validator == 'ok'\n        assert instance.clean_validator == 'ok'\n\n    def test_it_must_raise_a_bad_data_error_if_data_is_not_valid(self):\n        self.ddf.validate_models = True\n        self.ddf.get(ModelWithValidators, field_validator='nok', clean_validator='ok')\n        with pytest.raises(BadDataError):\n            self.ddf.get(ModelWithValidators, field_validator='ok', clean_validator='nok')\n\n\nclass ConfigurationValidatorTest(DDFTestCase):\n    def test_it_must_raise_a_bad_data_error_if_data_is_not_valid(self):\n        with pytest.raises(InvalidConfigurationError):\n            self.ddf.get(EmptyModel, unexistent_field='x')\n\n\nclass DisableAutoGeneratedDateTimesTest(DDFTestCase):\n    def test_auto_generated_datetimes_must_be_respected_if_nothing_is_specified(self):\n        instance = self.ddf.get(ModelWithAutoDateTimes)\n        assert datetime.today().date() == instance.auto_now_add\n        assert datetime.today().date() == instance.auto_now\n\n    def test_it_must_ignore_auto_generated_datetime_if_a_custom_value_is_provided(self):\n        instance = self.ddf.get(ModelWithAutoDateTimes, auto_now_add=date(2000, 12, 31))\n        assert instance.auto_now_add == date(2000, 12, 31)\n\n        instance = self.ddf.get(ModelWithAutoDateTimes, auto_now=date(2000, 12, 31))\n        assert instance.auto_now == date(2000, 12, 31)\n\n    def test_checking_if_implementation_works_for_m2m_fields_too(self):\n        instance = self.ddf.get(ModelWithAutoDateTimes, manytomany=[DynamicFixture(data_fixture, auto_now_add=date(2000, 12, 31))])\n        assert instance.manytomany.all()[0].auto_now_add == date(2000, 12, 31)\n\n        instance = self.ddf.get(ModelWithAutoDateTimes, manytomany=[DynamicFixture(data_fixture, auto_now=date(2000, 12, 31))])\n        assert instance.manytomany.all()[0].auto_now == date(2000, 12, 31)\n\n\nclass ModelWithCustomValidationTest(DDFTestCase):\n    def test_ddf_can_not_create_instance_of_models_with_custom_validations(self):\n        self.ddf.validate_models = True\n        with pytest.raises(BadDataError):\n            self.ddf.get(ModelWithClean)\n        self.ddf.get(ModelWithClean, integer=9999) # this does not raise an exception\n\n\nclass ExceptionsLayoutMessagesTest(DDFTestCase):\n    def test_UnsupportedFieldError(self):\n        try:\n            self.ddf.new(ModelWithUnsupportedField)\n            self.fail()\n        except UnsupportedFieldError as e:\n            assert \"\"\"django_dynamic_fixture.models_test.ModelWithUnsupportedField.z\"\"\" in str(e)\n\n    def test_BadDataError(self):\n        self.ddf = DynamicFixture(data_fixture, ignore_fields=['required', 'required_with_default'])\n        try:\n            self.ddf.get(ModelForIgnoreList)\n            self.fail()\n        except BadDataError as e:\n            assert 'IntegrityError' in str(e), str(e)\n            assert 'NULL' in str(e).upper(), str(e)\n\n    def test_InvalidConfigurationError(self):\n        try:\n            self.ddf.new(ModelWithNumbers, integer=lambda x: ''.invalidmethod())\n            self.fail()\n        except InvalidConfigurationError as e:\n            assert 'django_dynamic_fixture.models_test.ModelWithNumbers.integer' in str(e)\n            assert 'AttributeError' in str(e)\n            assert 'invalidmethod' in str(e)\n\n    def test_InvalidManyToManyConfigurationError(self):\n        try:\n            self.ddf.get(ModelWithRelationships, manytomany='a')\n            self.fail()\n        except InvalidManyToManyConfigurationError as e:\n            assert \"\"\"('Field: manytomany', 'a')\"\"\" == str(e)\n\n    def test_InvalidModelError(self):\n        try:\n            self.ddf.get(ModelAbstract)\n            self.fail()\n        except InvalidModelError as e:\n            assert \"\"\"django_dynamic_fixture.models_test.ModelAbstract\"\"\" == str(e)\n\n    def test_InvalidModelError_for_common_object(self):\n        class MyClass: pass\n        try:\n            self.ddf.new(MyClass)\n            self.fail()\n        except InvalidModelError as e:\n            assert \"\"\"django_dynamic_fixture.tests.test_ddf.MyClass\"\"\" == str(e)\n\n\nclass SanityTest(DDFTestCase):\n    def test_create_lots_of_models_to_verify_data_unicity_errors(self):\n        for i in range(1000):\n            self.ddf.get(ModelWithNumbers)\n\n\nclass AvoidNameCollisionTest(DDFTestCase):\n    def test_avoid_common_name_instance(self):\n        self.ddf = DynamicFixture(data_fixture, fill_nullable_fields=False)\n        instance = self.ddf.new(ModelWithCommonNames)\n        assert instance.instance is not None\n\n        instance = self.ddf.new(ModelWithCommonNames, instance=3)\n        assert instance.instance == 3\n\n        instance = self.ddf.get(ModelWithCommonNames)\n        assert instance.instance is not None\n\n        instance = self.ddf.get(ModelWithCommonNames, instance=4)\n        assert instance.instance == 4\n\n    def test_avoid_common_name_field(self):\n        self.ddf = DynamicFixture(data_fixture, fill_nullable_fields=False)\n        instance = self.ddf.new(ModelWithCommonNames)\n        assert instance.field is not None\n\n        instance = self.ddf.new(ModelWithCommonNames, field=5)\n        assert instance.field == 5\n\n        instance = self.ddf.get(ModelWithCommonNames)\n        assert instance.field is not None\n\n        instance = self.ddf.get(ModelWithCommonNames, field=6)\n        assert instance.field == 6\n"
  },
  {
    "path": "django_dynamic_fixture/tests/test_ddf_checkings.py",
    "content": "\nfrom django.test import TestCase\n\nfrom django_dynamic_fixture.ddf import DDFLibrary\nfrom django_dynamic_fixture import ddf_check_models, teach\n\n\nclass DDFTestCase(TestCase):\n    def setUp(self):\n        DDFLibrary.get_instance().clear()\n\n\nclass TestCheckCompatibility(DDFTestCase):\n    def test_default(self):\n        succeeded, errors = ddf_check_models()\n\n        compatible_models = [\n            'django_dynamic_fixture.EmptyModel',\n            'django_dynamic_fixture.ModelWithNumbers',\n        ]\n        for model in compatible_models:\n            assert model in succeeded.keys(), model\n\n        incompatible_models = [\n            'django_dynamic_fixture.ModelWithUnsupportedField',\n        ]\n        for model in incompatible_models:\n            assert model in errors.keys(), model\n        # TODO: Consider the RelatedObjectDoesNotExist errors\n        # https://stackoverflow.com/questions/26270042/how-do-you-catch-this-exception\n\n    def test_teaching_ddf(self):\n        teach('django_dynamic_fixture.ModelWithUnsupportedField', z='z')\n        succeeded, errors = ddf_check_models()\n\n        compatible_models = [\n            'django_dynamic_fixture.ModelWithUnsupportedField',\n        ]\n        for model in compatible_models:\n            assert model in succeeded.keys(), model\n            assert model not in errors.keys(), model\n"
  },
  {
    "path": "django_dynamic_fixture/tests/test_ddf_copier.py",
    "content": "from django.test import TestCase\nimport pytest\n\nfrom django_dynamic_fixture.models_test import *\nfrom django_dynamic_fixture.ddf import *\nfrom django_dynamic_fixture.fixture_algorithms.sequential_fixture import SequentialDataFixture\n\n\ndata_fixture = SequentialDataFixture()\n\n\nclass DDFTestCase(TestCase):\n    def setUp(self):\n        self.ddf = DynamicFixture(data_fixture)\n\n\nclass CopyTest(DDFTestCase):\n    def test_it_should_copy_from_model_fields(self):\n        instance = self.ddf.get(ModelForCopy, int_a=Copier('int_b'), int_b=3)\n        assert instance.int_a == 3\n\n    def test_simple_scenario(self):\n        instance = self.ddf.get(ModelForCopy, int_b=Copier('int_a'))\n        assert instance.int_b == instance.int_a\n\n    def test_order_of_attributes_must_be_superfluous(self):\n        instance = self.ddf.get(ModelForCopy, int_a=Copier('int_b'))\n        assert instance.int_a == instance.int_b\n\n    def test_it_should_deal_with_multiple_copiers(self):\n        instance = self.ddf.get(ModelForCopy, int_a=Copier('int_b'), int_c=Copier('int_d'))\n        assert instance.int_a == instance.int_b\n        assert instance.int_c == instance.int_d\n\n    def test_multiple_copiers_can_depend_of_one_field(self):\n        instance = self.ddf.get(ModelForCopy, int_a=Copier('int_c'), int_b=Copier('int_c'))\n        assert instance.int_a == instance.int_c\n        assert instance.int_b == instance.int_c\n\n    def test_it_should_deal_with_dependent_copiers(self):\n        instance = self.ddf.get(ModelForCopy, int_a=Copier('int_b'), int_b=Copier('int_c'))\n        assert instance.int_a == instance.int_b\n        assert instance.int_b == instance.int_c\n\n    def test_it_should_deal_with_relationships(self):\n        instance = self.ddf.get(ModelForCopy, int_a=Copier('e.int_e'))\n        assert instance.int_a == instance.e.int_e\n\n        instance = self.ddf.get(ModelForCopy, int_a=Copier('e.int_e'), e=DynamicFixture(data_fixture, int_e=5))\n        assert instance.int_a == 5\n\n    def test_it_should_raise_a_bad_data_error_if_value_is_invalid(self):\n        with pytest.raises(BadDataError):\n            self.ddf.get(ModelForCopy, int_a=Copier('int_b'), int_b=None)\n\n    def test_it_should_raise_a_invalid_configuration_error_if_expression_is_bugged(self):\n        with pytest.raises(InvalidConfigurationError):\n            self.ddf.get(ModelForCopy, int_a=Copier('invalid_field'))\n        with pytest.raises(InvalidConfigurationError):\n            self.ddf.get(ModelForCopy, int_a=Copier('int_b.invalid_field'))\n\n    def test_it_should_raise_a_invalid_configuration_error_if_copier_has_cyclic_dependency(self):\n        with pytest.raises(InvalidConfigurationError):\n            self.ddf.get(ModelForCopy, int_a=Copier('int_b'), int_b=Copier('int_a'))\n\n    def test_it_must_copy_generated_data_mask_too(self):\n        import re\n        instance = self.ddf.get(ModelWithStrings, string=Mask('- _ #'), text=Copier('string'))\n        assert re.match(r'[A-Z]{1} [a-z]{1} [0-9]{1}', instance.string)\n        assert re.match(r'[A-Z]{1} [a-z]{1} [0-9]{1}', instance.text)\n"
  },
  {
    "path": "django_dynamic_fixture/tests/test_ddf_custom_fields.py",
    "content": "from django.conf import settings\n\nfrom django.test import TestCase\nimport pytest\n\nfrom django_dynamic_fixture.models_test import *\nfrom django_dynamic_fixture.ddf import *\nfrom django_dynamic_fixture.decorators import only_for_database, POSTGRES\nfrom django_dynamic_fixture.fixture_algorithms.sequential_fixture import SequentialDataFixture\n\ndata_fixture = SequentialDataFixture()\n\n\nclass DDFTestCase(TestCase):\n    def setUp(self):\n        self.ddf = DynamicFixture(data_fixture)\n\n\nclass CustomFieldsTest(DDFTestCase):\n    def test_new_field_that_extends_django_field_must_be_supported(self):\n        instance = self.ddf.new(ModelWithCustomFields)\n        assert instance.x == 1\n\n    def test_new_field_that_extends_django_field_must_be_supported_with_custom_value(self):\n        instance = self.ddf.new(ModelWithCustomFields, x=6)\n        assert instance.x == 6\n\n    def test_unsupported_field_is_filled_with_null_if_it_is_possible(self):\n        instance = self.ddf.new(ModelWithCustomFields)\n        assert instance.y is None\n\n    def test_unsupported_field_raise_an_error_if_it_does_not_accept_null_value(self):\n        DDFLibrary.get_instance().clear()\n        with pytest.raises(UnsupportedFieldError):\n            self.ddf.new(ModelWithUnsupportedField)\n\n    def test_new_field_that_double_inherits_django_field_must_be_supported(self):\n        instance = self.ddf.new(ModelWithCustomFieldsMultipleInheritance)\n        assert instance.x == 1\n\n    def test_new_field_that_double_inherits_django_field_must_be_supported_with_custom_value(self):\n        instance = self.ddf.new(ModelWithCustomFieldsMultipleInheritance, x=5)\n        assert instance.x == 5\n\n\nclass NewFullFillAttributesUsingPluginsTest(DDFTestCase):\n    def test_custom_field_not_registered_must_raise_an_unsupported_field_exception(self):\n        DDFLibrary.get_instance().clear()\n        with pytest.raises(UnsupportedFieldError):\n            self.ddf.get(ModelWithUnsupportedField)\n\n    def test_new_fill_field_with_data_generated_by_plugins_with_dict(self):\n        data_fixture.plugins = settings.DDF_FIELD_FIXTURES\n        try:\n            instance = self.ddf.get(ModelForFieldPlugins)\n            # assert instance.aaa == 123456789\n            # assert instance.bbb == 123456789\n            assert instance.custom_field_custom_fixture == 123456789\n        finally:\n            data_fixture.plugins = {}\n\n    def test_new_fill_field_with_data_generated_by_plugins_with_direct_fuction(self):\n        data_fixture.plugins = settings.DDF_FIELD_FIXTURES\n        try:\n            instance = self.ddf.get(ModelForFieldPlugins)\n            assert instance.custom_field_custom_fixture2 == 987654321\n        finally:\n            data_fixture.plugins = {}\n\n    # Real Custom Field\n    def test_json_field_not_registered_must_raise_an_unsupported_field_exception(self):\n        # jsonfield requires Django 1.4+\n        try:\n            from jsonfield import JSONCharField, JSONField\n            instance = self.ddf.new(ModelForPlugins1)\n            assert False, 'JSON fields must not be supported by default'\n        except ImportError:\n            pass\n        except UnsupportedFieldError as e:\n            pass\n\n    def test_new_fill_json_field_with_data_generated_by_plugins(self):\n        # jsonfield requires Django 1.4+\n        try:\n            import json\n            from jsonfield import JSONCharField, JSONField\n            data_fixture.plugins = settings.DDF_FIELD_FIXTURES\n            try:\n                instance = self.ddf.new(ModelForPlugins1)\n                assert isinstance(instance.json_field1, str), type(instance.json_field1)\n                assert isinstance(instance.json_field2, str), type(instance.json_field2)\n                assert isinstance(json.loads(instance.json_field1), dict)\n                assert isinstance(json.loads(instance.json_field2), list)\n                assert instance.json_field1 == '{\"some random value\": \"c\"}'\n                assert instance.json_field2 == '[1, 2, 3]'\n            finally:\n                data_fixture.plugins = {}\n        except ImportError:\n            pass\n\n\nclass PostgresCustomFieldsTest(DDFTestCase):\n    @only_for_database(POSTGRES)\n    def test_json_field(self):\n        instance = self.ddf.get(ModelForPostgresFields)\n        assert instance.nullable_json_field == {}\n        assert instance.json_field == {}\n\n    @only_for_database(POSTGRES)\n    def test_json_field_as_null(self):\n        instance = self.ddf.get(ModelForPostgresFields, nullable_json_field=None)\n        assert instance.nullable_json_field is None\n\n    @only_for_database(POSTGRES)\n    def test_json_field_as_dicts(self):\n        instance = self.ddf.get(ModelForPostgresFields, json_field={'a': 1})\n        assert instance.json_field == {'a': 1}\n\n    @only_for_database(POSTGRES)\n    def test_json_field_as_lists(self):\n        instance = self.ddf.get(ModelForPostgresFields, json_field=['str1', 2, {'c': 3}])\n        assert instance.json_field == ['str1', 2, {'c': 3}]\n\n    @only_for_database(POSTGRES)\n    def test_json_field_as_strings(self):\n        instance = self.ddf.get(ModelForPostgresFields, json_field='str')\n        assert instance.json_field == 'str'\n"
  },
  {
    "path": "django_dynamic_fixture/tests/test_ddf_custom_models.py",
    "content": "from django.test import TestCase\nimport pytest\n\nfrom django_dynamic_fixture.models_test import *\nfrom django_dynamic_fixture.ddf import *\nfrom django_dynamic_fixture import G\n\ntry:\n    from polymorphic.models import PolymorphicModel\n\n    class PolymorphicModelTest(TestCase):\n        def test_create_polymorphic_model_and_retrieve(self):\n            p = G(ModelPolymorphic)\n            assert list(ModelPolymorphic.objects.all()) == [p]\n\n        def test_create_polymorphic_model_2_and_retrieve(self):\n            p = G(ModelPolymorphic2)\n            assert list(ModelPolymorphic2.objects.all()) == [p]\n\n        def test_cannot_save(self):\n            with self.assertRaises(BadDataError):\n                G(ModelPolymorphic3)\nexcept ImportError:\n    pass\n"
  },
  {
    "path": "django_dynamic_fixture/tests/test_ddf_geo.py",
    "content": "from django.conf import settings\nfrom django.core.exceptions import ImproperlyConfigured\n\ntry:\n    from django.contrib.gis.geos import *\nexcept ImproperlyConfigured:\n    pass  # environment without geo libs\n\ntry:\n    from django.contrib.gis.db import models as geomodel\nexcept ImproperlyConfigured:\n    pass  # environment without geo libs\n\nfrom django.test import TestCase\nimport pytest\n\nfrom django_dynamic_fixture.models_test import *\nfrom django_dynamic_fixture.ddf import *\nfrom django_dynamic_fixture.fixture_algorithms.sequential_fixture import SequentialDataFixture\n\n\ndata_fixture = SequentialDataFixture()\n\n\nclass DDFTestCase(TestCase):\n    def setUp(self):\n        self.ddf = DynamicFixture(data_fixture)\n\n\nif (hasattr(settings, 'DDF_TEST_GEODJANGO') and settings.DDF_TEST_GEODJANGO):\n    class GeoDjangoFieldsTest(DDFTestCase):\n        def test_geodjango_fields(self):\n            instance = self.ddf.new(ModelForGeoDjango)\n            assert isinstance(instance.geometry, GEOSGeometry), str(type(instance.geometry))\n            assert isinstance(instance.point, Point)\n            assert isinstance(instance.line_string, LineString)\n            assert isinstance(instance.polygon, Polygon)\n            assert isinstance(instance.multi_point, MultiPoint)\n            assert isinstance(instance.multi_line_string, MultiLineString)\n            assert isinstance(instance.multi_polygon, MultiPolygon)\n            assert isinstance(instance.geometry_collection, GeometryCollection)\n"
  },
  {
    "path": "django_dynamic_fixture/tests/test_ddf_signals.py",
    "content": "from django.test import TestCase\nimport pytest\n\nfrom django_dynamic_fixture.models_test import *\nfrom django_dynamic_fixture.ddf import *\nfrom django_dynamic_fixture.ddf import _PRE_SAVE, _POST_SAVE\nfrom django_dynamic_fixture.fixture_algorithms.sequential_fixture import SequentialDataFixture\n\n\ndata_fixture = SequentialDataFixture()\n\n\nclass DDFTestCase(TestCase):\n    def setUp(self):\n        self.ddf = DynamicFixture(data_fixture)\n        _PRE_SAVE.clear()\n        _POST_SAVE.clear()\n\n\n\nclass PreSaveTest(DDFTestCase):\n    def test_set_pre_save_receiver(self):\n        def callback_function(instance):\n            pass\n        set_pre_save_receiver(ModelForSignals, callback_function)\n        callback_function = lambda x: x\n        set_pre_save_receiver(ModelForSignals, callback_function)\n\n    def test_pre_save_receiver_must_raise_an_error_if_first_parameter_is_not_a_model_class(self):\n        callback_function = lambda x: x\n        with pytest.raises(InvalidReceiverError):\n            set_pre_save_receiver(str, callback_function)\n\n    def test_pre_save_receiver_must_raise_an_error_if_it_is_not_a_function(self):\n        with pytest.raises(InvalidReceiverError):\n            set_pre_save_receiver(ModelForSignals, '')\n\n    def test_pre_save_receiver_must_raise_an_error_if_it_is_not_an_only_one_argument_function(self):\n        callback_function = lambda x, y: x\n        with pytest.raises(InvalidReceiverError):\n            set_pre_save_receiver(ModelForSignals, callback_function)\n\n    def test_pre_save_receiver_must_be_executed_before_saving(self):\n        def callback_function(instance):\n            if instance.id is not None:\n                raise Exception('ops, instance already saved')\n            self.ddf.get(ModelForSignals2)\n        set_pre_save_receiver(ModelForSignals, callback_function)\n        self.ddf.get(ModelForSignals)\n        assert ModelForSignals2.objects.count() == 1\n\n    def test_bugged_pre_save_receiver_must_raise_an_error(self):\n        def callback_function(instance):\n            raise Exception('ops')\n        set_pre_save_receiver(ModelForSignals, callback_function)\n        with pytest.raises(BadDataError):\n            self.ddf.get(ModelForSignals)\n\n\nclass PostSaveTest(DDFTestCase):\n    def test_set_post_save_receiver(self):\n        def callback_function(instance):\n            pass\n        set_post_save_receiver(ModelForSignals, callback_function)\n        callback_function = lambda x: x\n        set_post_save_receiver(ModelForSignals, callback_function)\n\n    def test_post_save_receiver_must_raise_an_error_if_first_parameter_is_not_a_model_class(self):\n        callback_function = lambda x: x\n        with pytest.raises(InvalidReceiverError):\n            set_post_save_receiver(str, callback_function)\n\n    def test_post_save_receiver_must_raise_an_error_if_it_is_not_a_function(self):\n        with pytest.raises(InvalidReceiverError):\n            set_post_save_receiver(ModelForSignals, '')\n\n    def test_post_save_receiver_must_raise_an_error_if_it_is_not_an_only_one_argument_function(self):\n        callback_function = lambda x, y: x\n        with pytest.raises(InvalidReceiverError):\n            set_post_save_receiver(ModelForSignals, callback_function)\n\n    def test_pre_save_receiver_must_be_executed_before_saving(self):\n        def callback_function(instance):\n            if instance.id is None:\n                raise Exception('ops, instance not saved')\n            self.ddf.get(ModelForSignals2)\n        set_post_save_receiver(ModelForSignals, callback_function)\n        self.ddf.get(ModelForSignals)\n        assert ModelForSignals2.objects.count() == 1\n\n    def test_bugged_post_save_receiver_must_raise_an_error(self):\n        def callback_function(instance):\n            raise Exception('ops')\n        set_post_save_receiver(ModelForSignals, callback_function)\n        with pytest.raises(BadDataError):\n            self.ddf.get(ModelForSignals)\n"
  },
  {
    "path": "django_dynamic_fixture/tests/test_ddf_teaching_and_lessons.py",
    "content": "import re\n\nfrom django.test import TestCase\nimport pytest\n\nfrom django_dynamic_fixture.models_test import *\nfrom django_dynamic_fixture.ddf import *\nfrom django_dynamic_fixture.fixture_algorithms.sequential_fixture import SequentialDataFixture\n\n\ndata_fixture = SequentialDataFixture()\n\n\nclass DDFTestCase(TestCase):\n    def setUp(self):\n        self.ddf = DynamicFixture(data_fixture)\n        DDFLibrary.get_instance().clear()\n\n\nclass TeachAndLessonsTest(DDFTestCase):\n    def test_teach_a_default_lesson_for_a_model(self):\n        self.ddf.teach(ModelForLibrary, integer=1000)\n        instance = self.ddf.get(ModelForLibrary)\n        assert instance.integer == 1000\n\n    def test_default_lesson_may_be_overrided_although_it_is_an_anti_pattern(self):\n        self.ddf.teach(ModelForLibrary, integer=1000)\n        instance = self.ddf.get(ModelForLibrary)\n        assert instance.integer == 1000\n        self.ddf.teach(ModelForLibrary, integer=1001)\n        instance = self.ddf.get(ModelForLibrary)\n        assert instance.integer == 1001\n\n    def test_it_must_NOT_raise_an_error_if_user_try_to_use_a_not_saved_default_configuration(self):\n        self.ddf.get(ModelForLibrary)\n\n    def test_it_must_raise_an_error_if_try_to_set_a_static_value_to_a_field_with_unicity(self):\n        with pytest.raises(InvalidConfigurationError):\n            self.ddf.teach(ModelForLibrary, integer_unique=1000)\n\n    def test_it_allows_to_use_masks_as_lessons_for_unique_integer_fields(self):\n        self.ddf.teach(ModelForLibrary, integer_unique=Mask('1###'))\n        instance = self.ddf.get(ModelForLibrary)\n        assert 1000 <= int(instance.integer_unique) <= 1999\n\n    def test_it_allows_to_use_masks_as_lessons_for_unique_char_fields(self):\n        self.ddf.teach(ModelWithUniqueCharField, text_unique=Mask('---- ### __'))\n        instance = self.ddf.get(ModelWithUniqueCharField)\n        assert re.match(r'[A-Z]{4} [0-9]{3} [a-z]{2}', instance.text_unique)\n\n    def test_it_must_accept_dynamic_values_for_fields_with_unicity(self):\n        self.ddf.teach(ModelForLibrary, integer_unique=lambda field: 1000)\n\n    def test_it_must_NOT_propagate_lessons_for_internal_dependencies(self):\n        self.ddf.teach(ModelForLibrary, foreignkey=DynamicFixture(data_fixture, integer=1000))\n        instance = self.ddf.get(ModelForLibrary)\n        assert instance.integer != 1000\n        assert instance.foreignkey.integer == 1000\n\n    def test_it_must_use_lessons_for_internal_dependencies(self):\n        # ModelForLibrary.foreignkey is a `ModelForLibrary2`\n        self.ddf.teach(ModelForLibrary, integer=1000)\n        self.ddf.teach(ModelForLibrary2, integer=1001)\n        instance = self.ddf.get(ModelForLibrary, foreignkey=DynamicFixture(data_fixture))\n        assert instance.integer == 1000\n        assert instance.foreignkey.integer == 1001\n\n    def test_it_uses_lessons_for_base_model_when_creating_a_proxy_model(self):\n        self.ddf.teach(ModelForLibrary, integer=123)\n        instance = self.ddf.get(ProxyModelForLibrary)\n        assert instance.__class__ is ProxyModelForLibrary\n        assert instance.integer == 123\n\n    def test_it_uses_lessons_for_proxy_models_when_creating_the_base_model(self):\n        self.ddf.teach(ProxyModelForLibrary, integer=456)\n        instance = self.ddf.get(ModelForLibrary)\n        assert instance.__class__ is ModelForLibrary\n        assert instance.integer == 456\n\n    def test_it_uses_lessons_for_proxy_models_when_creating_the_proxy_model(self):\n        self.ddf.teach(ProxyModelForLibrary, integer=789)\n        instance = self.ddf.get(ProxyModelForLibrary)\n        assert instance.__class__ is ProxyModelForLibrary\n        assert instance.integer == 789\n\n    # Not implemented yet\n    # def test_teaching_must_store_ddf_configs_too(self):\n    #     self.ddf.teach(ModelForLibrary, fill_nullable_fields=False)\n    #     instance = self.ddf.get(ModelForLibrary)\n    #     assert instance.integer is None\n\n    #     DDFLibrary.get_instance().clear()\n    #     self.ddf.teach(ModelForLibrary, fill_nullable_fields=True)\n    #     instance = self.ddf.get(ModelForLibrary)\n    #     assert instance.integer is not None\n\n    # Not implemented yet\n    # def test_teaching_ddf_configs_must_NOT_be_propagated_to_another_models(self):\n    #     self.ddf.teach(ModelForLibrary, fill_nullable_fields=False)\n    #     instance = self.ddf.get(ModelForLibrary)\n    #     assert instance.integer is None\n    #     assert instance.foreignkey.integer is None\n\n    #     DDFLibrary.get_instance().clear()\n    #     self.ddf.teach(ModelForLibrary, fill_nullable_fields=True)\n    #     instance = self.ddf.get(ModelForLibrary)\n    #     assert instance.integer is not None\n    #     assert instance.foreignkey.integer is None # not populated\n\n\nclass TeachingAndCustomLessonsTest(DDFTestCase):\n    def test_a_model_can_have_custom_lessons(self):\n        self.ddf.teach(ModelForLibrary, integer=1000, ddf_lesson=None)\n        self.ddf.teach(ModelForLibrary, integer=1001, ddf_lesson='a name')\n        instance = self.ddf.get(ModelForLibrary)\n        assert instance.integer == 1000\n        instance = self.ddf.get(ModelForLibrary, ddf_lesson='a name')\n        assert instance.integer == 1001\n\n    def test_custom_lessons_must_not_be_used_if_not_explicity_specified(self):\n        self.ddf.teach(ModelForLibrary, integer=1000, ddf_lesson='a name')\n        instance = self.ddf.get(ModelForLibrary)\n        assert instance.integer != 1000\n\n    def test_a_model_can_have_many_custom_lessons(self):\n        self.ddf.teach(ModelForLibrary, integer=1000, ddf_lesson='a name')\n        self.ddf.teach(ModelForLibrary, integer=1001, ddf_lesson='a name 2')\n\n        instance = self.ddf.get(ModelForLibrary, ddf_lesson='a name')\n        assert instance.integer == 1000\n\n        instance = self.ddf.get(ModelForLibrary, ddf_lesson='a name 2')\n        assert instance.integer == 1001\n\n    def test_it_must_raise_an_error_if_user_try_to_use_a_not_saved_configuration(self):\n        with pytest.raises(InvalidConfigurationError):\n            self.ddf.get(ModelForLibrary, ddf_lesson='a not teached lesson')\n\n    def test_default_lesson_and_custom_lesson_must_work_together(self):\n        # regression test\n        self.ddf.teach(ModelForLibrary, integer=1000, ddf_lesson='a name')\n        self.ddf.teach(ModelForLibrary, integer=1001, ddf_lesson=True)\n        self.ddf.teach(ModelForLibrary, integer=1002, ddf_lesson='a name2')\n        instance = self.ddf.get(ModelForLibrary, ddf_lesson='a name')\n        assert instance.integer == 1000\n        instance = self.ddf.get(ModelForLibrary)\n        assert instance.integer == 1001\n        instance = self.ddf.get(ModelForLibrary, ddf_lesson='a name2')\n        assert instance.integer == 1002\n\n    def test_default_lesson_and_custom_lesson_must_work_together_for_different_models(self):\n        # regression test\n        self.ddf.teach(ModelForLibrary, integer=1000, ddf_lesson='a name')\n        self.ddf.teach(ModelForLibrary, integer=1001, ddf_lesson=True)\n        self.ddf.teach(ModelForLibrary, integer=1002, ddf_lesson='a name2')\n        self.ddf.teach(ModelForLibrary2, integer=2000, ddf_lesson='a name')\n        self.ddf.teach(ModelForLibrary2, integer=2001, ddf_lesson=True)\n        self.ddf.teach(ModelForLibrary2, integer=2002, ddf_lesson='a name2')\n\n        instance = self.ddf.get(ModelForLibrary, ddf_lesson='a name')\n        assert instance.integer == 1000\n        instance = self.ddf.get(ModelForLibrary)\n        assert instance.integer == 1001\n        instance = self.ddf.get(ModelForLibrary, ddf_lesson='a name2')\n        assert instance.integer == 1002\n\n        instance = self.ddf.get(ModelForLibrary2, ddf_lesson='a name')\n        assert instance.integer == 2000\n        instance = self.ddf.get(ModelForLibrary2)\n        assert instance.integer == 2001\n        instance = self.ddf.get(ModelForLibrary2, ddf_lesson='a name2')\n        assert instance.integer == 2002\n\n\nclass DDFLibraryTest(TestCase):\n    def setUp(self):\n        self.lib = DDFLibrary()\n\n    def test_add_and_get_configuration_without_string_name(self):\n        self.lib.add_configuration(ModelForLibrary, {'a': 1})\n        assert self.lib.get_configuration(ModelForLibrary) == {'a': 1}\n        assert self.lib.get_configuration(ModelForLibrary, name=DDFLibrary.DEFAULT_KEY) == {'a': 1}\n        assert self.lib.get_configuration(ModelForLibrary, name=None) == {'a': 1}\n\n        self.lib.clear()\n        self.lib.add_configuration(ModelForLibrary, {'a': 2}, name=None)\n        assert self.lib.get_configuration(ModelForLibrary) == {'a': 2}\n        assert self.lib.get_configuration(ModelForLibrary, name=DDFLibrary.DEFAULT_KEY) == {'a': 2}\n        assert self.lib.get_configuration(ModelForLibrary, name=None) == {'a': 2}\n\n        self.lib.clear()\n        self.lib.add_configuration(ModelForLibrary, {'a': 3}, name=True)\n        assert self.lib.get_configuration(ModelForLibrary) == {'a': 3}\n        assert self.lib.get_configuration(ModelForLibrary, name=DDFLibrary.DEFAULT_KEY) == {'a': 3}\n        assert self.lib.get_configuration(ModelForLibrary, name=None) == {'a': 3}\n\n    def test_add_and_get_configuration_with_name(self):\n        self.lib.add_configuration(ModelForLibrary, {'a': 1}, name='x')\n        assert self.lib.get_configuration(ModelForLibrary, name='x') == {'a': 1}\n\n    def test_clear_config(self):\n        self.lib.clear_configuration(ModelForLibrary) # run ok if empty\n        self.lib.add_configuration(ModelForLibrary, {'a': 1})\n        self.lib.add_configuration(ModelForLibrary, {'a': 2}, name='x')\n        self.lib.add_configuration(ModelForLibrary2, {'a': 3})\n        self.lib.clear_configuration(ModelForLibrary)\n        assert self.lib.get_configuration(ModelForLibrary) == {}\n        with pytest.raises(Exception):\n            self.lib.get_configuration(ModelForLibrary, name='x')\n        assert self.lib.get_configuration(ModelForLibrary2) == {'a': 3}\n\n    def test_clear(self):\n        self.lib.add_configuration(ModelForLibrary, {'a': 1})\n        self.lib.add_configuration(ModelForLibrary, {'a': 2}, name='x')\n        self.lib.add_configuration(ModelForLibrary2, {'a': 3})\n        self.lib.add_configuration(ModelForLibrary2, {'a': 4}, name='x')\n        self.lib.clear()\n        assert self.lib.get_configuration(ModelForLibrary) == {}\n        with pytest.raises(Exception):\n            self.lib.get_configuration(ModelForLibrary, name='x')\n        assert self.lib.get_configuration(ModelForLibrary2) == {}\n        with pytest.raises(Exception):\n            self.lib.get_configuration(ModelForLibrary2, name='x')\n"
  },
  {
    "path": "django_dynamic_fixture/tests/test_decorators.py",
    "content": "from unittest import TestCase\n\nfrom django.conf import settings\n\nfrom django_dynamic_fixture import decorators\n\n\nclass SkipForDatabaseTest(TestCase):\n    def setUp(self):\n        self.it_was_executed = False\n\n    def tearDown(self):\n        # It is important to do not break others tests: global and shared variable\n        decorators.DATABASE_ENGINE = settings.DATABASES['default']['ENGINE']\n\n    @decorators.only_for_database(decorators.POSTGRES)\n    def method_postgres(self):\n        self.it_was_executed = True\n\n    def test_annotated_method_only_for_postgres(self):\n        decorators.DATABASE_ENGINE = decorators.SQLITE3\n        self.method_postgres()\n        assert self.it_was_executed is False\n\n        decorators.DATABASE_ENGINE = decorators.POSTGRES\n        self.method_postgres()\n        assert self.it_was_executed\n\n\nclass OnlyForDatabaseTest(TestCase):\n    def setUp(self):\n        self.it_was_executed = False\n\n    def tearDown(self):\n        # It is important to do not break others tests: global and shared variable\n        decorators.DATABASE_ENGINE = settings.DATABASES['default']['ENGINE']\n\n    @decorators.skip_for_database(decorators.SQLITE3)\n    def method_sqlite3(self):\n        self.it_was_executed = True\n\n    def test_annotated_method_skip_for_sqlite3(self):\n        decorators.DATABASE_ENGINE = decorators.SQLITE3\n        self.method_sqlite3()\n        assert self.it_was_executed is False\n\n        decorators.DATABASE_ENGINE = decorators.POSTGRES\n        self.method_sqlite3()\n        assert self.it_was_executed\n"
  },
  {
    "path": "django_dynamic_fixture/tests/test_django_helper.py",
    "content": "\nfrom django.test import TestCase\nfrom django.db import models\nimport pytest\n\nfrom django_dynamic_fixture import N, G\nfrom django_dynamic_fixture.models_test import *\nfrom django_dynamic_fixture.django_helper import *\n\n\nclass DjangoHelperAppsTest(TestCase):\n    def test_get_apps_must_return_all_installed_apps(self):\n        assert len(get_apps()) >= 1\n\n    def test_get_apps_may_be_filtered_by_app_names(self):\n        apps = get_apps(application_labels=['django_dynamic_fixture'])\n        assert len(apps) == 1\n\n    def test_get_apps_may_ignore_some_apps(self):\n        apps = len(get_apps(exclude_application_labels=['django_dynamic_fixture']))\n        assert len(get_apps()) - apps == 1\n\n    def test_app_name_must_be_valid(self):\n        with pytest.raises(Exception):\n            get_apps(application_labels=['x'])\n        with pytest.raises(Exception):\n            get_apps(exclude_application_labels=['x'])\n\n    def test_get_app_name_must(self):\n        import django_dynamic_fixture.models as ddf\n        assert get_app_name(ddf) == 'django_dynamic_fixture'\n\n    def test_get_models_of_an_app_must(self):\n        ddf = get_apps(application_labels=['django_dynamic_fixture'])[0]\n        models_ddf = get_models_of_an_app(ddf)\n        assert len(models_ddf) > 0\n        assert ModelWithNumbers in models_ddf\n\n\nclass DjangoHelperModelsTest(TestCase):\n    def test_get_model_name(self):\n        class MyModel_test_get_model_name(models.Model): pass\n        assert get_model_name(MyModel_test_get_model_name) == 'MyModel_test_get_model_name'\n\n    def test_get_unique_model_name(self):\n        class MyModel_test_get_unique_model_name(models.Model): pass\n        assert get_unique_model_name(MyModel_test_get_unique_model_name) == 'django_dynamic_fixture.tests.test_django_helper.MyModel_test_get_unique_model_name'\n\n    def test_get_fields_from_model(self):\n        class Model4GetFields_test_get_fields_from_model(models.Model):\n            integer = models.IntegerField()\n        fields = get_fields_from_model(Model4GetFields_test_get_fields_from_model)\n        assert get_field_by_name_or_raise(Model4GetFields_test_get_fields_from_model, 'id') in fields\n        assert get_field_by_name_or_raise(Model4GetFields_test_get_fields_from_model, 'integer') in fields\n\n    def test_get_local_fields(self):\n        class ModelForGetLocalFields_test_get_local_fields(models.Model):\n            integer = models.IntegerField()\n        fields = get_local_fields(ModelForGetLocalFields_test_get_local_fields)\n        assert get_field_by_name_or_raise(ModelForGetLocalFields_test_get_local_fields, 'id') in fields\n        assert get_field_by_name_or_raise(ModelForGetLocalFields_test_get_local_fields, 'integer') in fields\n\n    def test_get_field_names_of_model(self):\n        class Model4GetFieldNames_test_get_field_names_of_model(models.Model):\n            smallinteger = models.SmallIntegerField()\n        fields = get_field_names_of_model(Model4GetFieldNames_test_get_field_names_of_model)\n        assert 'smallinteger' in fields\n        assert 'unknown' not in fields\n\n    def test_get_many_to_many_fields_from_model(self):\n        class ModelRelated_test_get_many_to_many_fields_from_model(models.Model): pass\n        class ModelWithM2M_test_get_many_to_many_fields_from_model(models.Model):\n            manytomany = models.ManyToManyField('ModelRelated_test_get_many_to_many_fields_from_model', related_name='m2m')\n        fields = get_many_to_many_fields_from_model(ModelWithM2M_test_get_many_to_many_fields_from_model)\n        assert get_field_by_name_or_raise(ModelWithM2M_test_get_many_to_many_fields_from_model, 'manytomany') in fields\n        assert get_field_by_name_or_raise(ModelWithM2M_test_get_many_to_many_fields_from_model, 'id') not in fields\n\n    def test_is_model_class(self):\n        class MyModel_test_is_model_class(models.Model): pass\n        assert is_model_class(MyModel_test_is_model_class) == True\n        class X(object): pass\n        assert is_model_class(X) == False\n\n    def test_is_model_abstract(self):\n        class AbstractModel_test_is_model_abstract(models.Model):\n            class Meta:\n                abstract = True\n        assert is_model_abstract(AbstractModel_test_is_model_abstract)\n\n        class ConcreteModel_test_is_model_abstract(models.Model):\n            class Meta:\n                abstract = False\n        assert is_model_abstract(ConcreteModel_test_is_model_abstract) == False\n\n    def test_is_model_managed(self):\n        class NotManagedModel_test_is_model_managed(models.Model):\n            class Meta:\n                managed = False\n        assert is_model_managed(NotManagedModel_test_is_model_managed) == False\n\n        class ManagedModel_test_is_model_managed(models.Model):\n            class Meta:\n                managed = True\n        assert is_model_managed(ManagedModel_test_is_model_managed)\n\n    def test_model_has_the_field(self):\n        class ModelWithWithoutFields_test_model_has_the_field(models.Model):\n            integer = models.IntegerField()\n            selfforeignkey = models.ForeignKey('self', null=True, on_delete=models.DO_NOTHING)\n            manytomany = models.ManyToManyField('self', related_name='m2m')\n        assert model_has_the_field(ModelWithWithoutFields_test_model_has_the_field, 'integer')\n        assert model_has_the_field(ModelWithWithoutFields_test_model_has_the_field, 'selfforeignkey')\n        assert model_has_the_field(ModelWithWithoutFields_test_model_has_the_field, 'manytomany')\n        assert model_has_the_field(ModelWithWithoutFields_test_model_has_the_field, 'x') == False\n\n\nclass DjangoHelperFieldsTest(TestCase):\n    def test_get_unique_field_name(self):\n        class Model4GetUniqueFieldName_test_get_unique_field_name(models.Model):\n            integer = models.IntegerField()\n        field = get_field_by_name_or_raise(Model4GetUniqueFieldName_test_get_unique_field_name, 'integer')\n        assert get_unique_field_name(field) == 'django_dynamic_fixture.tests.test_django_helper.Model4GetUniqueFieldName_test_get_unique_field_name.integer'\n\n    def test_get_related_model(self):\n        class ModelRelated_test_get_related_model(models.Model): pass\n        class Model4GetRelatedModel_test_get_related_model(models.Model):\n            fk = models.ForeignKey(ModelRelated_test_get_related_model, on_delete=models.DO_NOTHING)\n        assert get_related_model(get_field_by_name_or_raise(Model4GetRelatedModel_test_get_related_model, 'fk')) == \\\n               ModelRelated_test_get_related_model\n\n\n    def test_field_is_a_parent_link(self):\n        class ModelParent_test_get_related_model(models.Model): pass\n        class Model4FieldIsParentLink_test_get_related_model(ModelParent):\n            o2o_with_parent_link = models.OneToOneField(ModelParent_test_get_related_model, parent_link=True, related_name='my_custom_ref_x', on_delete=models.DO_NOTHING)\n        class Model4FieldIsParentLink2(ModelParent):\n            o2o_without_parent_link = models.OneToOneField(ModelParent_test_get_related_model, parent_link=False, related_name='my_custom_ref_y', on_delete=models.DO_NOTHING)\n        # FIXME\n        # assert field_is_a_parent_link(get_field_by_name_or_raise(Model4FieldIsParentLink, 'o2o_with_parent_link'))\n        assert field_is_a_parent_link(get_field_by_name_or_raise(Model4FieldIsParentLink2, 'o2o_without_parent_link')) == False\n\n    def test_field_has_choices(self):\n        class Model4FieldHasChoices_test_get_related_model(models.Model):\n            with_choices = models.IntegerField(choices=((1, 1), (2, 2)))\n            without_choices = models.IntegerField()\n        assert field_has_choices(get_field_by_name_or_raise(Model4FieldHasChoices_test_get_related_model, 'with_choices'))\n        assert field_has_choices(get_field_by_name_or_raise(Model4FieldHasChoices_test_get_related_model, 'without_choices')) == False\n\n    def test_field_has_default_value(self):\n        class Model4FieldHasDefault_test_field_has_default_value(models.Model):\n            with_default = models.IntegerField(default=1)\n            without_default = models.IntegerField()\n        assert field_has_default_value(get_field_by_name_or_raise(Model4FieldHasDefault_test_field_has_default_value, 'with_default'))\n        assert field_has_default_value(get_field_by_name_or_raise(Model4FieldHasDefault_test_field_has_default_value, 'without_default')) == False\n\n    def test_field_is_unique(self):\n        class Model4FieldMustBeUnique_test_field_is_unique(models.Model):\n            unique = models.IntegerField(unique=True)\n            not_unique = models.IntegerField()\n        assert field_is_unique(get_field_by_name_or_raise(Model4FieldMustBeUnique_test_field_is_unique, 'unique'))\n        assert field_is_unique(get_field_by_name_or_raise(Model4FieldMustBeUnique_test_field_is_unique, 'not_unique')) == False\n\n    def test_is_key_field(self):\n        class ModelForKeyField_test_is_key_field(models.Model):\n            integer = models.IntegerField()\n        assert is_key_field(get_field_by_name_or_raise(ModelForKeyField_test_is_key_field, 'id'))\n        assert is_key_field(get_field_by_name_or_raise(ModelForKeyField_test_is_key_field, 'integer')) == False\n\n    def test_is_relationship_field(self):\n        class ModelForRelationshipField_test_is_relationship_field(models.Model):\n            fk = models.ForeignKey('self', on_delete=models.DO_NOTHING)\n            one2one = models.OneToOneField('self', on_delete=models.DO_NOTHING)\n        assert is_relationship_field(get_field_by_name_or_raise(ModelForRelationshipField_test_is_relationship_field, 'fk'))\n        assert is_relationship_field(get_field_by_name_or_raise(ModelForRelationshipField_test_is_relationship_field, 'one2one'))\n        assert is_relationship_field(get_field_by_name_or_raise(ModelForRelationshipField_test_is_relationship_field, 'id')) == False\n\n    def test_is_file_field(self):\n        class ModelForFileField_test_is_file_field(models.Model):\n            filefield = models.FileField()\n        assert is_file_field(get_field_by_name_or_raise(ModelForFileField_test_is_file_field, 'filefield'))\n        assert is_file_field(get_field_by_name_or_raise(ModelForFileField_test_is_file_field, 'id')) == False\n\n\nclass PrintFieldValuesTest(TestCase):\n    def test_model_not_saved_do_not_raise_an_exception(self):\n        instance = N(ModelWithNumbers)\n        print_field_values(instance)\n\n    def test_model_saved_do_not_raise_an_exception(self):\n        instance = G(ModelWithNumbers)\n        print_field_values(instance)\n\n    def test_print_accept_list_of_models_too(self):\n        instances = G(ModelWithNumbers, n=2)\n        print_field_values(instances)\n        print_field_values([G(ModelWithNumbers), G(ModelWithNumbers)])\n\n    def test_print_accept_a_queryset_too(self):\n        G(ModelWithNumbers, n=2)\n        print_field_values(ModelWithNumbers.objects.all())\n\n"
  },
  {
    "path": "django_dynamic_fixture/tests/test_fdf.py",
    "content": "from django_dynamic_fixture.fdf import *\nfrom django.core.files import File\n\n\nclass FileSystemDjangoTestCaseDealWithDirectoriesTest(FileSystemDjangoTestCase):\n\n    def test_create_temp_directory_must_create_an_empty_directory(self):\n        directory = self.create_temp_directory()\n        self.assertDirectoryExists(directory)\n        self.assertNumberOfFiles(directory, 0)\n\n    def test_remove_temp_directory(self):\n        directory = self.create_temp_directory()\n        self.remove_temp_directory(directory)\n        self.assertDirectoryDoesNotExists(directory)\n\n    def test_remove_temp_directory_must_remove_directories_created_out_of_the_testcase_too(self):\n        directory = tempfile.mkdtemp()\n        self.remove_temp_directory(directory)\n        self.assertDirectoryDoesNotExists(directory)\n\n    def test_remove_temp_directory_must_remove_their_files_too(self):\n        directory = self.create_temp_directory()\n        self.create_temp_file_with_name(directory, 'x.txt')\n        self.remove_temp_directory(directory)\n        self.assertDirectoryDoesNotExists(directory)\n\n\nclass FileSystemDjangoTestCaseDealWithTemporaryFilesTest(FileSystemDjangoTestCase):\n\n    def test_create_temp_file_must_create_a_temporary_file_in_an_arbitrary_directory(self):\n        filepath = self.create_temp_file()\n        self.assertFileExists(filepath)\n\n        directory = self.get_directory_of_the_file(filepath)\n        filename = self.get_filename(filepath)\n        self.assertDirectoryContainsFile(directory, filename)\n\n    def test_create_temp_file_must_create_an_empty_temporary_file(self):\n        filepath = self.create_temp_file()\n        assert self.get_content_of_file(filepath) == ''\n\n    def test_create_temp_file_must_is_ready_to_add_content_to_it(self):\n        filepath = self.create_temp_file()\n        self.add_text_to_file(filepath, 'abc')\n        assert self.get_content_of_file(filepath) == 'abc'\n\n\nclass FileSystemDjangoTestCaseDealWithSpecificTemporaryFilesTest(FileSystemDjangoTestCase):\n\n    def test_create_temp_file_with_name_must_create_a_file_in_an_specific_directory_with_an_specific_name(self):\n        directory = self.create_temp_directory()\n        filepath = self.create_temp_file_with_name(directory, 'x.txt')\n        self.assertFileExists(filepath)\n\n        assert self.get_directory_of_the_file(filepath) == directory\n        assert self.get_filename(filepath) == 'x.txt'\n        self.assertDirectoryContainsFile(directory, self.get_filename(filepath))\n        self.assertNumberOfFiles(directory, 1)\n\n    def test_create_temp_file_with_name_must_create_an_empty_file(self):\n        directory = self.create_temp_directory()\n        filepath = self.create_temp_file_with_name(directory, 'x.txt')\n        assert self.get_content_of_file(filepath) == ''\n\n    def test_create_temp_file_with_name_is_ready_to_add_content_to_it(self):\n        directory = self.create_temp_directory()\n        filepath = self.create_temp_file_with_name(directory, 'x.txt')\n        self.add_text_to_file(filepath, 'abc')\n        assert self.get_content_of_file(filepath) == 'abc'\n\n\nclass FileSystemDjangoTestCaseCanRenameFilesTest(FileSystemDjangoTestCase):\n\n    def test_rename_file_must_preserve_the_directory(self):\n        directory = self.create_temp_directory()\n        old_filepath = self.create_temp_file_with_name(directory, 'x.txt')\n        old_filename = self.get_filename(old_filepath)\n\n        new_filepath = self.rename_temp_file(old_filepath, 'y.txt')\n        self.assertFileExists(new_filepath)\n        self.assertFileDoesNotExists(old_filepath)\n\n        new_filename = self.get_filename(new_filepath)\n        self.assertDirectoryContainsFile(directory, new_filename)\n        self.assertDirectoryDoesNotContainsFile(directory, old_filename)\n\n    def test_rename_file_must_preserve_the_file_content(self):\n        directory = self.create_temp_directory()\n        old_filepath = self.create_temp_file_with_name(directory, 'x.txt')\n        self.add_text_to_file(old_filepath, 'abc')\n\n        new_filepath = self.rename_temp_file(old_filepath, 'y.txt')\n\n        assert self.get_content_of_file(new_filepath) == 'abc'\n\n\nclass FileSystemDjangoTestCaseCanRemoveFilesTest(FileSystemDjangoTestCase):\n\n    def test_remove_file(self):\n        filepath = self.create_temp_file()\n        self.remove_temp_file(filepath)\n        self.assertFileDoesNotExists(filepath)\n\n    def test_remove_file_must_remove_files_with_custom_name_too(self):\n        directory = self.create_temp_directory()\n        filepath = self.create_temp_file_with_name(directory, 'x.txt')\n        self.remove_temp_file(filepath)\n        self.assertFileDoesNotExists(filepath)\n\n    def test_remove_file_must_remove_files_with_data_too(self):\n        filepath = self.create_temp_file()\n        self.add_text_to_file(filepath, 'abc')\n        self.remove_temp_file(filepath)\n        self.assertFileDoesNotExists(filepath)\n\n\nclass FileSystemDjangoTestCaseCanCopyFilesTest(FileSystemDjangoTestCase):\n\n    def test_copy_file_to_dir_must_not_remove_original_file(self):\n        directory = self.create_temp_directory()\n        filepath = self.create_temp_file()\n\n        new_filepath = self.copy_file_to_dir(filepath, directory)\n\n        self.assertFileExists(new_filepath)\n        self.assertFileExists(filepath)\n\n    def test_copy_file_to_dir_must_preserve_file_content(self):\n        directory = self.create_temp_directory()\n        filepath = self.create_temp_file()\n        self.add_text_to_file(filepath, 'abc')\n\n        new_filepath = self.copy_file_to_dir(filepath, directory)\n        self.get_content_of_file(new_filepath) == 'abc'\n\n\nclass FileSystemDjangoTestCaseDealWithDjangoFileFieldTest(FileSystemDjangoTestCase):\n\n    def test_django_file_must_create_a_django_file_object(self):\n        django_file = self.create_django_file_with_temp_file('x.txt')\n        assert isinstance(django_file, File)\n        assert django_file.name == 'x.txt'\n\n    def test_django_file_must_create_a_temporary_file_ready_to_add_content(self):\n        django_file = self.create_django_file_with_temp_file('x.txt')\n        filepath = django_file.file.name\n\n        self.add_text_to_file(filepath, 'abc')\n\n        assert self.get_content_of_file(filepath) == 'abc'\n\n\nclass FileSystemDjangoTestCaseTearDownTest(FileSystemDjangoTestCase):\n\n    def test_teardown_must_delete_all_created_files_in_tests(self):\n        directory = self.create_temp_directory()\n        filepath1 = self.create_temp_file()\n        filepath2 = self.create_temp_file_with_name(directory, 'x.txt')\n\n        self.fdf_teardown()\n\n        self.assertFileDoesNotExists(filepath1)\n        self.assertFileDoesNotExists(filepath2)\n\n    def test_teardown_must_delete_files_with_content_too(self):\n        filepath = self.create_temp_file()\n        self.add_text_to_file(filepath, 'abc')\n\n        self.fdf_teardown()\n\n        self.assertFileDoesNotExists(filepath)\n\n    def test_teardown_must_delete_all_created_directories_in_tests(self):\n        directory = self.create_temp_directory()\n\n        self.fdf_teardown()\n\n        self.assertDirectoryDoesNotExists(directory)\n\n\nclass FileSystemDjangoTestCaseTearDownFrameworkConfigurationTest(FileSystemDjangoTestCase):\n\n    def tearDown(self):\n        super().tearDown()\n\n        self.assertFileDoesNotExists(self.filepath1)\n        self.assertFileDoesNotExists(self.filepath2)\n        self.assertDirectoryDoesNotExists(self.directory)\n\n    def test_creating_directory_and_files_for_the_testcase(self):\n        self.directory = self.create_temp_directory()\n        self.filepath1 = self.create_temp_file()\n        self.filepath2 = self.create_temp_file_with_name(self.directory, 'x.txt')\n"
  },
  {
    "path": "django_dynamic_fixture/tests/test_global_settings.py",
    "content": "import importlib\n\nfrom django import conf\n\nfrom django.test import TestCase\nimport pytest\n\nfrom django_dynamic_fixture import global_settings\nfrom django_dynamic_fixture.fixture_algorithms.sequential_fixture import SequentialDataFixture, \\\n    StaticSequentialDataFixture\nfrom django_dynamic_fixture.fixture_algorithms.random_fixture import RandomDataFixture\n\n\n\nclass AbstractGlobalSettingsTestCase(TestCase):\n    def tearDown(self):\n        if hasattr(conf.settings, 'DDF_DEFAULT_DATA_FIXTURE'): del conf.settings.DDF_DEFAULT_DATA_FIXTURE\n        if hasattr(conf.settings, 'DDF_FILL_NULLABLE_FIELDS'): del conf.settings.DDF_FILL_NULLABLE_FIELDS\n        if hasattr(conf.settings, 'DDF_IGNORE_FIELDS'): del conf.settings.DDF_IGNORE_FIELDS\n        if hasattr(conf.settings, 'DDF_NUMBER_OF_LAPS'): del conf.settings.DDF_NUMBER_OF_LAPS\n        if hasattr(conf.settings, 'DDF_VALIDATE_MODELS'): del conf.settings.DDF_VALIDATE_MODELS\n        importlib.reload(conf)\n\n\nclass CustomDataFixture: pass\n\nclass DDF_DEFAULT_DATA_FIXTURE_TestCase(AbstractGlobalSettingsTestCase):\n    def test_not_configured_must_load_default_value(self):\n        importlib.reload(global_settings)\n        assert SequentialDataFixture == type(global_settings.DDF_DEFAULT_DATA_FIXTURE)\n\n    def test_may_be_an_internal_data_fixture_nick_name(self):\n        conf.settings.DDF_DEFAULT_DATA_FIXTURE = 'sequential'\n        importlib.reload(global_settings)\n        assert SequentialDataFixture == type(global_settings.DDF_DEFAULT_DATA_FIXTURE)\n\n        conf.settings.DDF_DEFAULT_DATA_FIXTURE = 'random'\n        importlib.reload(global_settings)\n        assert RandomDataFixture == type(global_settings.DDF_DEFAULT_DATA_FIXTURE)\n\n        conf.settings.DDF_DEFAULT_DATA_FIXTURE = 'static_sequential'\n        importlib.reload(global_settings)\n        assert StaticSequentialDataFixture == type(global_settings.DDF_DEFAULT_DATA_FIXTURE)\n\n    def test_may_be_a_path_to_a_custom_data_fixture(self):\n        conf.settings.DDF_DEFAULT_DATA_FIXTURE = 'django_dynamic_fixture.tests.test_global_settings.CustomDataFixture'\n        importlib.reload(global_settings)\n        assert CustomDataFixture == type(global_settings.DDF_DEFAULT_DATA_FIXTURE)\n\n    def test_if_path_can_not_be_found_it_will_raise_an_exception(self):\n        conf.settings.DDF_DEFAULT_DATA_FIXTURE = 'unknown_path.CustomDataFixture'\n        with pytest.raises(Exception):\n            importlib.reload(global_settings)\n\n\nclass DDF_FILL_NULLABLE_FIELDS_TestCase(AbstractGlobalSettingsTestCase):\n    def test_not_configured_must_load_default_value(self):\n        importlib.reload(global_settings)\n        assert global_settings.DDF_FILL_NULLABLE_FIELDS is False\n\n    def test_must_be_a_boolean(self):\n        conf.settings.DDF_FILL_NULLABLE_FIELDS = True\n        importlib.reload(global_settings)\n        assert global_settings.DDF_FILL_NULLABLE_FIELDS\n\n    def test_must_raise_an_exception_if_it_is_not_a_boolean(self):\n        conf.settings.DDF_FILL_NULLABLE_FIELDS = 'x'\n        with pytest.raises(Exception):\n            importlib.reload(global_settings)\n\n\nclass DDF_IGNORE_FIELDS_TestCase(AbstractGlobalSettingsTestCase):\n    def test_not_configured_must_load_default_value(self):\n        importlib.reload(global_settings)\n        assert global_settings.DDF_IGNORE_FIELDS == []\n\n    def test_must_be_a_list_of_strings(self):\n        conf.settings.DDF_IGNORE_FIELDS = ['x']\n        importlib.reload(global_settings)\n        assert global_settings.DDF_IGNORE_FIELDS == ['x']\n\n    def test_must_raise_an_exception_if_it_is_not_an_list_of_strings(self):\n        conf.settings.DDF_IGNORE_FIELDS = None\n        with pytest.raises(Exception):\n            importlib.reload(global_settings)\n\n\nclass DDF_FK_MIN_DEPTH_TestCase(AbstractGlobalSettingsTestCase):\n    def test_not_configured_must_load_default_value(self):\n        importlib.reload(global_settings)\n        assert global_settings.DDF_FK_MIN_DEPTH == 0\n\n    def test_must_be_an_integer(self):\n        conf.settings.DDF_FK_MIN_DEPTH = 2\n        importlib.reload(global_settings)\n        assert global_settings.DDF_FK_MIN_DEPTH == 2\n\n    def test_must_raise_an_exception_if_it_is_not_an_integer(self):\n        conf.settings.DDF_FK_MIN_DEPTH = None\n        with pytest.raises(Exception):\n            importlib.reload(global_settings)\n\n\nclass DDF_VALIDATE_MODELS_TestCase(AbstractGlobalSettingsTestCase):\n    def test_not_configured_must_load_default_value(self):\n        importlib.reload(global_settings)\n        assert global_settings.DDF_VALIDATE_MODELS is False\n\n    def test_must_be_a_boolean(self):\n        conf.settings.DDF_VALIDATE_MODELS = False\n        importlib.reload(global_settings)\n        assert global_settings.DDF_VALIDATE_MODELS is False\n\n    def test_must_raise_an_exception_if_it_is_not_a_boolean(self):\n        conf.settings.DDF_VALIDATE_MODELS = 'x'\n        with pytest.raises(Exception):\n            importlib.reload(global_settings)\n"
  },
  {
    "path": "django_dynamic_fixture/tests/test_mask.py",
    "content": "import re\n\nfrom django.test import TestCase\nimport pytest\n\nfrom django_dynamic_fixture.models_test import *\nfrom django_dynamic_fixture.ddf import *\nfrom django_dynamic_fixture.fixture_algorithms.sequential_fixture import SequentialDataFixture\n\n\nclass DDFTestCase(TestCase):\n    def setUp(self):\n        self.ddf = DynamicFixture(SequentialDataFixture())\n\n\nclass MaskTests(DDFTestCase):\n    def test_it_must_generate_random_numbers(self):\n        instance = self.ddf.get(ModelWithStrings, string=Mask('###'))\n        assert re.match(r'\\d{3}', instance.string)\n\n    def test_it_must_generate_lower_ascii_chars(self):\n        instance = self.ddf.get(ModelWithStrings, string=Mask('___'))\n        assert re.match(r'[a-z]{3}', instance.string)\n\n    def test_it_must_generate_upper_ascii_chars(self):\n        instance = self.ddf.get(ModelWithStrings, string=Mask('---'))\n        assert re.match(r'[A-Z]{3}', instance.string)\n\n    def test_it_must_accept_pure_chars(self):\n        instance = self.ddf.get(ModelWithStrings, string=Mask('ABC123'))\n        assert re.match(r'ABC123', instance.string)\n\n    def test_it_must_be_able_to_escape_symbols(self):\n        instance = self.ddf.get(ModelWithStrings, string=Mask(r'!# !_ !-'))\n        assert '# _ -' == instance.string\n\n    def test_phone_mask(self):\n        instance = self.ddf.get(ModelWithStrings, string=Mask(r'+## (##) #####!-#####'))\n        assert re.match(r'\\+\\d{2} \\(\\d{2}\\) \\d{5}-\\d{5}', instance.string)\n\n    def test_address_mask(self):\n        instance = self.ddf.get(ModelWithStrings, string=Mask(r'St. -______, ### !- -- --'))\n        assert re.match(r'St\\. [A-Z]{1}[a-z]{6}, \\d{3} - [A-Z]{2} [A-Z]{2}', instance.string)\n"
  },
  {
    "path": "django_dynamic_fixture/tests/test_module_ddf_shortcut.py",
    "content": "\ntry:\n    from ddf import N, G, F, C, P, PRE_SAVE, POST_SAVE\n    from ddf import new, get, fixture, teach, look_up_alias\n    from ddf import skip_for_database, only_for_database\n    from ddf import FileSystemDjangoTestCase\nexcept ImportError:\n    assert False, 'Import `ddf` module is not working properly.'\n"
  },
  {
    "path": "django_dynamic_fixture/tests/test_sample_app.py",
    "content": "import pytest\n\nfrom django.test import TestCase\n\nfrom ddf import *\n\n\nclass SampleAppTestCase(TestCase):\n    def test_publisher(self):\n        o = G('django_dynamic_fixture.Publisher')\n        assert o.name is not None\n\n    def test_author(self):\n        o = G('django_dynamic_fixture.Author')\n        assert o.name is not None\n        assert o.description is None\n        o = G('django_dynamic_fixture.Author', fill_nullable_fields=True)\n        assert o.description is not None\n\n    def test_category(self):\n        o = G('django_dynamic_fixture.Category')\n        assert o.name is not None\n        assert o.parent is None\n        o = G('django_dynamic_fixture.Category', fk_min_depth=1)\n        assert o.parent is not None\n        assert o.parent.parent is None\n        o = G('django_dynamic_fixture.Category', fk_min_depth=2)\n        assert o.parent.parent is not None\n        assert o.parent.parent.parent is None\n\n    def test_book(self):\n        o = G('django_dynamic_fixture.Book')\n        assert o.main_author is not None\n        assert o.main_author.name is not None\n        assert o.authors.all().count() == 0\n        assert o.categories.all().count() == 0\n        o = G('django_dynamic_fixture.Book', authors=2, categories=5)\n        assert o.authors.all().count() == 2\n        assert o.categories.all().count() == 5\n        o = G('django_dynamic_fixture.Book', metadata={'a': 1})\n        assert o.metadata == {'a': 1}\n\n    def test_book_edition(self):\n        o = G('django_dynamic_fixture.BookEdition')\n        assert o.book is not None\n        assert o.year is not None\n        assert o.publishers.all().count() == 0\n        o = G('django_dynamic_fixture.BookEdition', publishers=2)\n        assert o.publishers.all().count() == 2\n\n    def test_book_publisher(self):\n        o = G('django_dynamic_fixture.BookPublisher')\n        assert o.book_edition.book is not None\n        assert o.publisher is not None\n        assert o.comments is not None\n"
  },
  {
    "path": "django_dynamic_fixture/tests/test_wrappers.py",
    "content": "\nfrom django.test import TransactionTestCase as TestCase\n\nfrom django_dynamic_fixture.models_test import EmptyModel, ModelWithRelationships, ModelForLibrary, ModelWithStrings\nfrom django_dynamic_fixture import N, G, F, C, M, P, teach, look_up_alias, PRE_SAVE, POST_SAVE\n\n\nclass NShortcutTest(TestCase):\n    def test_shortcut_N(self):\n        instance = N(EmptyModel)\n        assert instance.id == None\n\n\nclass GShortcutTest(TestCase):\n    def test_shortcut_G(self):\n        instance = G(EmptyModel)\n        assert instance.id != None\n\n\nclass PShortcutTest(TestCase):\n    def test_accept_model_instance(self):\n        P(N(EmptyModel))\n        P(G(EmptyModel))\n\n    def test_accepts_list(self):\n        P([N(EmptyModel), G(EmptyModel)])\n\n    def test_accepts_tuple(self):\n        P((N(EmptyModel), G(EmptyModel)))\n\n    def test_accepts_queryset(self):\n        P(EmptyModel.objects.all())\n\n\nclass FShortcutTest(TestCase):\n    def test_fk(self):\n        instance = G(ModelWithRelationships, integer=1000, foreignkey=F(integer=1001))\n        assert 1000, instance.integer == 1000\n        assert instance.foreignkey.integer == 1001\n\n    def test_self_fk(self):\n        instance = G(ModelWithRelationships, integer=1000, selfforeignkey=F(integer=1001))\n        assert instance.integer == 1000\n        assert instance.selfforeignkey.integer == 1001\n\n    def test_o2o(self):\n        instance = G(ModelWithRelationships, integer=1000, onetoone=F(integer=1001))\n        assert instance.integer == 1000\n        assert instance.onetoone.integer == 1001\n\n    def test_m2m_with_one_element(self):\n        instance = G(ModelWithRelationships, integer=1000, manytomany=[F(integer=1001)])\n        assert instance.integer == 1000\n        assert instance.manytomany.all()[0].integer == 1001\n\n    def test_m2m_with_many_elements(self):\n        instance = G(ModelWithRelationships, integer=1000, manytomany=[F(integer=1001), F(integer=1002)])\n        assert instance.integer == 1000\n        assert instance.manytomany.all()[0].integer == 1001\n        assert instance.manytomany.all()[1].integer == 1002\n\n    def test_full_example(self):\n        instance = G(ModelWithRelationships, integer=1000,\n                     foreignkey=F(integer=1001),\n                     selfforeignkey=F(integer=1002),\n                     onetoone=F(integer=1003),\n                     manytomany=[F(integer=1004), F(integer=1005), F(selfforeignkey=F(integer=1006))])\n        assert instance.integer == 1000\n        assert instance.foreignkey.integer == 1001\n        assert instance.selfforeignkey.integer == 1002\n        assert instance.onetoone.integer == 1003\n        assert instance.manytomany.all()[0].integer == 1004\n        assert instance.manytomany.all()[1].integer == 1005\n        assert instance.manytomany.all()[2].selfforeignkey.integer == 1006\n\n    def test_two_properties_same_object(self):\n        instance = G(ModelWithRelationships, integer=1000, foreignkey=F(integer=1001, integer_b=1002))\n        assert instance.integer == 1000\n        assert instance.foreignkey.integer == 1001\n        assert instance.foreignkey.integer_b == 1002\n\n    def test_using_look_up_alias(self):\n        instance = G(ModelWithRelationships, integer=1000,\n                     foreignkey__integer=1001,\n                     selfforeignkey__integer=1002,\n                     onetoone__integer=1003,\n                     manytomany=[F(integer=1004), F(integer=1005), F(selfforeignkey__integer=1006)])\n        assert instance.integer == 1000\n        assert instance.foreignkey.integer == 1001\n        assert instance.selfforeignkey.integer == 1002\n        assert instance.onetoone.integer == 1003\n        assert instance.manytomany.all()[0].integer == 1004\n        assert instance.manytomany.all()[1].integer == 1005\n        assert instance.manytomany.all()[2].selfforeignkey.integer == 1006\n\n    def test_using_look_up_alias_two_properties_same_object(self):\n        instance = G(ModelWithRelationships, integer=1000,\n                                             foreignkey__integer=1001,\n                                             foreignkey__integer_b=1002)\n        assert instance.integer == 1000\n        assert instance.foreignkey.integer == 1001\n        assert instance.foreignkey.integer_b == 1002\n\n    def test_using_look_up_alias_two_properties_same_object(self):\n        instance = G(ModelWithRelationships, integer=1000,\n                                             foreignkey__integer=1001,\n                                             foreignkey__integer_b=1002)\n        assert instance.integer == 1000\n        assert instance.foreignkey.integer_b == 1002\n        assert instance.foreignkey.integer == 1001\n\n\nclass CShortcutTest(TestCase):\n    def test_copying_from_the_same_model(self):\n        instance = G(ModelWithRelationships, integer=C('integer_b'))\n        assert instance.integer == instance.integer_b\n\n    def test_copying_from_a_fk(self):\n        instance = G(ModelWithRelationships, foreignkey=F(), integer=C('foreignkey.integer'))\n        assert instance.integer == instance.foreignkey.integer\n\n    def test_copying_from_a_one2one(self):\n        instance = G(ModelWithRelationships, onetoone=F(), integer=C('onetoone.integer'))\n        assert instance.integer == instance.onetoone.integer\n\n    def test_copying_from_a_self_fk(self):\n        instance = G(ModelWithRelationships, selfforeignkey=F(), integer=C('selfforeignkey.integer_b'))\n        assert instance.integer == instance.selfforeignkey.integer_b\n\n    def test_copying_inside_fk(self):\n        instance = G(ModelWithRelationships, selfforeignkey=F(selfforeignkey=F(), integer=C('selfforeignkey.integer_b')))\n        assert instance.selfforeignkey.integer == instance.selfforeignkey.selfforeignkey.integer_b\n\n    def test_copying_inside_many_to_many(self):\n        instance = G(ModelWithRelationships, manytomany=[F(integer=C('integer_b'))])\n        instance1 = instance.manytomany.all()[0]\n        assert instance1.integer == instance1.integer_b\n\n\nclass MShortcutTest(TestCase):\n    def test_full_data_mask_sample(self):\n        import re\n        instance = G(ModelWithStrings, string=M(r'St. -______, ### !- -- --'))\n        assert re.match(r'St\\. [A-Z]{1}[a-z]{6}, \\d{3} - [A-Z]{2} [A-Z]{2}', instance.string)\n\n\nclass TeachingAndLessonsTest(TestCase):\n    def test_global_lesson(self):\n        teach(ModelForLibrary, integer=1000)\n        instance = G(ModelForLibrary)\n        assert instance.integer == 1000\n\n        instance = G(ModelForLibrary, integer=1001)\n        assert instance.integer == 1001\n\n        instance = G(ModelForLibrary)\n        assert instance.integer == 1000\n\n\nclass CreatingMultipleObjectsTest(TestCase):\n    def test_new(self):\n        assert N(EmptyModel, n=0) == []\n        assert N(EmptyModel, n= -1) == []\n        assert isinstance(N(EmptyModel), EmptyModel) # default is 1\n        assert isinstance(N(EmptyModel, n=1), EmptyModel)\n        assert len(N(EmptyModel, n=2)) == 2\n\n    def test_get(self):\n        assert G(EmptyModel, n=0) == []\n        assert G(EmptyModel, n= -1) == []\n        assert isinstance(G(EmptyModel), EmptyModel) # default is 1\n        assert isinstance(G(EmptyModel, n=1), EmptyModel)\n        assert len(G(EmptyModel, n=2)) == 2\n\n\nclass LookUpSeparatorTest(TestCase):\n    def test_look_up_alias_with_all_params_combination(self):\n        assert {'a': 1} == look_up_alias(a=1, ddf_as_f=False)\n        assert {'a': 1, 'b': 2} == look_up_alias(a=1, b=2, ddf_as_f=False)\n        assert {'a': {'b': 1}} == look_up_alias(a__b=1, ddf_as_f=False)\n        assert {'a': {'b': 1}, 'c': 2} == look_up_alias(a__b=1, c=2, ddf_as_f=False)\n        assert {'a': {'b': 1}, 'c': {'d': 2}} == look_up_alias(a__b=1, c__d=2, ddf_as_f=False)\n        assert {'a': {'b': 1, 'c': 2}} == look_up_alias(a__b=1, a__c=2, ddf_as_f=False)\n        assert {'a': {'b': 1, 'c': {'d': 2}}} == look_up_alias(a__b=1, a__c__d=2, ddf_as_f=False)\n        assert {'a': {'b': 1, 'c': {'d': 2}}, 'e': {'f': 3}, 'g': 4} == look_up_alias(a__b=1, a__c__d=2, e__f=3, g=4, ddf_as_f=False)\n\n    def test_look_up_alias_as_f_with_all_params_combination(self):\n        assert {'a': 1} == look_up_alias(a=1)\n        assert {'a': 1, 'b': 2} == look_up_alias(a=1, b=2)\n        assert {'a': F(b=1)} == look_up_alias(a__b=1)\n        assert {'a': F(b=1), 'c': 2} == look_up_alias(a__b=1, c=2)\n        assert {'a': F(b=1), 'c': F(d=2)} == look_up_alias(a__b=1, c__d=2)\n        assert {'a': F(b=1, c=2)} == look_up_alias(a__b=1, a__c=2)\n        assert {'a': F(b=1, c=F(d=2))} == look_up_alias(a__b=1, a__c__d=2)\n        assert {'a': F(b=1, c=F(d=2)), 'e': F(f=3), 'g': 4} == look_up_alias(a__b=1, a__c__d=2, e__f=3, g=4)\n\n    def test_look_up_alias_with_just_one_parameter(self):\n        assert {'a': 1} == look_up_alias(a=1)\n        assert {'a': F()} == look_up_alias(a=F())\n        assert {'a_b': 1} == look_up_alias(a_b=1)\n        assert {'a': F(b=1)} == look_up_alias(a__b=1)\n        assert {'a_b': F(c=1)} == look_up_alias(a_b__c=1)\n        assert {'a': F(b=F(c=1))} == look_up_alias(a__b__c=1)\n        assert {'a_b': F(c_d=F(e_f=1))} == look_up_alias(a_b__c_d__e_f=1)\n\n    def test_look_up_alias_with_many_parameters(self):\n        assert {'a': 1, 'b': 2} == look_up_alias(a=1, b=2)\n        assert {'a': 1, 'b_c': 2} == look_up_alias(a=1, b_c=2)\n        assert {'a': 1, 'b': F(c=2)} == look_up_alias(a=1, b__c=2)\n        assert {'a': F(b=1), 'c': F(d=2)} == look_up_alias(a__b=1, c__d=2)\n\n    def test_dont_format_default_dict_values(self):\n        kwargs = dict(metadata=dict(a=1))\n        assert {'metadata': {'a': 1}} == look_up_alias(**kwargs)\n        assert {'metadata': {'a': 1}} == look_up_alias(metadata={'a': 1})\n\n\nclass PreAndPostSaveTest(TestCase):\n    def tearDown(self):\n        # Workaround to pass the tests in Travis, caused by an unknown issue\n        # with LazySettings and ALLOWED_HOSTS\n        pass\n\n    def test_pre_save(self):\n        PRE_SAVE(EmptyModel, lambda x: x)\n\n    def test_post_save(self):\n        POST_SAVE(EmptyModel, lambda x: x)\n\n\nclass UsingModelNameInsteadTest(TestCase):\n    def test_compatibility_for_new(self):\n        instance = N('django_dynamic_fixture.ModelWithNumbers', integer=5)\n        assert instance.integer == 5\n\n    def test_compatibility_for_get(self):\n        instance = G('django_dynamic_fixture.ModelWithNumbers', integer=5)\n        assert instance.integer == 5\n\n    def test_compatibility_for_teach(self):\n        teach('django_dynamic_fixture.ModelWithDefaultValues', integer_with_default=5)\n        instance = G('django_dynamic_fixture.ModelWithDefaultValues')\n        assert instance.integer_with_default == 5\n\n\nclass OverrideDataFixture(TestCase):\n    def test_random(self):\n        instance = N('django_dynamic_fixture.ModelWithNumbers', data_fixture='random')\n        assert instance is not None\n        instance = G('django_dynamic_fixture.ModelWithNumbers', data_fixture='random')\n        assert instance is not None\n\n    def test_sequential(self):\n        instance = N('django_dynamic_fixture.ModelWithNumbers', data_fixture='sequential')\n        assert instance is not None\n        instance = G('django_dynamic_fixture.ModelWithNumbers', data_fixture='sequential')\n        assert instance is not None\n\n    def test_static_sequential(self):\n        instance = N('django_dynamic_fixture.ModelWithNumbers', data_fixture='static_sequential')\n        assert instance is not None\n        instance = G('django_dynamic_fixture.ModelWithNumbers', data_fixture='static_sequential')\n        assert instance is not None\n\n    def test_custom_one(self):\n        from django_dynamic_fixture.fixture_algorithms.sequential_fixture import SequentialDataFixture\n        instance = N('django_dynamic_fixture.ModelWithNumbers', data_fixture=SequentialDataFixture())\n        assert instance is not None\n        instance = G('django_dynamic_fixture.ModelWithNumbers', data_fixture=SequentialDataFixture())\n        assert instance is not None\n\n\nclass Version(TestCase):\n    def test_version(self):\n        from django_dynamic_fixture import __version__\n        from ddf import __version__\n"
  },
  {
    "path": "docs/Makefile",
    "content": "# Makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line.\nSPHINXOPTS    =\nSPHINXBUILD   = ../env/bin/sphinx-build\nPAPER         =\nBUILDDIR      = build\n\n# User-friendly check for sphinx-build\nifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)\n$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)\nendif\n\n# Internal variables.\nPAPEROPT_a4     = -D latex_paper_size=a4\nPAPEROPT_letter = -D latex_paper_size=letter\nALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source\n# the i18n builder cannot share the environment and doctrees with the others\nI18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source\n\n.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext\n\nhelp:\n\t@echo \"Please use \\`make <target>' where <target> is one of\"\n\t@echo \"  html       to make standalone HTML files\"\n\t@echo \"  dirhtml    to make HTML files named index.html in directories\"\n\t@echo \"  singlehtml to make a single large HTML file\"\n\t@echo \"  pickle     to make pickle files\"\n\t@echo \"  json       to make JSON files\"\n\t@echo \"  htmlhelp   to make HTML files and a HTML help project\"\n\t@echo \"  qthelp     to make HTML files and a qthelp project\"\n\t@echo \"  devhelp    to make HTML files and a Devhelp project\"\n\t@echo \"  epub       to make an epub\"\n\t@echo \"  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter\"\n\t@echo \"  latexpdf   to make LaTeX files and run them through pdflatex\"\n\t@echo \"  latexpdfja to make LaTeX files and run them through platex/dvipdfmx\"\n\t@echo \"  text       to make text files\"\n\t@echo \"  man        to make manual pages\"\n\t@echo \"  texinfo    to make Texinfo files\"\n\t@echo \"  info       to make Texinfo files and run them through makeinfo\"\n\t@echo \"  gettext    to make PO message catalogs\"\n\t@echo \"  changes    to make an overview of all changed/added/deprecated items\"\n\t@echo \"  xml        to make Docutils-native XML files\"\n\t@echo \"  pseudoxml  to make pseudoxml-XML files for display purposes\"\n\t@echo \"  linkcheck  to check all external links for integrity\"\n\t@echo \"  doctest    to run all doctests embedded in the documentation (if enabled)\"\n\nclean:\n\trm -rf $(BUILDDIR)/*\n\nhtml:\n\t$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html\n\t@echo\n\t@echo \"Build finished. The HTML pages are in $(BUILDDIR)/html.\"\n\ndirhtml:\n\t$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml\n\t@echo\n\t@echo \"Build finished. The HTML pages are in $(BUILDDIR)/dirhtml.\"\n\nsinglehtml:\n\t$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml\n\t@echo\n\t@echo \"Build finished. The HTML page is in $(BUILDDIR)/singlehtml.\"\n\npickle:\n\t$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle\n\t@echo\n\t@echo \"Build finished; now you can process the pickle files.\"\n\njson:\n\t$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json\n\t@echo\n\t@echo \"Build finished; now you can process the JSON files.\"\n\nhtmlhelp:\n\t$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp\n\t@echo\n\t@echo \"Build finished; now you can run HTML Help Workshop with the\" \\\n\t      \".hhp project file in $(BUILDDIR)/htmlhelp.\"\n\nqthelp:\n\t$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp\n\t@echo\n\t@echo \"Build finished; now you can run \"qcollectiongenerator\" with the\" \\\n\t      \".qhcp project file in $(BUILDDIR)/qthelp, like this:\"\n\t@echo \"# qcollectiongenerator $(BUILDDIR)/qthelp/DDF.qhcp\"\n\t@echo \"To view the help file:\"\n\t@echo \"# assistant -collectionFile $(BUILDDIR)/qthelp/DDF.qhc\"\n\ndevhelp:\n\t$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp\n\t@echo\n\t@echo \"Build finished.\"\n\t@echo \"To view the help file:\"\n\t@echo \"# mkdir -p $$HOME/.local/share/devhelp/DDF\"\n\t@echo \"# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/DDF\"\n\t@echo \"# devhelp\"\n\nepub:\n\t$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub\n\t@echo\n\t@echo \"Build finished. The epub file is in $(BUILDDIR)/epub.\"\n\nlatex:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo\n\t@echo \"Build finished; the LaTeX files are in $(BUILDDIR)/latex.\"\n\t@echo \"Run \\`make' in that directory to run these through (pdf)latex\" \\\n\t      \"(use \\`make latexpdf' here to do that automatically).\"\n\nlatexpdf:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo \"Running LaTeX files through pdflatex...\"\n\t$(MAKE) -C $(BUILDDIR)/latex all-pdf\n\t@echo \"pdflatex finished; the PDF files are in $(BUILDDIR)/latex.\"\n\nlatexpdfja:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo \"Running LaTeX files through platex and dvipdfmx...\"\n\t$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja\n\t@echo \"pdflatex finished; the PDF files are in $(BUILDDIR)/latex.\"\n\ntext:\n\t$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text\n\t@echo\n\t@echo \"Build finished. The text files are in $(BUILDDIR)/text.\"\n\nman:\n\t$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man\n\t@echo\n\t@echo \"Build finished. The manual pages are in $(BUILDDIR)/man.\"\n\ntexinfo:\n\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo\n\t@echo\n\t@echo \"Build finished. The Texinfo files are in $(BUILDDIR)/texinfo.\"\n\t@echo \"Run \\`make' in that directory to run these through makeinfo\" \\\n\t      \"(use \\`make info' here to do that automatically).\"\n\ninfo:\n\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo\n\t@echo \"Running Texinfo files through makeinfo...\"\n\tmake -C $(BUILDDIR)/texinfo info\n\t@echo \"makeinfo finished; the Info files are in $(BUILDDIR)/texinfo.\"\n\ngettext:\n\t$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale\n\t@echo\n\t@echo \"Build finished. The message catalogs are in $(BUILDDIR)/locale.\"\n\nchanges:\n\t$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes\n\t@echo\n\t@echo \"The overview file is in $(BUILDDIR)/changes.\"\n\nlinkcheck:\n\t$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck\n\t@echo\n\t@echo \"Link check complete; look for any errors in the above output \" \\\n\t      \"or in $(BUILDDIR)/linkcheck/output.txt.\"\n\ndoctest:\n\t$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest\n\t@echo \"Testing of doctests in the sources finished, look at the \" \\\n\t      \"results in $(BUILDDIR)/doctest/output.txt.\"\n\nxml:\n\t$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml\n\t@echo\n\t@echo \"Build finished. The XML files are in $(BUILDDIR)/xml.\"\n\npseudoxml:\n\t$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml\n\t@echo\n\t@echo \"Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml.\"\n"
  },
  {
    "path": "docs/source/_static/coverage.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n    <title>Coverage report</title>\n    <link rel=\"icon\" sizes=\"32x32\" href=\"favicon_32.png\">\n    <link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n    <script type=\"text/javascript\" src=\"coverage_html.js\" defer></script>\n</head>\n<body class=\"indexfile\">\n<header>\n    <div class=\"content\">\n        <h1>Coverage report:\n            <span class=\"pc_cov\">92%</span>\n        </h1>\n        <aside id=\"help_panel_wrapper\">\n            <input id=\"help_panel_state\" type=\"checkbox\">\n            <label for=\"help_panel_state\">\n                <img id=\"keyboard_icon\" src=\"keybd_closed.png\" alt=\"Show/hide keyboard shortcuts\" />\n            </label>\n            <div id=\"help_panel\">\n                <p class=\"legend\">Shortcuts on this page</p>\n                <div class=\"keyhelp\">\n                    <p>\n                        <kbd>n</kbd>\n                        <kbd>s</kbd>\n                        <kbd>m</kbd>\n                        <kbd>x</kbd>\n                        <kbd>c</kbd>\n                        &nbsp; change column sorting\n                    </p>\n                    <p>\n                        <kbd>[</kbd>\n                        <kbd>]</kbd>\n                        &nbsp; prev/next file\n                    </p>\n                    <p>\n                        <kbd>?</kbd> &nbsp; show/hide this help\n                    </p>\n                </div>\n            </div>\n        </aside>\n        <form id=\"filter_container\">\n            <input id=\"filter\" type=\"text\" value=\"\" placeholder=\"filter...\" />\n        </form>\n        <p class=\"text\">\n            <a class=\"nav\" href=\"https://coverage.readthedocs.io/en/7.3.0\">coverage.py v7.3.0</a>,\n            created at 2023-09-15 17:34 -0500\n        </p>\n    </div>\n</header>\n<main id=\"index\">\n    <table class=\"index\" data-sortable>\n        <thead>\n            <tr class=\"tablehead\" title=\"Click to sort\">\n                <th class=\"name left\" aria-sort=\"none\" data-shortcut=\"n\">Module</th>\n                <th aria-sort=\"none\" data-default-sort-order=\"descending\" data-shortcut=\"s\">statements</th>\n                <th aria-sort=\"none\" data-default-sort-order=\"descending\" data-shortcut=\"m\">missing</th>\n                <th aria-sort=\"none\" data-default-sort-order=\"descending\" data-shortcut=\"x\">excluded</th>\n                <th class=\"right\" aria-sort=\"none\" data-shortcut=\"c\">coverage</th>\n            </tr>\n        </thead>\n        <tbody>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_194004471fb5367f___init___py.html\">django_dynamic_fixture/__init__.py</a></td>\n                <td>91</td>\n                <td>2</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"89 91\">98%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_194004471fb5367f_ddf_py.html\">django_dynamic_fixture/ddf.py</a></td>\n                <td>405</td>\n                <td>36</td>\n                <td>9</td>\n                <td class=\"right\" data-ratio=\"369 405\">91%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_194004471fb5367f_decorators_py.html\">django_dynamic_fixture/decorators.py</a></td>\n                <td>21</td>\n                <td>0</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"21 21\">100%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_194004471fb5367f_django_helper_py.html\">django_dynamic_fixture/django_helper.py</a></td>\n                <td>133</td>\n                <td>16</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"117 133\">88%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_194004471fb5367f_fdf_py.html\">django_dynamic_fixture/fdf.py</a></td>\n                <td>128</td>\n                <td>13</td>\n                <td>2</td>\n                <td class=\"right\" data-ratio=\"115 128\">90%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_194004471fb5367f_fields_py.html\">django_dynamic_fixture/fields.py</a></td>\n                <td>34</td>\n                <td>13</td>\n                <td>5</td>\n                <td class=\"right\" data-ratio=\"21 34\">62%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_745a1b59d8af1d7f___init___py.html\">django_dynamic_fixture/fixture_algorithms/__init__.py</a></td>\n                <td>12</td>\n                <td>0</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"12 12\">100%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_745a1b59d8af1d7f_default_fixture_py.html\">django_dynamic_fixture/fixture_algorithms/default_fixture.py</a></td>\n                <td>59</td>\n                <td>22</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"37 59\">63%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_745a1b59d8af1d7f_random_fixture_py.html\">django_dynamic_fixture/fixture_algorithms/random_fixture.py</a></td>\n                <td>77</td>\n                <td>6</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"71 77\">92%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_745a1b59d8af1d7f_sequential_fixture_py.html\">django_dynamic_fixture/fixture_algorithms/sequential_fixture.py</a></td>\n                <td>105</td>\n                <td>7</td>\n                <td>6</td>\n                <td class=\"right\" data-ratio=\"98 105\">93%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_cae8023b4e3b30dc___init___py.html\">django_dynamic_fixture/fixture_algorithms/tests/__init__.py</a></td>\n                <td>0</td>\n                <td>0</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"0 0\">100%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_cae8023b4e3b30dc_abstract_test_generic_fixture_py.html\">django_dynamic_fixture/fixture_algorithms/tests/abstract_test_generic_fixture.py</a></td>\n                <td>47</td>\n                <td>2</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"45 47\">96%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_cae8023b4e3b30dc_test_default_fixture_py.html\">django_dynamic_fixture/fixture_algorithms/tests/test_default_fixture.py</a></td>\n                <td>39</td>\n                <td>23</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"16 39\">41%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_cae8023b4e3b30dc_test_default_fixture_postgres_py.html\">django_dynamic_fixture/fixture_algorithms/tests/test_default_fixture_postgres.py</a></td>\n                <td>49</td>\n                <td>2</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"47 49\">96%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_cae8023b4e3b30dc_test_random_fixture_py.html\">django_dynamic_fixture/fixture_algorithms/tests/test_random_fixture.py</a></td>\n                <td>6</td>\n                <td>0</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"6 6\">100%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_cae8023b4e3b30dc_test_sequential_fixture_py.html\">django_dynamic_fixture/fixture_algorithms/tests/test_sequential_fixture.py</a></td>\n                <td>32</td>\n                <td>0</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"32 32\">100%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_cae8023b4e3b30dc_test_unique_random_fixture_py.html\">django_dynamic_fixture/fixture_algorithms/tests/test_unique_random_fixture.py</a></td>\n                <td>39</td>\n                <td>0</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"39 39\">100%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_745a1b59d8af1d7f_unique_random_fixture_py.html\">django_dynamic_fixture/fixture_algorithms/unique_random_fixture.py</a></td>\n                <td>116</td>\n                <td>13</td>\n                <td>3</td>\n                <td class=\"right\" data-ratio=\"103 116\">89%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_194004471fb5367f_global_settings_py.html\">django_dynamic_fixture/global_settings.py</a></td>\n                <td>49</td>\n                <td>3</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"46 49\">94%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_194004471fb5367f_models_py.html\">django_dynamic_fixture/models.py</a></td>\n                <td>4</td>\n                <td>0</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"4 4\">100%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_194004471fb5367f_models_sample_app_py.html\">django_dynamic_fixture/models_sample_app.py</a></td>\n                <td>25</td>\n                <td>0</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"25 25\">100%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_194004471fb5367f_models_test_py.html\">django_dynamic_fixture/models_test.py</a></td>\n                <td>291</td>\n                <td>13</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"278 291\">96%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_194004471fb5367f_models_third_party_py.html\">django_dynamic_fixture/models_third_party.py</a></td>\n                <td>43</td>\n                <td>14</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"29 43\">67%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_194004471fb5367f_script_ddf_checkings_py.html\">django_dynamic_fixture/script_ddf_checkings.py</a></td>\n                <td>60</td>\n                <td>20</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"40 60\">67%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_2810ef72909b6803___init___py.html\">django_dynamic_fixture/tests/__init__.py</a></td>\n                <td>0</td>\n                <td>0</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"0 0\">100%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_2810ef72909b6803_conftest_py.html\">django_dynamic_fixture/tests/conftest.py</a></td>\n                <td>13</td>\n                <td>2</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"11 13\">85%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_2810ef72909b6803_test_ddf_py.html\">django_dynamic_fixture/tests/test_ddf.py</a></td>\n                <td>390</td>\n                <td>7</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"383 390\">98%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_2810ef72909b6803_test_ddf_checkings_py.html\">django_dynamic_fixture/tests/test_ddf_checkings.py</a></td>\n                <td>22</td>\n                <td>0</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"22 22\">100%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_2810ef72909b6803_test_ddf_copier_py.html\">django_dynamic_fixture/tests/test_ddf_copier.py</a></td>\n                <td>52</td>\n                <td>0</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"52 52\">100%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_2810ef72909b6803_test_ddf_custom_fields_py.html\">django_dynamic_fixture/tests/test_ddf_custom_fields.py</a></td>\n                <td>95</td>\n                <td>25</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"70 95\">74%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_2810ef72909b6803_test_ddf_custom_models_py.html\">django_dynamic_fixture/tests/test_ddf_custom_models.py</a></td>\n                <td>19</td>\n                <td>2</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"17 19\">89%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_2810ef72909b6803_test_ddf_geo_py.html\">django_dynamic_fixture/tests/test_ddf_geo.py</a></td>\n                <td>31</td>\n                <td>12</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"19 31\">61%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_2810ef72909b6803_test_ddf_signals_py.html\">django_dynamic_fixture/tests/test_ddf_signals.py</a></td>\n                <td>76</td>\n                <td>4</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"72 76\">95%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_2810ef72909b6803_test_ddf_teaching_and_lessons_py.html\">django_dynamic_fixture/tests/test_ddf_teaching_and_lessons.py</a></td>\n                <td>158</td>\n                <td>0</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"158 158\">100%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_2810ef72909b6803_test_decorators_py.html\">django_dynamic_fixture/tests/test_decorators.py</a></td>\n                <td>33</td>\n                <td>0</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"33 33\">100%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_2810ef72909b6803_test_django_helper_py.html\">django_dynamic_fixture/tests/test_django_helper.py</a></td>\n                <td>159</td>\n                <td>0</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"159 159\">100%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_2810ef72909b6803_test_fdf_py.html\">django_dynamic_fixture/tests/test_fdf.py</a></td>\n                <td>134</td>\n                <td>0</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"134 134\">100%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_2810ef72909b6803_test_global_settings_py.html\">django_dynamic_fixture/tests/test_global_settings.py</a></td>\n                <td>86</td>\n                <td>0</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"86 86\">100%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_2810ef72909b6803_test_mask_py.html\">django_dynamic_fixture/tests/test_mask.py</a></td>\n                <td>31</td>\n                <td>0</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"31 31\">100%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_2810ef72909b6803_test_module_ddf_shortcut_py.html\">django_dynamic_fixture/tests/test_module_ddf_shortcut.py</a></td>\n                <td>7</td>\n                <td>2</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"5 7\">71%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_2810ef72909b6803_test_sample_app_py.html\">django_dynamic_fixture/tests/test_sample_app.py</a></td>\n                <td>46</td>\n                <td>0</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"46 46\">100%</td>\n            </tr>\n            <tr class=\"file\">\n                <td class=\"name left\"><a href=\"d_2810ef72909b6803_test_wrappers_py.html\">django_dynamic_fixture/tests/test_wrappers.py</a></td>\n                <td>203</td>\n                <td>4</td>\n                <td>0</td>\n                <td class=\"right\" data-ratio=\"199 203\">98%</td>\n            </tr>\n        </tbody>\n        <tfoot>\n            <tr class=\"total\">\n                <td class=\"name left\">Total</td>\n                <td>3420</td>\n                <td>263</td>\n                <td>25</td>\n                <td class=\"right\" data-ratio=\"3157 3420\">92%</td>\n            </tr>\n        </tfoot>\n    </table>\n    <p id=\"no_rows\">\n        No items found using the specified filter.\n    </p>\n</main>\n<footer>\n    <div class=\"content\">\n        <p>\n            <a class=\"nav\" href=\"https://coverage.readthedocs.io/en/7.3.0\">coverage.py v7.3.0</a>,\n            created at 2023-09-15 17:34 -0500\n        </p>\n    </div>\n    <aside class=\"hidden\">\n        <a id=\"prevFileLink\" class=\"nav\" href=\"d_2810ef72909b6803_test_wrappers_py.html\"/>\n        <a id=\"nextFileLink\" class=\"nav\" href=\"d_194004471fb5367f___init___py.html\"/>\n        <button type=\"button\" class=\"button_prev_file\" data-shortcut=\"[\"/>\n        <button type=\"button\" class=\"button_next_file\" data-shortcut=\"]\"/>\n        <button type=\"button\" class=\"button_show_hide_help\" data-shortcut=\"?\"/>\n    </aside>\n</footer>\n</body>\n</html>\n"
  },
  {
    "path": "docs/source/about.rst",
    "content": ".. about:\n\nAbout\n*******************************************************************************\n\n.. contents::\n   :local:\n\n\nCollaborators\n===============================================================================\n\n* Paulo Cheque <https://paulocheque.codeart.io> <https://github.com/paulocheque> - Master Dissertation about Automated Test Patterns: https://teses.usp.br/teses/disponiveis/45/45134/tde-02042012-120707/pt-br.php\n* Valder Gallo <http://valdergallo.com.br> <https://github.com/valdergallo>\n* Julio Netto <http://www.inerciasensorial.com.br> <https://bitbucket.org/inerte>\n\n\nPull Requests tips\n===============================================================================\n\nAbout commit messages\n-------------------------------------------------------------------------------\n\n* Messages in english only\n* All messages have to follow the pattern: \"[TAG] message\"\n* TAG have to be one of the following: new, update, bugfix, delete, refactoring, config, log, doc, mergefix\n\nAbout the code\n-------------------------------------------------------------------------------\n\n* One change (new feature, update, refactoring, bugfix etc) by commit\n* All bugfix must have a test simulating the bug\n* All commit must have 100% of test coverage\n\nRunning tests\n-------------------------------------------------------------------------------\n\nCommand::\n\n    python manage.py test --with-coverage --cover-inclusive --cover-html --cover-package=django_dynamic_fixture.* --with-queries --with-ddf-setup\n\nTODO list\n===============================================================================\n\nTests and Bugfixes\n-------------------------------------------------------------------------------\n* with_queries bugfixes (always print 0 queries)\n* Deal with relationships with dynamic related_name\n* bugfix in fdf or ddf: some files/directories are not deleted\n* tests with files in ddf\n* tests with proxy models\n* tests with GenericRelations, GenericForeignKey etc\n* more tests with OneToOneField(parent_link=True)\n\nFeatures\n-------------------------------------------------------------------------------\n* auto config of denormalizated fields\n* related_name documentation or workaround\n* today, yesterday, tomorrow on fdf\n* string generation according to a regular expression\n\nDocumentation\n-------------------------------------------------------------------------------\n* with_queries documentation\n* example to generate models with validators in fields or in clean methods\n\nExternal references\n===============================================================================\n\n  * http://stackoverflow.com/search?q=django+dynamic+fixture\n  * http://stackoverflow.com/questions/12487337/optimizing-setup-and-teardown-for-sample-django-model-using-django-nose-and-djan\n  * http://stackoverflow.com/questions/4400609/initial-data-fixture-management-in-django\n\n\nRunning tests locally\n===============================================================================\n\nInstall GDAL: https://docs.djangoproject.com/en/1.11/ref/contrib/gis/install/geolibs/#gdal\n\nCommands::\n\n    make build\n    make tox\n"
  },
  {
    "path": "docs/source/change_log.rst",
    "content": ".. about:\n\nChange Log\n*******************************************************************************\n\n.. contents::\n   :local:\n\nDate format: yyyy/mm/dd\n\nVersion 4.0.1 - 2023/09/15\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/4.0.1>\n  * Reuse lessons in Proxy models\n  * https://github.com/paulocheque/django-dynamic-fixture/pull/161\n\nVersion 4.0.0 - 2023/08/26\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/4.0.0>\n  * Removed compatibilty of Python 2\n  * Removed compatibilty of Django 3 or lower\n  * Removed Nose plugins\n  * Removed Coveralls integration\n\nVersion 3.1.3 - 2023/08/18\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/3.1.3>\n  * Removed deprecation warnings: PR #150\n  * Fixed doc typos: PR #151\n  * Allow Mask objects as lessons for unique fields: PR #153\n\nVersion 3.1.2 - 2021/10/01\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/3.1.2>\n  * Correct type for TimeField: PR #139\n  * Catch Django 3.2 TypeError instantiating abstracts: PR #142\n  * ci: update tox.ini and travis.yml to test Django3.1/3.2: PR #143\n\nVersion 3.1.1 - 2020/11/17\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/3.1.1>\n  * Fixed importing FieldDoesNotExist exception class for Django==3.1: PR #134\n\nVersion 3.1.0 - 2020/03/29\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/3.1.0>\n  * Compatibility check report improvements: PR #131\n  * DDF now accepts to override a DDF lesson: PR #130\n  * New feature: DDF Mask: ``M``: PR #129\n  * Option to configure DDF via Environment variables\n\nVersion 3.0.3 - 2020/03/01\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/3.0.3>\n  * Setting ``DDF_NUMBER_OF_LAPS`` was removed in favor of the new ``DDF_FK_MIN_DEPTH``\n  * Parameter ``number_of_laps`` was removed in favor of new ``fk_min_depth``\n  * Important bugfix for the FK field management: Issue #120\n  * Give priority to default values instead of null values: Issue #121\n  * Fixed lookup fields that was breaking JSONFields: Issue #122\n\nVersion 3.0.2 - 2020/01/10\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/3.0.2>\n  * Changed ``VERSION`` to ``__version__``: ``from ddf import __version``\n  * Changed ``lesson`` to ``ddf_lesson``:  ``G(Model, ddf_lesson='...')``\n\nVersion 3.0.1 - 2020/01/07\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/3.0.1>\n  * Fixed importing ``from ddf import ddf_check_models``\n  * Added a CSV report for the ddf_check_models\n  * Added the VERSION property in ddf: ``from ddf import VERSION``\n\nVersion 3.0.0 - 2020/01/05\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/3.0.0>\n  * New ``teach`` method that replaced the old ``shelve=True``.\n  * Support to ``app_label.ModelName`` strings instead of the model class.\n  * New ``ddf`` shortcut: ``from ddf import G, N, C, P, teach``.\n  * Support for **Django 3.0.0**.\n  * New ``ddf_check_models`` method to print a compatibility report.\n  * Added Python 3 Type Hints.\n  * Added native support for the ``Postgres.JSONField``.\n  * Added native support for Django-Polymorphic models.\n  * Bugfix for the ``data_fixture`` parameter to accept string alias.\n  * Another small bugfixes with ``choices`` parameter.\n  * Many internal refactorings.\n  * Travis/Tests integration fixed.\n  * Documentation organised, updated and simplified.\n  * Changed the default value of the ``persist_dependencies`` in ``N`` from True to False.\n  * DDF_USE_LIBRARY settings removed. Now, it is always activated by default.\n  * DDF_VALIDATE_ARGS settings removed. Now, it is always activated by default.\n  * DDF_FILL_NULLABLE_FIELDS default changed from True to False\n  * DDF_NUMBER_OF_LAPS default changed from 1 to 0\n  * Bugfix for named primary keys.\n\nVersion 2.0.0 - 2017/12/08\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/2.0.0>\n  * `DDF_IGNORE_FIELDS` globally for all new instances\n  * Bugfix for auto generated `_ptr` fields.\n  * Support for Django 2.0.0.\n\nVersion 1.9.5 - 2017/05/09\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.9.5>\n  * Bugfix: avoid GDALException on Django 1.11\n\nVersion 1.9.4 - 2017/04/17\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.9.4>\n  * Added support for django.contrib.postgres.fields.ArrayField field\n  * Fixed GeoDjango Point instantiation.\n\nVersion 1.9.3 - 2017/03/08\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.9.3>\n  * Improve compatibility for the DDF internal tests\n\nVersion 1.9.2 - 2017/03/08\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.9.2>\n  * Django 2.0 compatibility\n  * New: Support for wildcards `?` and `*` in the ignore fields\n  * Bugfix: Fixed DDF_TEST_GEODJANGO test issues\n\nVersion 1.9.1 - 2016/12/21\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.9.1>\n  * Bugfix: Django version parser\n  * Bugfix: NameError on invalid variable name\n\nVersion 1.9.0 - 2016/05/23\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.9.0>\n  * [New] Django 1.9 support\n  * [Bugfix] Fixed issue on ForeignKey field with default id\n  * [Bugfix] Fixed issue with SimpleUploadedFile\n\nVersion 1.8.4 - 2015/05/26\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.8.4>\n  * [New] UUIDField support\n  * [New] GeoDjango fields support (GeometryField, PointField, LineStringField, PolygonField, MultiPointField, MultiLineStringField, MultiPolygonField, GeometryCollectionField)\n  * [Update] Better error messages\n  * [Bugfix] BinaryField fixture fix\n  * [Update] Optimizations\n\n\nVersion 1.8.3 - 2015/05\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.8.3>\n  * [Update] No more deprecated methods\n\n\nVersion 1.8.2 - 2015/05\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.8.2>\n  * [New] Support for Django 1.8\n\n\nVersion 1.8.1 - 2014/12\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.8.1>\n  * [Update] Avoid conflicts with \"instance\" and \"field\" model field names.\n\nVersion 1.8.0 - 2014/09\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.8.0>\n  * [New] DDF_FIELD_FIXTURES global settings. You can include support of other fields here.\n  * [New] Support for BinaryField\n  * [Update] Django 1.7, Python 3.4 and Pypy official suppport (fixed some tests)\n  * [New] ReadTheDocs full documentation\n  * [Update] Fixed some print calls for python 3\n  * [Update] Nose plugin disable as default. Recommended behavior of nose plugins.\n  * [Update] ignore_fields parameter does not consider fields explicitly defined by the developer.\n  * [Update] Travis env using Tox\n\nVersion 1.7.0 - 2014/03/26\n-------------------------------------------------------------------------------\n\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.7.0>\n\nVersion 1.6.4 - 2012/12/30\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.6.4>\n  * [Bugfix] auto_now and auto_now_add must not be disabled forever (thanks for reporting)\n  * [New] Added global_sequential data fixture (Pull request, thanks)\n\nVersion 1.6.3 - 2012/04/10\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.6.3>\n  * [New] Pre save and post save special signals\n\nVersion 1.6.2 - 2012/04/09\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.6.2>\n  * [New] Debug Mode and option (global/local) to enable/disable debug mode\n\nVersion 1.6.1 - 2012/04/07\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.6.1>\n  * [New] New alias for F: field1__field2=value instead of field1=F(field2=value)\n  * [New] Named shelves inherit from default shelve\n\nVersion 1.6.0 - 2012/03/31\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.6.0>\n  * [New] Copier: option to copy a generated value for a field to another one. Useful for denormalizated fields.\n  * [New] Shelve/Library: option to store a default configuration of a specific model. Useful to avoid replicated code of fixtures. Global option: DDF_USE_LIBRARY.\n  * [New] Named Shelve: option to store multiple configurations for a model in the library.\n  * [New] Nose plugin for global set up.\n  * [New] P function now accept a queryset.\n\nVersion 1.5.1 - 2012/03/26\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.5.0>\n  * [New] global option: DDF_VALIDATE_ARGS that enable or disable field names.\n  * [Bugfix] F feature stop working.\n\nVersion 1.5.0 - 2012/03/25\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.5.0>\n  * [New] global settings: DDF_DEFAULT_DATA_FIXTURE, DDF_FILL_NULLABLE_FIELDS, DDF_IGNORE_FIELDS, DDF_NUMBER_OF_LAPS, DDF_VALIDATE_MODELS\n  * [New] new data fixture that generates random data\n  * [New] new data fixture that use sequential numbers only for fields that have unique=True\n  * [New] P function now accept a list of model instances\n  * [New] Option to call model_instance.full_clean() validation method before saving the object (DDF_VALIDATE_MODELS).\n  * [New] Validate field names. If a invalid field name is passed as argument, it will raise an InvalidConfigurationError exception.\n  * [Bugfix] DateField options 'auto_add_now' and 'auto_add' are disabled if a custom value is used.\n\nVersion 1.4.3 - 2012/02/23\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.4.3>\n  * [Bugfix] Bugfix in ForeignKeys with default values\n\nVersion 1.4.2 - 2011/11/07\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.4.2>\n  * [Bugfix] Bugfix in FileSystemDjangoTestCase\n\nVersion 1.4.1 - 2011/11/07\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.4.1>\n  * [New] Now you can set a custom File to a FileField and the file will be saved in the file storage system.\n  * **FileSystemDjangoTestCase**:\n  * [New] create_django_file_using_file create a django.File using the content of your file\n  * [New] create_django_file_with_temp_file now accepts a content attribute that will be saved in the generated file\n  * [Bugfix] now create_django_file_with_temp_file close the generated file\n\nVersion 1.4.0 - 2011/10/29\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.4.0>\n  * [New] Nose plugin to count queries on each test\n  * [New] Command line to count queries on the save (insert and update) of each model\n  * [Update] Field with choice and default must use the default value, not the first choice value\n  * [Update] Validation if the class is a models.Model instance\n  * [Update] Showing all stack trace, when an exception occurs\n\n  * **Decorators**:\n  * [Bugfix] default values of database engines were not used correctly\n  * **FileSystemDjangoTestCase**:\n  * [Testfix] Fixing tests\n\nVersion 1.3.1 - 2011/10/03\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.3.1>\n  * [Bugfix] Bugfixes in FileSystemDjangoTestCase\n\nVersion 1.3.0 - 2011/10/03\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.3.0>\n  * [New] File System Django Test Case\n  * [New] Decorators skip_for_database and only_for_database\n  * [Bugfix] Inheritance problems, before this version the DDF filled fields with the attribute parent_link\n\nVersion 1.2.3 - 2011/06/27\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.2.3>\n  * [Bugfix] string truncation to max_length\n\nVersion 1.2.2 - 2011/05/05\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.2.2>\n  * [Update] Improvements in exception messages\n\nVersion 1.2.1 - 2011/03/11\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.2.1>\n  * [Bugfix] Propagate ignored fields to self references\n  * [Refact] Refactoring\n\nVersion 1.2 - 2011/03/04\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.2>\n  * [New] ignore_fields\n  * [New] now it is possible to set the ID\n\nVersion 1.1\n-------------------------------------------------------------------------------\n  * <http://pypi.python.org/pypi/django-dynamic-fixture/1.0> (1.0 has the 1.1 package)\n  * [Bugfix] Bug fixes for 1.0\n\nVersion 1.0\n-------------------------------------------------------------------------------\n  * Initial version\n  * Ready to use in big projects\n"
  },
  {
    "path": "docs/source/conf.py",
    "content": "#\n# DDF documentation build configuration file, created by\n# sphinx-quickstart on Mon Sep  1 18:20:45 2014.\n#\n# This file is execfile()d with the current directory set to its\n# containing dir.\n#\n# Note that not all possible configuration values are present in this\n# autogenerated file.\n#\n# All configuration values have a default; values that are commented out\n# serve to show the default.\n\nimport sys\nimport os\n\n# If extensions (or modules to document with autodoc) are in another directory,\n# add these directories to sys.path here. If the directory is relative to the\n# documentation root, use os.path.abspath to make it absolute, like shown here.\n#sys.path.insert(0, os.path.abspath('.'))\n\n# -- General configuration ------------------------------------------------\n\n# If your documentation needs a minimal Sphinx version, state it here.\n#needs_sphinx = '1.0'\n\n# Add any Sphinx extension module names here, as strings. They can be\n# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom\n# ones.\nextensions = [\n    'sphinx.ext.todo',\n]\n\n# Add any paths that contain templates here, relative to this directory.\ntemplates_path = ['_templates']\n\n# The suffix of source filenames.\nsource_suffix = '.rst'\n\n# The encoding of source files.\n#source_encoding = 'utf-8-sig'\n\n# The master toctree document.\nmaster_doc = 'index'\n\n# General information about the project.\nproject = 'DDF'\ncopyright = '2014, Paulo Cheque'\n\n# The version info for the project you're documenting, acts as replacement for\n# |version| and |release|, also used in various other places throughout the\n# built documents.\n#\n# The short X.Y version.\nversion = '4.0.1'\n# The full version, including alpha/beta/rc tags.\nrelease = '4.0.1'\n\n# The language for content autogenerated by Sphinx. Refer to documentation\n# for a list of supported languages.\n#language = None\n\n# There are two options for replacing |today|: either, you set today to some\n# non-false value, then it is used:\n#today = ''\n# Else, today_fmt is used as the format for a strftime call.\n#today_fmt = '%B %d, %Y'\n\n# List of patterns, relative to source directory, that match files and\n# directories to ignore when looking for source files.\nexclude_patterns = []\n\n# The reST default role (used for this markup: `text`) to use for all\n# documents.\n#default_role = None\n\n# If true, '()' will be appended to :func: etc. cross-reference text.\n#add_function_parentheses = True\n\n# If true, the current module name will be prepended to all description\n# unit titles (such as .. function::).\n#add_module_names = True\n\n# If true, sectionauthor and moduleauthor directives will be shown in the\n# output. They are ignored by default.\n#show_authors = False\n\n# The name of the Pygments (syntax highlighting) style to use.\npygments_style = 'sphinx'\n\n# A list of ignored prefixes for module index sorting.\n#modindex_common_prefix = []\n\n# If true, keep warnings as \"system message\" paragraphs in the built documents.\n#keep_warnings = False\n\n\n# -- Options for HTML output ----------------------------------------------\n\n# The theme to use for HTML and HTML Help pages.  See the documentation for\n# a list of builtin themes.\nhtml_theme = 'default'\n\nimport sphinx_rtd_theme\nhtml_theme = 'sphinx_rtd_theme'\nhtml_theme_path = [sphinx_rtd_theme.get_html_theme_path()]\n\n# Theme options are theme-specific and customize the look and feel of a theme\n# further.  For a list of options available for each theme, see the\n# documentation.\n#html_theme_options = {}\n\n# Add any paths that contain custom themes here, relative to this directory.\n#html_theme_path = []\n\n# The name for this set of Sphinx documents.  If None, it defaults to\n# \"<project> v<release> documentation\".\n#html_title = None\n\n# A shorter title for the navigation bar.  Default is the same as html_title.\n#html_short_title = None\n\n# The name of an image file (relative to this directory) to place at the top\n# of the sidebar.\n#html_logo = None\n\n# The name of an image file (within the static path) to use as favicon of the\n# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32\n# pixels large.\n#html_favicon = None\n\n# Add any paths that contain custom static files (such as style sheets) here,\n# relative to this directory. They are copied after the builtin static files,\n# so a file named \"default.css\" will overwrite the builtin \"default.css\".\nhtml_static_path = ['_static']\n\n# Add any extra paths that contain custom files (such as robots.txt or\n# .htaccess) here, relative to this directory. These files are copied\n# directly to the root of the documentation.\n#html_extra_path = []\n\n# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,\n# using the given strftime format.\n#html_last_updated_fmt = '%b %d, %Y'\n\n# If true, SmartyPants will be used to convert quotes and dashes to\n# typographically correct entities.\n#html_use_smartypants = True\n\n# Custom sidebar templates, maps document names to template names.\n#html_sidebars = {}\n\n# Additional templates that should be rendered to pages, maps page names to\n# template names.\n#html_additional_pages = {}\n\n# If false, no module index is generated.\n#html_domain_indices = True\n\n# If false, no index is generated.\n#html_use_index = True\n\n# If true, the index is split into individual pages for each letter.\n#html_split_index = False\n\n# If true, links to the reST sources are added to the pages.\n#html_show_sourcelink = True\n\n# If true, \"Created using Sphinx\" is shown in the HTML footer. Default is True.\n#html_show_sphinx = True\n\n# If true, \"(C) Copyright ...\" is shown in the HTML footer. Default is True.\n#html_show_copyright = True\n\n# If true, an OpenSearch description file will be output, and all pages will\n# contain a <link> tag referring to it.  The value of this option must be the\n# base URL from which the finished HTML is served.\n#html_use_opensearch = ''\n\n# This is the file name suffix for HTML files (e.g. \".xhtml\").\n#html_file_suffix = None\n\n# Output file base name for HTML help builder.\nhtmlhelp_basename = 'DDFdoc'\n\n\n# -- Options for LaTeX output ---------------------------------------------\n\nlatex_elements = {\n# The paper size ('letterpaper' or 'a4paper').\n#'papersize': 'letterpaper',\n\n# The font size ('10pt', '11pt' or '12pt').\n#'pointsize': '10pt',\n\n# Additional stuff for the LaTeX preamble.\n#'preamble': '',\n}\n\n# Grouping the document tree into LaTeX files. List of tuples\n# (source start file, target name, title,\n#  author, documentclass [howto, manual, or own class]).\nlatex_documents = [\n  ('index', 'DDF.tex', 'DDF Documentation',\n   'Paulo Cheque', 'manual'),\n]\n\n# The name of an image file (relative to this directory) to place at the top of\n# the title page.\n#latex_logo = None\n\n# For \"manual\" documents, if this is true, then toplevel headings are parts,\n# not chapters.\n#latex_use_parts = False\n\n# If true, show page references after internal links.\n#latex_show_pagerefs = False\n\n# If true, show URL addresses after external links.\n#latex_show_urls = False\n\n# Documents to append as an appendix to all manuals.\n#latex_appendices = []\n\n# If false, no module index is generated.\n#latex_domain_indices = True\n\n\n# -- Options for manual page output ---------------------------------------\n\n# One entry per manual page. List of tuples\n# (source start file, name, description, authors, manual section).\nman_pages = [\n    ('index', 'ddf', 'DDF Documentation',\n     ['Paulo Cheque'], 1)\n]\n\n# If true, show URL addresses after external links.\n#man_show_urls = False\n\n\n# -- Options for Texinfo output -------------------------------------------\n\n# Grouping the document tree into Texinfo files. List of tuples\n# (source start file, target name, title, author,\n#  dir menu entry, description, category)\ntexinfo_documents = [\n  ('index', 'DDF', 'DDF Documentation',\n   'Paulo Cheque', 'DDF', 'One line description of project.',\n   'Miscellaneous'),\n]\n\n# Documents to append as an appendix to all manuals.\n#texinfo_appendices = []\n\n# If false, no module index is generated.\n#texinfo_domain_indices = True\n\n# How to display URL addresses: 'footnote', 'no', or 'inline'.\n#texinfo_show_urls = 'footnote'\n\n# If true, do not generate a @detailmenu in the \"Top\" node's menu.\n#texinfo_no_detailmenu = False\n"
  },
  {
    "path": "docs/source/data.rst",
    "content": ".. _data:\n\nField Data Generation\n*******************************************************************************\n\n.. contents::\n   :local:\n\nSupported Fields\n===============================================================================\n\n* **Numbers**: IntegerField, SmallIntegerField, PositiveIntegerField, PositiveSmallIntegerField, BigIntegerField, FloatField,DecimalField\n\n* **Strings**: CharField, TextField, SlugField, CommaSeparatedintegerField\n\n* **Booleans**: BooleanField, NullBooleanField\n\n* **Timestamps**: DateField, TimeField, DatetimeField\n\n* **Utilities**: EmailField, UrlField, IPAddressField, GenericIPAddressField, XMLField, UUIDField\n\n* **Files**: FilePathField, FileField, ImageField\n\n* **Binary**: BinaryField\n\n* **Postgres**: JSONField, ArrayField\n\n* **GIS/Django Geo**: Geometryfield, PointField, LineStringField, PolygonField, MultiPointField, MultiLineStringField, MultiPolygonField, GeometryCollectionField\n\nUse ``DDF_FIELD_FIXTURES`` settings, customized data or even the field default values to deal with not supported fields.\n\n\nGeoDjango Fields\n===============================================================================\n\nAfter `1.8.4` version, DDF has native support for GeoDjango fields: GeometryField, PointField, LineStringField, PolygonField, MultiPointField, MultiLineStringField, MultiPolygonField, GeometryCollectionField.\n\nFor older versions of DDF, please, use the following approach:\n\nYou can use ``DDF_FIELD_FIXTURES`` to create fixtures for Geo Django fields::\n\n    # https://docs.djangoproject.com/en/dev/ref/contrib/gis/\n    from django.contrib.gis.geos import Point\n    DDF_FIELD_FIXTURES = {\n        'django.contrib.gis.db.models.GeometryField': lambda: None,\n        'django.contrib.gis.db.models.PointField': lambda: None,\n        'django.contrib.gis.db.models.LineStringField': lambda: None,\n        'django.contrib.gis.db.models.PolygonField': lambda: None,\n        'django.contrib.gis.db.models.MultiPointField': lambda: None,\n        'django.contrib.gis.db.models.MultiLineStringField': lambda: None,\n        'django.contrib.gis.db.models.MultiPolygonField': lambda: None,\n        'django.contrib.gis.db.models.GeometryCollectionField': lambda: None,\n    }\n\n\nAbout Custom Fields\n===============================================================================\n\n* Customized data is also valid for unsupported fields.\n* You can also set the field fixture using the ``DDF_FIELD_FIXTURES`` settings. (new in 1.8.0)\n* if a field is not default in Django, but it inherits from a Django field, it will be filled using its config.\n\n* if a field is not default in Django and not related with a Django field, it will raise an ``UnsupportedFieldError``.\n* if it does not recognize the Field class, it will raise an ``UnsupportedFieldError``.\n\n\nFill Nullable Fields\n===============================================================================\n\nThis option define if nullable fields (fields with ``null=True``) will receive a generated data or not (``data=None``). This property is exclusive for non-FK fields. It is possible to override the global option for an specific instance. But be careful because this option will be propagate to all internal dependencies.\n\nIn settings.py::\n\n    DDF_FILL_NULLABLE_FIELDS = True\n\nIn the test file::\n\n    instance = G(MyModel, fill_nullable_fields=False)\n    assert instance.a_nullable_field is None\n    assert instance.a_required_field is not None\n\n    instance = G(MyModel, fill_nullable_fields=True)\n    assert instance.a_nullable_field is not None\n    assert instance.a_required_field is not None\n\n\nIgnoring Fields (New in 1.2.0)\n===============================================================================\n\nThis option defines a list of fields DDF will ignore. In other words, DDF will not fill it with dynamic data. This option can be useful for fields auto calculated by models, like [MPTT](https://github.com/django-mptt/django-mptt) models. Ignored fields are propagated ONLY to self references.\n\nIn settings.py::\n\n    DDF_IGNORE_FIELDS = ['field_x', 'field_y'] # default = []\n\nIgnored field names can use wildcard matching with '*' and '?' characters which substitute multiple or one character respectively. Wildcards are useful for fields that should not be populated and which match a pattern, like ``*_ptr`` fields for [django-polymorphic](https://github.com/django-polymorphic/django-polymorphic).\n\nIn settings.py::\n\n    DDF_IGNORE_FIELDS = ['*_ptr'] # Ignore django-polymorphic pointer fields\n\nIt is not possible to override the global configuration, just extend the list. So use global option with caution::\n\n    instance = G(MyModel, ignore_fields=['another_field_name'])\n    assert instance.another_field_name is None\n\n\nMinimum Foreign Key Depth\n===============================================================================\n\nThis option is used by DDF to control dependencies and cyclic dependencies (``ForeignKey`` by ``self``, denormalizations, bad design etc). DDF does not enter infinite loop of instances generation. This option defines how depth DDF should go to create instances of foreign key fields. This option can also be used to create trees with different lengths.\n\nIn settings.py::\n\n    DDF_FK_MIN_DEPTH = 0\n\nIn the test file::\n\n    instance = G(MyModel, fk_min_depth=1)\n    assert instance.self_fk.id is not None\n    assert instance.self_fk.self_fk.id is None\n\n    instance = G(MyModel, fk_min_depth=2)\n    assert instance.self_fk.id is not None\n    assert instance.self_fk.self_fk.id is not None\n    assert instance.self_fk.self_fk.self_fk.id is None\n\n> Incompatibility warning: Before DDF 3.0.3, DDF handled FK cycles instead of FK depth, through the removed properties `DDF_NUMBER_OF_LAPS` and `number_of_laps`.\n"
  },
  {
    "path": "docs/source/data_fixtures.rst",
    "content": ".. _data_fixtures:\n\nData Fixtures\n*******************************************************************************\n\n.. contents::\n   :local:\n\nConfiguration\n===============================================================================\n\nThis configuration defines the algorithm of data generation that will be used to populate fields with dynamic data. Do NOT mix data fixtures in the same test suite because the generated data may conflict and it will produce erratic tests.\n\nIn settings.py::\n\n    DDF_DEFAULT_DATA_FIXTURE = 'sequential' # or 'static_sequential' or 'random' or 'path.to.your.DataFixtureClass'\n\nOverriding global data fixture\n===============================================================================\n\nThis algorithm will be used just for the current model generation.\n\nIn the test file or shell::\n\n    G(MyModel, data_fixture='sequential')\n    G(MyModel, data_fixture='random')\n    G(MyModel, data_fixture=MyCustomDataFixture())\n\nSequential Data Fixture\n===============================================================================\n\nUseful to use in test suites. Sequential Data Fixture stores an independent counter for each model field that is incremented every time this field has to be populated. If for some reason the field has some restriction (*max_length*, *max_digits* etc), the counter restarts. This counter is used to populate fields of numbers (*Integer*, *BigDecimal* etc) and strings (*CharField*, *TextField* etc). For *BooleanFields*, it will always return False. For *NullBooleanFields*, it will always return None. For date and time fields, it will always return Today minus 'counter' days or Now minus 'counter' seconds, respectively.\n\nIn settings.py::\n\n    DDF_DEFAULT_DATA_FIXTURE = 'sequential'\n\nIn the test file::\n\n    instance = G(MyModel)\n    assert instance.integerfield_a == 1\n    assert instance.integerfield_b == 1\n    assert instance.charfield_b == 1\n    assert instance.booleanfield == False\n    assert instance.nullbooleanfield is None\n\n    instance = G(MyModel)\n    assert instance.integerfield_a == 2\n    assert instance.integerfield_b == 2\n    assert instance.charfield_b == 2\n    assert instance.booleanfield == False\n    assert instance.nullbooleanfield is None\n\n    instance = G(MyOtherModel)\n    assert instance.integerfield_a == 1\n\n    # ...\n\nStatic Sequential Data Fixture\n===============================================================================\n\nUseful to use in test suites. Static Sequential Data Fixture is the same as Sequential Data Fixture, except it will increase the counter only if the field has *unique=True*.\n\nIn settings.py::\n\n    DDF_DEFAULT_DATA_FIXTURE = 'static_sequential'\n\nIn the test file::\n\n    instance = G(MyModel)\n    assert instance.integerfield_unique == 1\n    assert instance.integerfield_notunique == 2\n\n    instance = G(MyModel)\n    assert instance.integerfield_unique == 2\n    assert instance.integerfield_notunique == 2\n    # ...\n\nRandom Data Fixture\n===============================================================================\n\nUseful to use in python shells. In shell you may want to do some manual tests, and DDF may help you to generate models too. If you are using shell with a not-in-memory database, you may have problems with *SequentialDataFixture* because the sequence will be reset every time you close the shell, but the data already generated is persisted.\n\nIt is dangerous to use this data fixture in a test suite because it can produce erratic tests. For example, depending on the quantity of tests and *max_length* of a *CharField*, there is a high probability to generate an identical value which will result in invalid data for fields with *unique=True*.\n\nIn settings.py::\n\n    DDF_DEFAULT_DATA_FIXTURE = 'random'\n\nIn the test file::\n\n    instance = G(MyModel)\n    assert instance.integerfield_a is not None\n    assert instance.charfield_b is not None\n    assert instance.booleanfield in [False, True]\n    assert instance.nullbooleanfield in [None, False, True]\n    # ...\n\nCustom Data Fixture\n===============================================================================\n\nIn settings.py::\n\n    DDF_DEFAULT_DATA_FIXTURE = 'path.to.your.DataFixtureClass'\n\nIn the path/to/your.py file::\n\n    from django_dynamic_fixture.ddf import DataFixture\n    class DataFixtureClass(DataFixture): # it can inherit of SequentialDataFixture, RandomDataFixture etc.\n        def integerfield_config(self, field, key): # method name must have the format: FIELDNAME_config\n            return 1000 # it will always return 1000 for all IntegerField\n\nIn the test file::\n\n    instance = G(MyModel)\n    assert instance.integerfield_a == 1000\n    assert instance.integerfield_b == 1000\n    # ...\n\n\nCustom Field Fixture\n===============================================================================\n\nYou can also override a field default fixture or even create a fixture for a new field using the **DDF_FIELD_FIXTURES** settings in ``settings.py``::\n\n    # https://github.com/bradjasper/django-jsonfield\n    import json\n    DDF_FIELD_FIXTURES = {\n        'jsonfield.fields.JSONCharField': {'ddf_fixture': lambda: json.dumps({'some random value': 'c'})},\n        'jsonfield.fields.JSONField': {'ddf_fixture': lambda: json.dumps([1, 2, 3])},\n    }\n"
  },
  {
    "path": "docs/source/ddf.rst",
    "content": ".. _ddf:\n\nCore DDF features\n*******************************************************************************\n\n.. contents::\n   :local:\n\nGet: G\n===============================================================================\n\nThe ``G`` function (shortcut for the ``get`` function) is the main feature of DDF. It is useful for integration tests, for the model logic and queries to the database.\n\nIt receives a model class and it will return a **valid and persisted instance** filled with dynamically generated data::\n\n\n    from ddf import G # or from ddf import get\n    author = G(Author)\n    assert author.id is not None # indicating the instance was saved\n    assert author.name is not None # indicating a name was generated for you\n    assert len(author.name) > 0\n\n\nThis facilitates writing tests and it hides all dummy data that pollutes the source code. But all **important data of the test may be explicitly defined**. This is even a good practice, because it let the test very clear and cohesive::\n\n\n    book = G(Book, name='The Lord of the Rings', publish_date=date(1954, 07, 29))\n    assert book.name == 'The Lord of the Rings'\n    assert book.publish_date == date(1954, 07, 29)\n\n\nImportant details:\n\n* The **id** (AutoField) is auto filled, unless you set a value to it.\n* if a field has **default value**, it is used by default. Unless you override it.\n* if a field has **choices**, the first option is selected by default. Unless you override it.\n\n\nNew: N\n===============================================================================\n\nThis function ``N`` (shortcut to ``new``) is similar to ``G``, except it will NOT save the generated instance. This is good for **unit tests**, without touching the database::\n\n    from ddf import N\n    not_saved_book = N(Book)\n    assert not_saved_book.id is None # indicating the instance was NOT saved\n    assert not_saved_book.name is not None # indicating a name was generated for you\n\nIt can also be usefuf to **manipulate the instance before saving it**. Usually, we need that to deal with custom fields, custom validations etc. For these cases, we can use the ``persist_dependencies=True`` parameter to save internal dependencies of ``ForeignKey`` and ``OneToOneField`` fields::\n\n    book = N(Book, persist_dependencies=True)\n    assert book.id is None # the Book was not persisted\n    assert book.publisher.id is not None # internal dependency was persisted\n\nps: Since the instance does not have an ID, it can NOT insert instances in ``ManyToManyField`` fields. So, be aware to use the ``G`` function for these cases.\n\nFixture: F\n===============================================================================\n\nDDF also allows you **customise recursively through relationship fields** ``ForeignKey``, ``OneToOneField`` and ``ManyToManyField``) using the ``F`` function (shortcut for ``fixture``).\n\nForeignKey and OneToOneField\n-------------------------------------------------------------------------------\n\nTo customise relationships, you can use the ``F`` function or the Django look up syntax::\n\n    from ddf import G, F\n    book = G(Book, author=F(name='Eistein'))\n    # or, even simpler, using the Django loop up syntax:\n    book = G(Book, author__name='Eistein')\n    assert book.author.name == 'Eistein'\n\nThis is the equivalent to::\n\n    author = G(Author, name='Eistein')\n    book = G(Book, author=author)\n    assert book.author.name == 'Eistein'\n\n``F`` function is recursible::\n\n    book = G(Book, author=F(address=F(zipcode='123456789')))\n    # or, even simpler, using the Django loop up syntax:\n    book = G(Book, author__address__zipcode='123456789')\n    assert book.author.address.zipcode == '123456789'\n\n``F`` can be used to customize instances of a ``ManyToManyField`` too::\n\n    book = G(Book, authors=[F(name='Eistein'), F(name='Tesla')])\n    assert book.authors.all()[0].name == 'Eistein'\n    assert book.authors.all()[1].name == 'Tesla'\n\n\nDjango Look Up fields syntax (New in 1.6.1) (Fixed in 3.0.0)\n-------------------------------------------------------------------------------\n\nThis is an alias to ``F`` function, and it follows the Django pattern of filters that use two underlines to access internal fields of foreign keys. You can **combine** multiple parameters to create a complete customisable instance.\n\nps: Just be careful because DDF does NOT interpret **related names** yet. It has also some limitation for many to many fields.\n\n\nMany to Many fields\n-------------------------------------------------------------------------------\n\nDDF can add instances in ``ManyToManyFields``, but only if the instance has been persisted to the database (Django requirement). DDF handles ``ManyToManyFields`` with ``through`` table as well.\n\nIt is possible to define **how many instances** will be created dynamically::\n\n    book = G(Book, authors=5)\n    assert book.authors.all().count() == 5\n\nIt is possible to customize each instance of the ``ManyToManyField``::\n\n    book = G(Book, authors=[F(name='Eistein'), F(address__zipcode='123456789')])\n    assert book.authors.all().count() == 2\n    assert instance.authors.all()[0].name == 'Eistein'\n    assert instance.authors.all()[1].address.zipcode == '123456789'\n\nIt is possible to pass already created instances too::\n\n    author1 = G(Author)\n    author2 = G(Author)\n\n    book = G(Book, authors=[author1, author2])\n    assert book.authors.all().count() == 2\n\nOr even mixed them up::\n\n    book = G(Book, authors=[F(), author1, F(), author2])\n    assert book.authors.all().count() == 4\n\n\nMask: M (New in 3.1.0)\n===============================================================================\n\n``M`` (shortcut for ``Mask``) is a feature that tell DDF to generate a random string using a custom mask.\n\nThe mask symbols are:\n\n- ``#``: represents a number: 0-9\n- ``-``: represents a upper case char: A-Z\n- ``_``: represents a lower case char: a-z\n- ``!``: escape mask symbols, inclusive itself\n\nExamples::\n\n    from ddf import G, M\n    instance = G(Publisher, address=M(r'St. -______, ### !- -- --'))\n    assert instance.address == 'St. Imaiden, 164 - SP BR'\n\n\nCopier: C (New in 1.6.0)\n===============================================================================\n\n``C`` (shortcut for ``Copier``) is a feature to copy the data of a field to another one. It is necessary to avoid cycles in the copier expression. If a cycle is found, DDF will alert the programmer the expression is invalid::\n\n    from ddf import G, C\n    user = G(User, first_name=C('username'))\n    assert instance.first_name == instance.username\n\n    instance = G(MyModel, first_name=C('username'), username='eistein')\n    assert instance.first_name == 'eistein'\n\nIt is possible to copy values of internal relationships, but only in the **bottom-up way**::\n\n    person = G(Person, phone=C('parent.phone'))\n    assert person.phone == person.parent.phone\n\n\nTeaching DDF with Lessons (shelve in 2.1.0) (New in 3.0.0)\n===============================================================================\n\nSometimes DDF can not generate a valid and persisted instance because it contains custom fields or custom validations (field or model validation). In these cases, it is possible to **teach DDF how to build a valid instance**. It is necessary to create a valid configuration and save it in an internal and global DDF library of configurations. All future instances of that model will use the saved lesson as base.\n\nIn the **PyTest** **conftest.py** file or another global module that will be loaded before the test suite::\n\n    from ddf import teach\n    teach(Author, name='Eistein')\n    # After this command, all authors will have the name Eistein, unless it was overrided.\n\nIn the test files::\n\n    from ddf import G\n    author = G(Author)\n    assert author.name == 'Eistein'\n\n\nIt is possible to **override** the lessons though::\n\n    author = G(Author, name='Tesla')\n    assert author.name == 'Tesla'\n\nIt is possible to store **custom functions** of data fixtures for fields too::\n\n    zip_code_data_fixture = lambda field: 'MN {}'.format(random.randint())\n    teach(Address, zip_code=zip_code_data_fixture)\n\n    address = G(Address)\n    assert address.zip_code == 'MN 55416'\n\nIt is possible to store **Copiers** too::\n\n    teach(Author, first_name=C('username'))\n\n    author = G(Author, username='eistein')\n    assert instance.username == 'eistein'\n    assert instance.first_name == 'eistein'\n\nIt is also possible to save custom lessons that will override the default one. But avoid having too many of them, since this will became the test suite very complex.\n\nYou can have **many custom lessons** too, giving names to them::\n\n    from ddf import teach\n    teach(Model, field_x=77)\n    teach(Model, field_x=88, ddf_lesson='my custom lesson 1')\n    teach(Model, field_x=99, ddf_lesson='my custom lesson 2')\n\n    instance = G(Model)\n    assert instance.field_x == 77\n\n    instance = G(Model, ddf_lesson='my custom lesson 1')\n    assert instance.field_x == 88\n\n    instance = G(Model, ddf_lesson='my custom lesson 2')\n    assert instance.field_x == 99\n\nps: Just be aware that overriding lessons is an anti-pattern and may let your test suite very hard to understand.\n"
  },
  {
    "path": "docs/source/fdf.rst",
    "content": ".. _fdf:\n\nFileSystemDjangoTestCase (New in 1.3.0)\n*******************************************************************************\n\n.. contents::\n   :local:\n\n*FileSystemDjangoTestCase* has a tear down method to delete all test files generated by tests, to avoid letting trash in the file system::\n\n    class MyTests(FileSystemDjangoTestCase):\n        def test_x(self):\n            print(dir(self))\n\nIt also has a collection of methods to simplify tests that use files, like:\n\n* create_temp_directory\n* remove_temp_directory\n* create_temp_file\n* create_temp_file_with_name\n* rename_temp_file\n* remove_temp_file\n* copy_file_to_dir\n* add_text_to_file\n* get_directory_of_the_file\n* get_filename\n* get_filepath\n* get_content_of_file\n* create_django_file_with_temp_file\n* create_django_file_using_file\n\nIt also contains a set of assertion methods:\n\n* assertFileExists\n* assertFileDoesNotExists\n* assertDirectoryExists\n* assertDirectoryDoesNotExists\n* assertDirectoryContainsFile\n* assertDirectoryDoesNotContainsFile\n* assertFilesHaveEqualLastModificationTimestamps\n* assertFilesHaveNotEqualLastModificationTimestamps\n* assertNumberOfFiles\n\n"
  },
  {
    "path": "docs/source/index.rst",
    "content": ".. DDF documentation master file, created by\n   sphinx-quickstart on Mon Sep  1 18:20:45 2014.\n   You can adapt this file completely to your liking, but it should at least\n   contain the root `toctree` directive.\n\nWelcome to DDF's documentation!\n===============================\n\nDjango Dynamic Fixture (DDF) is a complete and simple library to create **dynamic model instances** for **testing purposes**.\n\nIt lets you **focus on your tests**, instead of focusing on generating some dummy data which is boring and pollutes the test source code.\n\nIt exists to solve the **anti-pattern** of Static Fixtures and Factory objects. Are you tired to maintain dozens of yml/json files and factory objects?\n\n\n.. toctree::\n   :maxdepth: 2\n\n   overview\n   ddf\n   data\n   settings\n   data_fixtures\n   more\n   patterns\n   fdf\n   about\n   change_log\n\n\nIndices and tables\n==================\n\n* :ref:`genindex`\n* :ref:`modindex`\n* :ref:`search`\n\n"
  },
  {
    "path": "docs/source/more.rst",
    "content": ".. _more:\n\nDDF Extras\n*******************************************************************************\n\n.. contents::\n   :local:\n\n\nDebugging\n===============================================================================\n\nPrint model instance values: P\n-------------------------------------------------------------------------------\n\nPrint all field values of an instance. You can also pass a list of instances or a *QuerySet*. It is useful for debug::\n\n    from django_dynamic_fixture import G, P\n\n    P(G(Model))\n    P(G(Model, n=2))\n    P(Model.objects.all())\n\n    # This will print some thing like that:\n    # :: Model my_app.MyModel (12345)\n    # id: 12345\n    # field_x: 'abc'\n    # field_y: 1\n    # field_z: 1\n\n\nDDF compatibility checking (New in 3.0.0)\n-------------------------------------------------------------------------------\n\nBefore starting using DDF in your application, it is good to check its compatibility with your application models.\n\nDDF has a simple script that will look for all Django models of all installed Django applications and it will **print a report** for you::\n\n    from ddf import ddf_check_models\n    succeeded, errors = ddf_check_models()\n\nYou can also print in CSV format (using Tabs for separators)::\n\n    succeeded, errors = ddf_check_models(print_csv=True)\n\nOr even save the report directly to a CSV file::\n\n    succeeded, errors = ddf_check_models(csv_filename='ddf_compatibility_report.csv')\n\nCheck for a **ddf_compatibility_report.csv** file in the current directory, so you can use it better in a CSV editor.\n\n\nDebug Mode (New in 1.6.2)\n-------------------------------------------------------------------------------\n\nPrint debug log of DDF.\n\nIn settings.py::\n\n    DDF_DEBUG_MODE = True # default = False\n\nIn the test file::\n\n    G(MyModel, debug_mode=True)\n\n\nDDF Version (New in 3.0.2)\n-------------------------------------------------------------------------------\n\nType::\n\n    import ddf\n    ddf.__version__\n\n\nList of Exceptions\n-------------------------------------------------------------------------------\n\n* *UnsupportedFieldError*: DynamicFixture does not support this field.\n* *InvalidConfigurationError*: The specified configuration for the field can not be applied or it is bugged.\n* *InvalidManyToManyConfigurationError*: M2M attribute configuration must be a number or a list of DynamicFixture or model instances.\n* *BadDataError*: The data passed to a field has some problem (not unique or invalid) or a required attribute is in ignore list.\n* *InvalidCopierExpressionError*: The specified expression used in a Copier is invalid.\n* *InvalidModelError*: Invalid Model: The class is not a model or it is abstract.\n\n\nDecorators (New in 1.4.0)\n===============================================================================\n\nExample::\n\n    from django_dynamic_fixture.decorators import skip_for_database, only_for_database, SQLITE3, POSTGRES\n\n    @skip_for_database(SQLITE3)\n    def test_some_feature_that_use_raw_sql_not_supported_by_sqlite(self): pass\n\n    @only_for_database(POSTGRES)\n    def test_some_feature_that_use_raw_sql_specific_to_my_production_database(self): pass\n\nIt is possible to pass a custom string as argument, one that would be defined in settings.DATABASES['default']['ENGINE']::\n\n    @skip_for_database('my custom driver')\n    @only_for_database('my custom driver')\n\n\nValidation\n===============================================================================\n\nValidate Models (New in 1.5.0)\n-------------------------------------------------------------------------------\nThis option is a flag to determine if the method *full_clean* of model instances will be called before DDF calls the save method.\n\nIn settings.py::\n\n    DDF_VALIDATE_MODELS = False\n\nIn the test file::\n\n    G(MyModel, validate_models=True)\n\n\nSignals PRE_SAVE and POST_SAVE:\n===============================================================================\n\nIn very special cases a signal may facilitate implementing tests with DDF, but Django signals may not be satisfactory for testing purposes because the developer does not have control of the execution order of the receivers. For this reason, DDF provides its own signals. It is possible to have only one receiver for each model, to avoid anti-patterns::\n\n    from django_dynamic_fixture import PRE_SAVE, POST_SAVE\n    def callback_function(instance):\n        pass # do something\n    PRE_SAVE(MyModel, callback_function)\n    POST_SAVE(MyModel, callback_function)\n"
  },
  {
    "path": "docs/source/overview.rst",
    "content": ".. _overview:\n\n\nGetting Started\n*******************************************************************************\n\n.. contents::\n   :local:\n\nBasic Example of Usage\n===============================================================================\n\nModels sample (`models.py`)::\n\n    from django.db import models\n\n    class Author(models.Model):\n        name = models.CharField(max_length=255)\n\n    class Book(models.Model):\n        name = models.CharField(max_length=255)\n        authors = models.ManyToManyField(Author)\n\n        @staticmethod\n        def search_by_author(author_name):\n            return Book.objects.filter(authors__name=author_name)\n\n\n**PyTest** example (`tests/test_books.py`)::\n\n    from ddf import G\n\n    def test_search_book_by_author():\n        author1 = G(Author)\n        author2 = G(Author)\n        book1 = G(Book, authors=[author1])\n        book2 = G(Book, authors=[author2])\n        books = Book.objects.search_by_author(author1.name)\n        assert book1 in books\n        assert book2 not in books\n\n**Django TestCase** example (`tests/test_books.py`)::\n\n    from django.test import TestCase\n    from ddf import G\n\n    class SearchingBooks(TestCase):\n        def test_search_book_by_author(self):\n            author1 = G(Author)\n            author2 = G(Author)\n            book1 = G(Book, authors=[author1])\n            book2 = G(Book, authors=[author2])\n            books = Book.objects.search_by_author(author1.name)\n            self.assertTrue(book1 in books)\n            self.assertTrue(book2 not in books)\n\n\nInstallation\n===============================================================================\n\n::\n\n    pip install django-dynamic-fixture\n\nor::\n\n    1. Download zip file\n    2. Extract it\n    3. Execute in the extracted directory: python setup.py install\n\nDevelopment version\n-------------------------------------------------------------------------------\n\n::\n\n    pip install -e git+git@github.com:paulocheque/django-dynamic-fixture.git#egg=django-dynamic-fixture\n\n\nrequirements.txt\n-------------------------------------------------------------------------------\n\n::\n\n    django-dynamic-fixture==<VERSION>\n    # or use the development version\n    git+git://github.com/paulocheque/django-dynamic-fixture.git#egg=django-dynamic-fixture\n\n\nUpgrade\n-------------------------------------------------------------------------------\n\n::\n\n    pip install django-dynamic-fixture --upgrade --no-deps\n\n\nSupport and Compatibility\n===============================================================================\n\n+---------------------------------------------------------+\n| DDF current support                                     |\n+================+=================+======================+\n| Python 3.11    | Django 4.x.x    | DDF 4.*.* - Aug 2023 |\n+----------------+-----------------+----------------------+\n| Python 3.10    | Django 4.x.x    | DDF 4.*.* - Aug 2023 |\n+----------------+-----------------+----------------------+\n| Python 3.9     | Django 4.x.x    | DDF 4.*.* - Aug 2023 |\n+----------------+-----------------+----------------------+\n| Python 3.8     | Django 4.x.x    | DDF 4.*.* - Aug 2023 |\n+----------------+-----------------+----------------------+\n\nFor old versions of Python or Django, use old versions of DDF too:\n\n+---------------------------------------------------------+\n| DDF old support                                         |\n+================+=================+======================+\n| Python 3.8     | Django 3.x.x    | DDF 3.*.* - Jan 2020 |\n+----------------+-----------------+----------------------+\n| Python 3.7     | Django 3.x.x    | DDF 3.*.* - Jan 2020 |\n+----------------+-----------------+----------------------+\n| Python 3.6     | Django 3.x.x    | DDF 3.*.* - Jan 2020 |\n+----------------+-----------------+----------------------+\n| Python > 3.5   | Django 2.x.x    | DDF 3.*.* - Jan 2020 |\n+----------------+-----------------+----------------------+\n| Python 3.3     | Django < 1.11.x | DDF 2.0.* - Dec 2017 |\n+----------------+-----------------+----------------------+\n| Python 2.7     | Django 1.11.x   | DDF 3.*.* - Jan 2020 |\n+----------------+-----------------+----------------------+\n| Python <= 2.7  | Django < 1.11.x | DDF 2.0.* - Dec 2017 |\n+----------------+-----------------+----------------------+\n\n\nList of features\n===============================================================================\n\n  * Highly customizable: you can **customize fields recursively**\n  * Deals with **unique=True**\n  * Deals with **cyclic dependencies** (including self references)\n  * Deals with **many to many relationship** (common M2M or M2M with additional data, i.e. **through='table'**)\n  * Deals with **custom fields** (especially if the custom field inherits from a django field)\n  * Support for **parallel tests**\n  * Deals with **auto calculated** attributes\n  * It is **easy to debug errors**\n\nMotivation\n===============================================================================\n\n  * It is a terrible practice to use **static data** in tests (yml/json/sql files).\n  * It is very hard to maintain lots of **Factory objects**.\n  * Creating fixtures for each model is boring and it produces a lot of **replicated code**.\n  * It is a bad idea to use uncontrolled data in tests, like bizarre random data.\n\nComparison with other tools\n===============================================================================\n\nThe DDF was created in a context of a project with a **very complex design** with many **cyclic dependencies**. In that context, no available tool was satisfactory. Or we stumbled in some **infinite loop** or some bug caused by a **custom field**. For these reasons, the tests started to fail and it was very hard to understand why.\n\nAnother thing, the DDF was planned to have a **lean and clean syntax**. We believe that automated tests must be developed quickly with the **minimum overhead**. For that reason we are in favor of **less verbose approach**, except in the documentation ;)\n\nAlso, DDF is flexible, since it is possible to customize the entire data generation or by field.\n\n  * Either they are incomplete, or bugged or it produces erratic tests, because they use random and uncontrolled data.\n  * The syntax of others tools is too verbose, which pollutes the tests.\n  * Complete, lean and practice documentation.\n  * It is hard to debug tests with another tools.\n  * List of other tools: <https://www.djangopackages.com/grids/g/testing/> or <http://djangopackages.com/grids/g/fixtures>\n  * The core of the tool is the algorithm, it is not the data generation as all other tools. This means you can change the data generation logic.\n\nPlus:\n\n  * **PyTest** compatible\n  * **Command** to count how many queries are executed to save any kind of model instance\n  * **FileSystemDjangoTestCase** that facilitates to create tests for features that use filesystem.\n"
  },
  {
    "path": "docs/source/patterns.rst",
    "content": ".. _patterns:\n\nPatterns\n*******************************************************************************\n\n.. contents::\n   :local:\n\nPatterns\n===============================================================================\n\n  * Use *N* function for unit tests (not integration tests) for the main model.\n  * Use *G* function instead of *N* for shelving configurations. It helps to identify errors.\n  * Use *ignore_fields* option to deal with fields filled by listeners.\n  * Use custom values for unsupported fields.\n  * Use default lesson for unsupported fields with a custom function that generated data.\n  * Use *fill_nullable_fields* for unsupported nullable fields.\n  * Use *fk_min_depth* option to test trees.\n  * [Automated Test Patterns](http://www.teses.usp.br/teses/disponiveis/45/45134/tde-02042012-120707/pt-br.php) (in Portuguese)\n\nAnti-Patterns\n===============================================================================\n\n  * Using auto generated data in an assertion method.\n  * Shelving a static value for a field with *unique=True*. Raise an error.\n  * Overriding a lesson *Copier* with None.\n  * Using *Copier* to fix a bad design of the code.\n  * Too many named lessons configurations.\n  * Mix data fixture algorithms in the same test suite.\n  * Use default and custom lessons to avoid fixing a messy architecture.\n  * Extensive use of global set up: setup suite (from DDF), setup module and setup class (from unittest2).\n\n\nA good automated test\n===============================================================================\n\n  * Simple\n  * Legible\n  * Repeatable\n  * Independent\n  * Isolated\n  * Useful\n  * Unique\n  * Accurate\n  * Professional\n  * Fast"
  },
  {
    "path": "docs/source/settings.rst",
    "content": ".. _settings:\n\nDDF Settings\n===============================================================================\n\n.. contents::\n   :local:\n\n.. role:: python(code)\n   :language: python\n\n\nGlobal Settings\n-------------------------------------------------------------------------------\n\nYou can configure DDF in ``settings.py`` file. You can also override the global config per instance creation when necessary.\n\n* **DDF_FILL_NULLABLE_FIELDS** (Default = False): DDF can fill nullable fields (``null=True``) with None or some data::\n\n    # SomeModel(models.Model): nullable_field = Field(null=True)\n    G(SomeModel).nullable_field is None # True if DDF_FILL_NULLABLE_FIELDS is True\n    G(SomeModel).nullable_field is None # False if DDF_FILL_NULLABLE_FIELDS is False\n\n    # You can override the global config for one case:\n    assert G(Model, fill_nullable_fields=False).nullable_field is None\n    assert G(Model, fill_nullable_fields=True).nullable_field is not None\n\n\n*  **DDF_VALIDATE_MODELS** (Default = False): DDF will call ``model.full_clean()`` method before saving to the database::\n\n    # You can override the global config for one case:\n    G(Model, validate_models=True)\n    G(Model, validate_models=False)\n\n\n* **DDF_FIELD_FIXTURES** (Default = {}) (new in 1.8.0): Dictionary where the key is the full qualified name of the field and the value is a function without parameters that returns a value::\n\n    DDF_FIELD_FIXTURES = {'path.to.your.Field': lambda: random.randint(0, 10) }\n\n\n* **DDF_FK_MIN_DEPTH** (Default = 0):  For models with non required foreign keys (FKs with `null=True`), like FKs to itself (``ForeignKey('self')``), cyclic dependencies or even optional FKs, DDF will avoid infinite loops because it stops creating objects indefinitely, because it will stop after the min depth was achieved.::\n\n    # You can override the global config for one case:\n    G(Model, fk_min_depth=5)\n\n> Incompatibility warning: Before DDF 3.0.3, DDF handled FK cycles instead of FK depth, through the removed properties `DDF_NUMBER_OF_LAPS` and `number_of_laps`.\n\n\n* **DDF_DEBUG_MODE** (Default = False): To show some DDF logs::\n\n    # You can override the global config for one case:\n    G(Model, debug_mode=True)\n    G(Model, debug_mode=False)\n\n\n* **DDF_SHELL_MODE** (Default = False): To disable some DDF warnings so DDF can be used better in Python shell: to populate the DB, for example.\n"
  },
  {
    "path": "manage.py",
    "content": "#!/usr/bin/env python\ntry:\n    import settings_sqlite # Assumed to be in the same directory.\nexcept ImportError:\n    import sys\n    sys.stderr.write(\"Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\\nYou'll have to run django-admin.py, passing it your settings module.\\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\\n\" % __file__)\n    sys.exit(1)\n\nif __name__ == \"__main__\":\n    import os\n    os.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"settings_sqlite\")\n    from django.core.management import execute_from_command_line\n    execute_from_command_line()\n"
  },
  {
    "path": "pytest.ini",
    "content": "[pytest]\nDJANGO_SETTINGS_MODULE = settings_sqlite\naddopts = --pyargs --create-db --reuse-db --no-migrations\npython_files = test_*.py\n"
  },
  {
    "path": "queries/__init__.py",
    "content": ""
  },
  {
    "path": "queries/count_queries_on_save.py",
    "content": "\nfrom django_dynamic_fixture import new\n\nfrom django.conf import settings\nfrom django.db import connection\nfrom django import db\nfrom django_dynamic_fixture.django_helper import get_models_of_an_app, is_model_managed, get_unique_model_name, get_apps\n\n\nclass Report:\n    def __init__(self):\n        self.data = []\n        self.errors = []\n\n    def add_record(self, app, model, queries_insert, queries_update):\n        self.data.append((app, model, queries_insert, queries_update))\n\n    def add_error(self, msg):\n        self.errors.append(msg)\n\n    def export_csv(self, order_by_quantity_queries=False):\n        if order_by_quantity_queries:\n            self.data.sort(key=lambda t: t[2], reverse=True)\n        print('APP.MODEL;QUERIES ON INSERT;QUERIES ON UPDATE')\n        for app, model, queries_insert, queries_update in self.data:\n            print('%s;%s;%s' % (get_unique_model_name(model), queries_insert, queries_update))\n\n        for err in self.errors:\n            print(err)\n\n\nclass CountQueriesOnSave:\n    def __init__(self):\n        self.report = Report()\n\n    def count_queries_for_model(self, app, model):\n        try:\n            model_instance = new(model, print_errors=False)\n        except Exception as e:\n            self.report.add_error('- Could not prepare %s: %s' % (get_unique_model_name(model), str(e)))\n            return\n\n        db.reset_queries()\n        try:\n            model_instance.save()\n        except Exception as e:\n            self.report.add_error('- Could not insert %s: %s' % (get_unique_model_name(model), str(e)))\n            return\n        queries_insert = len(connection.queries)\n\n        db.reset_queries()\n        try:\n            model_instance.save()\n        except Exception as e:\n            self.report.add_error('- Could not update %s: %s' % (get_unique_model_name(model), str(e)))\n            return\n        queries_update = len(connection.queries)\n\n        self.report.add_record(app, model, queries_insert, queries_update)\n\n    def execute(self, app_labels=[], exclude_app_labels=[]):\n        settings.DEBUG = True\n        apps = get_apps(application_labels=app_labels, exclude_application_labels=exclude_app_labels)\n        for app in apps:\n            models = get_models_of_an_app(app)\n            for model in models:\n                if not is_model_managed(model):\n                    continue\n                self.count_queries_for_model(app, model)\n        return self.report\n"
  },
  {
    "path": "queries/management/__init__.py",
    "content": "\n"
  },
  {
    "path": "queries/management/commands/__init__.py",
    "content": "\n"
  },
  {
    "path": "queries/management/commands/count_queries_on_save.py",
    "content": "\nfrom optparse import make_option\n\nfrom django.core.management.base import AppCommand\nfrom queries.count_queries_on_save import CountQueriesOnSave\n\n\nclass Command(AppCommand):\n    help = \"\"\"\n    Default Usage:\n    manage.py count_queries_on_save\n    manage.py count_queries_on_save --settings=my_settings\n\n    = Specifying apps:\n    manage.py count_queries_on_save [APP_NAMES]+\n    Usage:\n    manage.py count_queries_on_save app1 app2\n    manage.py count_queries_on_save app1 app2\n    \n    = Skipping apps:\n    manage.py count_queries_on_save --skip=[APP_NAME,]+\n    Usage:\n    manage.py count_queries_on_save --skip=app1\n    manage.py count_queries_on_save --skip=app1,app2\n    manage.py count_queries_on_save app1 app2 --skip=app2\n    \"\"\"\n    args = '<app_name app_name ...> --skip=APP1,APP2'\n    option_list = AppCommand.option_list + (\n        make_option('--skip', '-s', dest='skip-apps', default='',\n                    help='Skip applications. Separate application labels by commas.'),\n    )\n\n    def handle(self, *args, **options):\n        script = CountQueriesOnSave()\n        app_labels = args\n        exclude_app_labels = options['skip-apps'].split(',')\n        report = script.execute(app_labels, exclude_app_labels)\n        report.export_csv(order_by_quantity_queries=True)\n"
  },
  {
    "path": "requirements-dev.txt",
    "content": "# Build/Package/Publish\nbuild\ntwine\n\n# Tests and Coverage\npytest\npytest-django\npytest-xdist # Run tests in parallel\npytest-cov\ntox # For the CI\n\npsycopg2-binary\n#psycopg2==2.8.4 # For tests with Postgres fields\n#or psycopg2cffi==2.7.5 # For pypy\n\n# Code\nflake8\npyflakes\npylint\nruff\npre-commit\n\n# Docs\nsphinx\nsphinx_rtd_theme\nsphinx-rtd-theme\n"
  },
  {
    "path": "requirements.txt",
    "content": "# Database Drivers\n#mysql-python\n#psycopg2 # not pypy compatible\n#psycopg2cffi # pypy2+ compatible\n\n# DjangoGEO\ngeopy\n\n# 3rd party libraries\n# jsonfield>=2.1.1\ndjango-json-field\ndjango-polymorphic\n"
  },
  {
    "path": "settings_ddf.py",
    "content": "from distutils.version import StrictVersion\nimport django\nDJANGO_VERSION = django.get_version()[0:3]\n\nDEBUG = True\n\nIMPORT_DDF_MODELS = True\n\nSECRET_KEY = 'ddf-secret-key'\n\nALLOWED_HOSTS = ['*'] # Since Django 1.11, it is verified when running tests\n\n\nINSTALLED_APPS = ()\n\nINSTALLED_APPS += (\n    'queries',\n    'django_dynamic_fixture',\n    'django.contrib.contenttypes',\n)\ntry:\n    import polymorphic\n    INSTALLED_APPS += ('polymorphic',)\nexcept ImportError:\n    pass\n\n\n# EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'\n# EMAIL_FILE_PATH = '/tmp/invest-messages'  # change this to a proper location\nEMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'\n\n# python manage.py test --with-coverage --cover-inclusive --cover-html --cover-package=django_dynamic_fixture.* --with-queries --with-ddf-setup\n\n\n# To avoid warnings\nMIDDLEWARE_CLASSES = ()\n\n# Example of DDF plugins for Custom fields\nimport json\nDDF_FIELD_FIXTURES = {\n    'django_dynamic_fixture.models_test.CustomDjangoField': {'ddf_fixture': lambda: 123456789},\n    'django_dynamic_fixture.models_test.CustomDjangoField2': lambda: 987654321,\n\n    # https://github.com/bradjasper/django-jsonfield\n    'jsonfield.fields.JSONCharField': {'ddf_fixture': lambda: json.dumps({'some random value': 'c'})},\n    'jsonfield.fields.JSONField': {'ddf_fixture': lambda: json.dumps([1, 2, 3])},\n}\n"
  },
  {
    "path": "settings_mysql.py",
    "content": "from settings_ddf import *\n\nDDF_TEST_GEODJANGO = True\n\n# MySQL\nDATABASES = {\n    'default': {\n        'ENGINE': 'django.db.backends.mysql',\n        'NAME': 'ddf',\n        'USER': 'paulocheque', # please, change this if you want to run tests in your machine\n        'PASSWORD': '',\n        'HOST': 'localhost',\n        'PORT': 3306,\n    }\n}\n\nif DDF_TEST_GEODJANGO:\n    INSTALLED_APPS += ('django.contrib.gis',)\n"
  },
  {
    "path": "settings_postgres.py",
    "content": "import os\nfrom settings_ddf import *\n\nDDF_TEST_GEODJANGO = True\n\n# Postgres and PostGis\n# > psql -d ddf -c \"CREATE EXTENSION postgis;\"\n# > psql -d ddf -c \"select postgis_lib_version();\"\nDATABASES = {\n    'default': {\n        # Postgis supports all Django features\n        # createdb ddf\n        'ENGINE': 'django.contrib.gis.db.backends.postgis',\n        'HOST': os.getenv('POSTGRES_HOST', 'localhost'),\n        'PORT': os.getenv('POSTGRES_PORT', 5432),\n        'NAME': os.getenv('POSTGRES_DB', 'ddf'),\n        'USER': os.getenv('POSTGRES_USER', 'ddf_user'), # please, change this if you want to run tests in your machine\n        'PASSWORD': os.getenv('POSTGRES_PASSWORD', 'ddf_pass'),\n    }\n}\n\nif DDF_TEST_GEODJANGO:\n    INSTALLED_APPS += ('django.contrib.gis',)\n"
  },
  {
    "path": "settings_sqlite.py",
    "content": "from settings_ddf import *\n\nDDF_TEST_GEODJANGO = False\n\n# SQlite and SpatialLite\n# brew install spatialite-tools\n# brew install gdal\nSPATIALITE_LIBRARY_PATH = '/usr/local/lib/mod_spatialite.dylib'\nDATABASES = {\n    'default': {\n        'ENGINE': 'django.db.backends.sqlite3',\n        'NAME': ':memory:',\n    }\n}\n\nif DDF_TEST_GEODJANGO:\n    INSTALLED_APPS += ('django.contrib.gis',)\n"
  },
  {
    "path": "setup.py",
    "content": "from pathlib import Path\nfrom setuptools import setup, find_packages\n\nVERSION = '4.0.1'\n\ntests_require = []\n\ninstall_requires = []\n\nthis_directory = Path(__file__).parent\nlong_description = (this_directory / 'README.md').read_text()\n\nsetup(name='django-dynamic-fixture',\n      url='https://github.com/paulocheque/django-dynamic-fixture',\n      author=\"paulocheque\",\n      author_email='paulocheque@gmail.com',\n      keywords='python django testing fixture',\n      description='A full library to create dynamic model instances for testing purposes.',\n      long_description_content_type='text/markdown',\n      long_description=long_description,\n      license='MIT',\n      classifiers=[\n          'Framework :: Django',\n          'Operating System :: OS Independent',\n          'Topic :: Software Development',\n          'Programming Language :: Python :: 3.8',\n          'Programming Language :: Python :: 3.9',\n          'Programming Language :: Python :: 3.10',\n          'Programming Language :: Python :: 3.11',\n          'Programming Language :: Python :: Implementation :: PyPy',\n      ],\n\n      version=VERSION,\n      install_requires=install_requires,\n      tests_require=tests_require,\n      test_suite='pytest',\n      extras_require={'test': tests_require},\n\n      packages=find_packages(),\n)\n\n"
  },
  {
    "path": "tox.ini",
    "content": "[tox]\nenvlist =\n    py38-django40\n    py38-django41\n    py38-django42\n    py39-django40\n    py39-django41\n    py39-django42\n    py310-django40\n    py310-django41\n    py310-django42\n    py311-django40\n    py311-django41\n    py311-django42\n\n[testenv]\nwhitelist_externals = pytest\nallowlist_externals = pytest\n\ndeps =\n    -r{toxinidir}/requirements.txt\n    -r{toxinidir}/requirements-dev.txt\n    django40: Django>=4.0,<4.1\n    django41: Django>=4.1,<4.2\n    django42: Django>=4.2,<4.3\n\ncommands = pytest -n 3 --create-db --reuse-db --no-migrations\n"
  }
]