from functools import partial from typing import Dict, Any, Sequence, Callable, Optional from django.db.models import Model from . import compare as base_compare from .comparison import _compare_mapping, register, CompareContext, unspecified, Registry def instance_fields(instance): opts = instance._meta for name in ( 'concrete_fields', 'virtual_fields', 'private_fields', ): fields = getattr(opts, name, None) if fields: for field in fields: yield field def model_to_dict( instance: Any, exclude: Sequence[str], include_not_editable: bool, ) -> Dict[str, Any]: data = {} for f in instance_fields(instance): if f.name in exclude: continue if not getattr(f, 'editable', False) and not include_not_editable: continue data[f.name] = f.value_from_object(instance) return data def compare_model(x, y, context: CompareContext): """ Returns an informative string describing the differences between the two supplied Django model instances. The way in which this comparison is performed can be controlled using the following parameters: :param ignore_fields: A sequence of fields to ignore during comparison, most commonly set to ``['id']``. By default, no fields are ignored. :param non_editable_fields: If `True`, then fields with ``editable=False`` will be included in the comparison. By default, these fields are ignored. """ ignore_fields = context.get_option('ignore_fields', set()) non_editable_fields= context.get_option('non_editable_fields', False) args = [] for obj in x, y: args.append(model_to_dict(obj, ignore_fields, non_editable_fields)) args.append(context) args.append(x) return _compare_mapping(*args) register(Model, compare_model) def compare( *args, x: Any = unspecified, y: Any = unspecified, expected: Any = unspecified, actual: Any = unspecified, prefix: str = None, suffix: str = None, x_label: str = None, y_label: str = None, raises: bool = True, recursive: bool = True, strict: bool = False, ignore_eq: bool = True, comparers: Registry = None, **options: Any ) -> Optional[str]: """ This is identical to :func:`~testfixtures.compare`, but with ``ignore=True`` automatically set to make comparing django :class:`~django.db.models.Model` instances easier. """ return base_compare( *args, x=x, y=y, expected=expected, actual=actual, prefix=prefix, suffix=suffix, x_label=x_label, y_label=y_label, raises=raises, recursive=recursive, strict=strict, ignore_eq=ignore_eq, comparers=comparers, **options )
Name | Type | Size | Permission | Actions |
---|---|---|---|---|
__pycache__ | Folder | 0755 |
|
|
tests | Folder | 0755 |
|
|
__init__.py | File | 1.19 KB | 0644 |
|
comparison.py | File | 39.14 KB | 0644 |
|
compat.py | File | 224 B | 0644 |
|
components.py | File | 1.31 KB | 0644 |
|
datetime.py | File | 24.42 KB | 0644 |
|
django.py | File | 2.88 KB | 0644 |
|
logcapture.py | File | 10.75 KB | 0644 |
|
mock.py | File | 1.21 KB | 0644 |
|
outputcapture.py | File | 4.69 KB | 0644 |
|
popen.py | File | 9.89 KB | 0644 |
|
replace.py | File | 12.15 KB | 0644 |
|
resolve.py | File | 2.05 KB | 0644 |
|
rmtree.py | File | 2.52 KB | 0644 |
|
shouldraise.py | File | 3.58 KB | 0644 |
|
shouldwarn.py | File | 2.21 KB | 0644 |
|
sybil.py | File | 2.28 KB | 0644 |
|
tempdirectory.py | File | 12.89 KB | 0644 |
|
twisted.py | File | 4.8 KB | 0644 |
|
utils.py | File | 2.74 KB | 0644 |
|
version.txt | File | 6 B | 0644 |
|