django-pfx 1.7.6.dev35__tar.gz → 1.7.6.dev37__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (330) hide show
  1. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/PKG-INFO +1 -1
  2. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/django_pfx.egg-info/PKG-INFO +1 -1
  3. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/django_pfx.egg-info/SOURCES.txt +1 -0
  4. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/django_pfx.egg-info/scm_file_list.json +1 -0
  5. django_pfx-1.7.6.dev37/django_pfx.egg-info/scm_version.json +8 -0
  6. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/test.py +76 -2
  7. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/requirements.txt +2 -0
  8. django_pfx-1.7.6.dev37/tests/tests/parallel_scenarios.py +89 -0
  9. django_pfx-1.7.6.dev37/tests/tests/test_test_runner.py +234 -0
  10. django_pfx-1.7.6.dev35/django_pfx.egg-info/scm_version.json +0 -8
  11. django_pfx-1.7.6.dev35/tests/tests/test_test_runner.py +0 -117
  12. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/.gitignore +0 -0
  13. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/.gitlab-ci.yml +0 -0
  14. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/.pre-commit-config.yaml +0 -0
  15. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/LICENSE +0 -0
  16. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/MANIFEST.in +0 -0
  17. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/README.md +0 -0
  18. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/django_pfx.egg-info/dependency_links.txt +0 -0
  19. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/django_pfx.egg-info/requires.txt +0 -0
  20. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/django_pfx.egg-info/top_level.txt +0 -0
  21. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/doc/Makefile +0 -0
  22. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/doc/conf.py +0 -0
  23. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/doc/index.rst +0 -0
  24. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/doc/source/api.views.rst +0 -0
  25. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/doc/source/authentication.md +0 -0
  26. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/doc/source/decorator.md +0 -0
  27. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/doc/source/generate_openapi.md +0 -0
  28. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/doc/source/getting_started.md +0 -0
  29. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/doc/source/internationalisation.md +0 -0
  30. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/doc/source/model.md +0 -0
  31. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/doc/source/pfx_views.md +0 -0
  32. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/doc/source/profiling.md +0 -0
  33. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/doc/source/settings.md +0 -0
  34. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/doc/source/testing.md +0 -0
  35. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/doc/source/user_jobs.md +0 -0
  36. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/img/pfx.png +0 -0
  37. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/img/pfx.svg +0 -0
  38. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/make_messages +0 -0
  39. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/manage.py +0 -0
  40. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/__init__.py +0 -0
  41. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/__init__.py +0 -0
  42. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/apps.py +0 -0
  43. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/email_backend/__init__.py +0 -0
  44. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/email_backend/memory_email_backend.py +0 -0
  45. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/email_backend/q_mailjet_email_backend.py +0 -0
  46. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/exceptions.py +0 -0
  47. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/locale/fr/LC_MESSAGES/django.mo +0 -0
  48. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/locale/fr/LC_MESSAGES/django.po +0 -0
  49. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/mailjet/__init__.py +0 -0
  50. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/mailjet/mailjet.py +0 -0
  51. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/mailjet/message_result.py +0 -0
  52. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/migrations/0001_initial.py +0 -0
  53. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/migrations/0002_alter_email_headers.py +0 -0
  54. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/migrations/0003_alter_email_options.py +0 -0
  55. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/migrations/0004_alter_email_mail_from.py +0 -0
  56. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/migrations/0005_lowercase_verbose_names.py +0 -0
  57. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/migrations/0006_alter_email_attachments.py +0 -0
  58. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/migrations/__init__.py +0 -0
  59. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/models/__init__.py +0 -0
  60. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/models/email.py +0 -0
  61. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/providers/__init__.py +0 -0
  62. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/providers/email_django_q_executor.py +0 -0
  63. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/shortcuts.py +0 -0
  64. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/tasks.py +0 -0
  65. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/templates/emails/base_template.html +0 -0
  66. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/templates/emails/base_template.txt +0 -0
  67. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/templates/emails/base_template_subject.txt +0 -0
  68. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/test.py +0 -0
  69. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/urls.py +0 -0
  70. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/views/__init__.py +0 -0
  71. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/emails/views/email_rest_view.py +0 -0
  72. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/__init__.py +0 -0
  73. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/apidoc/__init__.py +0 -0
  74. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/apidoc/parameters.py +0 -0
  75. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/apidoc/schema.py +0 -0
  76. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/apidoc/tags.py +0 -0
  77. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/apps.py +0 -0
  78. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/decorator/__init__.py +0 -0
  79. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/decorator/rest.py +0 -0
  80. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/default_settings.py +0 -0
  81. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/exceptions.py +0 -0
  82. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/fields/__init__.py +0 -0
  83. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/fields/decimal_field.py +0 -0
  84. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/fields/media_field.py +0 -0
  85. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/fields/minutes_duration_field.py +0 -0
  86. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/fields/rich_text_field.py +0 -0
  87. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/http/__init__.py +0 -0
  88. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/http/json_response.py +0 -0
  89. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/locale/fr/LC_MESSAGES/django.mo +0 -0
  90. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/locale/fr/LC_MESSAGES/django.po +0 -0
  91. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/management/__init__.py +0 -0
  92. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/management/commands/__init__.py +0 -0
  93. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/management/commands/makeapidoc.py +0 -0
  94. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/management/commands/profile.py +0 -0
  95. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/mfa/__init__.py +0 -0
  96. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/mfa/authenticator.py +0 -0
  97. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/mfa/base.py +0 -0
  98. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/mfa/email.py +0 -0
  99. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/mfa/legacy.py +0 -0
  100. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/mfa/sms.py +0 -0
  101. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/middleware/__init__.py +0 -0
  102. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/middleware/authentication.py +0 -0
  103. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/middleware/locale.py +0 -0
  104. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/middleware/profiling.py +0 -0
  105. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/middleware/request_too_big_middleware.py +0 -0
  106. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/middleware/ws_cookie_authentication_middleware.py +0 -0
  107. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/migrations/0001_initial.py +0 -0
  108. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/migrations/0002_pfxpermissionsuser.py +0 -0
  109. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/migrations/0003_delete_pfxpermissionsuser.py +0 -0
  110. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/migrations/0004_alter_loginban_failed_counter_and_more.py +0 -0
  111. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/migrations/0005_mfadevice_mfadevice_mfa_device_unique_backend.py +0 -0
  112. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/migrations/0006_alter_pfxuser_managers.py +0 -0
  113. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/migrations/0007_alter_pfxuser_options.py +0 -0
  114. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/migrations/0008_lowercase_verbose_names.py +0 -0
  115. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/migrations/__init__.py +0 -0
  116. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/migrations/operations/__init__.py +0 -0
  117. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/migrations/operations/permissions.py +0 -0
  118. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/models/__init__.py +0 -0
  119. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/models/abstract_pfx_base_user.py +0 -0
  120. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/models/attachment_mixin.py +0 -0
  121. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/models/cache_mixins.py +0 -0
  122. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/models/login_ban.py +0 -0
  123. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/models/mfa_device.py +0 -0
  124. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/models/mfa_user_mixin.py +0 -0
  125. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/models/not_null_fields.py +0 -0
  126. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/models/ordered_model_mixin.py +0 -0
  127. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/models/pfx_models.py +0 -0
  128. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/models/pfx_user.py +0 -0
  129. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/models/user_filtered_queryset_mixin.py +0 -0
  130. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/serializers/__init__.py +0 -0
  131. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/serializers/json.py +0 -0
  132. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/settings.py +0 -0
  133. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/shortcuts.py +0 -0
  134. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/sms/__init__.py +0 -0
  135. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/sms/backends/__init__.py +0 -0
  136. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/sms/backends/base.py +0 -0
  137. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/sms/backends/console.py +0 -0
  138. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/sms/backends/memory.py +0 -0
  139. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/storage/__init__.py +0 -0
  140. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/storage/exceptions.py +0 -0
  141. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/storage/local_storage.py +0 -0
  142. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/storage/s3_storage.py +0 -0
  143. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/templates/registration/otp_code_email.txt +0 -0
  144. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/templates/registration/otp_code_subject.txt +0 -0
  145. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/templates/registration/password_reset_email.txt +0 -0
  146. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/templates/registration/password_reset_subject.txt +0 -0
  147. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/templates/registration/welcome_email.txt +0 -0
  148. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/templates/registration/welcome_subject.txt +0 -0
  149. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/urls.py +0 -0
  150. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/version_check.py +0 -0
  151. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/__init__.py +0 -0
  152. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/authentication_views.py +0 -0
  153. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/fields.py +0 -0
  154. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/filters_views.py +0 -0
  155. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/locale_views.py +0 -0
  156. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/media_rest_view_mixin.py +0 -0
  157. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/mfa_authentication_views.py +0 -0
  158. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/ordered_rest_view_mixin.py +0 -0
  159. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/parameters/__init__.py +0 -0
  160. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/parameters/date_format.py +0 -0
  161. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/parameters/groups.py +0 -0
  162. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/parameters/list_count.py +0 -0
  163. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/parameters/list_items.py +0 -0
  164. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/parameters/list_mode.py +0 -0
  165. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/parameters/list_order.py +0 -0
  166. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/parameters/list_search.py +0 -0
  167. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/parameters/media_redirect.py +0 -0
  168. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/parameters/meta_fields.py +0 -0
  169. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/parameters/meta_filters.py +0 -0
  170. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/parameters/meta_orders.py +0 -0
  171. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/parameters/subset.py +0 -0
  172. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/parameters/subset_limit.py +0 -0
  173. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/parameters/subset_offset.py +0 -0
  174. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/parameters/subset_page.py +0 -0
  175. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/parameters/subset_page_size.py +0 -0
  176. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/parameters/subset_page_subset.py +0 -0
  177. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/views/rest_views.py +0 -0
  178. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/pfxcore/xml_test_runner.py +0 -0
  179. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/settings/__init__.py +0 -0
  180. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/settings/dev.py +0 -0
  181. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/userjobs/__init__.py +0 -0
  182. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/userjobs/apps.py +0 -0
  183. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/userjobs/locale/fr/LC_MESSAGES/django.mo +0 -0
  184. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/userjobs/locale/fr/LC_MESSAGES/django.po +0 -0
  185. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/userjobs/migrations/0001_initial.py +0 -0
  186. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/userjobs/migrations/0002_alter_userjob_options_alter_userjob_auto_queued_and_more.py +0 -0
  187. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/userjobs/migrations/0003_clean_scheduled_tasks.py +0 -0
  188. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/userjobs/migrations/0004_userjob_summary_url.py +0 -0
  189. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/userjobs/migrations/0005_swappable_user_job.py +0 -0
  190. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/userjobs/migrations/0006_lowercase_verbose_names.py +0 -0
  191. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/userjobs/migrations/__init__.py +0 -0
  192. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/userjobs/models/__init__.py +0 -0
  193. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/userjobs/models/user_job.py +0 -0
  194. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/userjobs/models/user_job_attachment.py +0 -0
  195. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/userjobs/providers/__init__.py +0 -0
  196. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/userjobs/providers/user_job_django_q_executor.py +0 -0
  197. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/userjobs/providers/user_job_websocket_channel_provider.py +0 -0
  198. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/userjobs/tasks.py +0 -0
  199. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/userjobs/urls.py +0 -0
  200. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/userjobs/views/__init__.py +0 -0
  201. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/userjobs/views/user_job_attachment_view.py +0 -0
  202. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/userjobs/views/user_job_view.py +0 -0
  203. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pfx/userjobs/views/user_websocket_consumer.py +0 -0
  204. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/pyproject.toml +0 -0
  205. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/serve-doc +0 -0
  206. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/setup.cfg +0 -0
  207. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/setup.py +0 -0
  208. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/__init__.py +0 -0
  209. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/apps.py +0 -0
  210. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/channel_group_send_calls.py +0 -0
  211. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/locale/fr/LC_MESSAGES/django.po +0 -0
  212. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/mfa_urls.py +0 -0
  213. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/migrations/0001_initial.py +0 -0
  214. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/migrations/__init__.py +0 -0
  215. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/models.py +0 -0
  216. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/settings/__init__.py +0 -0
  217. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/settings/ci.py +0 -0
  218. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/settings/common.py +0 -0
  219. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/settings/dev.py +0 -0
  220. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/settings/dev_custom_example.py +0 -0
  221. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/settings/dev_default.py +0 -0
  222. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/__init__.py +0 -0
  223. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/basic_api_errors.py +0 -0
  224. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/basic_api_test.py +0 -0
  225. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/mfa_test_utils.py +0 -0
  226. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_api_doc.py +0 -0
  227. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_api_doc_search.py +0 -0
  228. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_auth_api.py +0 -0
  229. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_body_mixin.py +0 -0
  230. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_cache.py +0 -0
  231. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_client.py +0 -0
  232. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_emails_email_api.py +0 -0
  233. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_emails_email_model.py +0 -0
  234. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_emails_q_mailjet_email_backend.py +0 -0
  235. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_emails_send_email_message.py +0 -0
  236. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_emails_test_tools.py +0 -0
  237. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_fields_choices.py +0 -0
  238. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_fields_date.py +0 -0
  239. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_fields_decimal.py +0 -0
  240. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_fields_help_text.py +0 -0
  241. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_fields_minutes_duration.py +0 -0
  242. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_fields_one2many.py +0 -0
  243. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_fields_rich_text.py +0 -0
  244. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_fields_time.py +0 -0
  245. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_filters.py +0 -0
  246. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_locale_api.py +0 -0
  247. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_mfa_legacy.py +0 -0
  248. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_mfa_login_api.py +0 -0
  249. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_mfa_setup_api.py +0 -0
  250. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_ordered_rest_view_mixin.py +0 -0
  251. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_perm_tests.py +0 -0
  252. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_permissions.py +0 -0
  253. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_perms_api.py +0 -0
  254. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_post_migrate_groups_update.py +0 -0
  255. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_profiling_middleware.py +0 -0
  256. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_settings.py +0 -0
  257. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_shortcuts.py +0 -0
  258. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_timezone_middleware.py +0 -0
  259. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_tools.py +0 -0
  260. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_user_job_api.py +0 -0
  261. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_user_job_messages.py +0 -0
  262. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_user_job_model.py +0 -0
  263. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_user_queryset.py +0 -0
  264. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_user_websocket.py +0 -0
  265. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_verbose_names.py +0 -0
  266. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_version_check.py +0 -0
  267. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_view_decorators.py +0 -0
  268. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_view_fields.py +0 -0
  269. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/tests/test_ws_cookie_middleware.py +0 -0
  270. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/urls.py +0 -0
  271. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests/views.py +0 -0
  272. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_base_user/__init__.py +0 -0
  273. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_base_user/migrations/__init__.py +0 -0
  274. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_base_user/settings/__init__.py +0 -0
  275. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_base_user/settings/ci.py +0 -0
  276. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_base_user/settings/common.py +0 -0
  277. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_base_user/settings/dev.py +0 -0
  278. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_base_user/settings/dev_custom_example.py +0 -0
  279. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_base_user/settings/dev_default.py +0 -0
  280. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_base_user/tests/__init__.py +0 -0
  281. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_base_user/tests/test_api.py +0 -0
  282. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_base_user/tests/test_auth_api.py +0 -0
  283. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_base_user/urls.py +0 -0
  284. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_base_user/views.py +0 -0
  285. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user/__init__.py +0 -0
  286. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user/migrations/0001_initial.py +0 -0
  287. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user/migrations/__init__.py +0 -0
  288. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user/models.py +0 -0
  289. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user/settings/__init__.py +0 -0
  290. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user/settings/ci.py +0 -0
  291. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user/settings/common.py +0 -0
  292. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user/settings/dev.py +0 -0
  293. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user/settings/dev_custom_example.py +0 -0
  294. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user/settings/dev_default.py +0 -0
  295. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user/tests/__init__.py +0 -0
  296. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user/tests/test_api.py +0 -0
  297. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user/tests/test_auth_api.py +0 -0
  298. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user/urls.py +0 -0
  299. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user/views.py +0 -0
  300. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user_job/__init__.py +0 -0
  301. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user_job/migrations/0001_initial.py +0 -0
  302. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user_job/migrations/0002_lowercase_verbose_names.py +0 -0
  303. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user_job/migrations/__init__.py +0 -0
  304. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user_job/models.py +0 -0
  305. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user_job/providers.py +0 -0
  306. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user_job/scope.py +0 -0
  307. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user_job/settings/__init__.py +0 -0
  308. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user_job/settings/ci.py +0 -0
  309. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user_job/settings/common.py +0 -0
  310. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user_job/settings/dev.py +0 -0
  311. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user_job/settings/dev_custom_example.py +0 -0
  312. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user_job/settings/dev_default.py +0 -0
  313. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user_job/tests/__init__.py +0 -0
  314. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user_job/tests/test_user_job.py +0 -0
  315. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_custom_user_job/urls.py +0 -0
  316. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_user_email_login/__init__.py +0 -0
  317. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_user_email_login/migrations/0001_initial.py +0 -0
  318. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_user_email_login/migrations/__init__.py +0 -0
  319. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_user_email_login/models.py +0 -0
  320. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_user_email_login/settings/__init__.py +0 -0
  321. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_user_email_login/settings/ci.py +0 -0
  322. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_user_email_login/settings/common.py +0 -0
  323. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_user_email_login/settings/dev.py +0 -0
  324. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_user_email_login/settings/dev_custom_example.py +0 -0
  325. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_user_email_login/settings/dev_default.py +0 -0
  326. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_user_email_login/tests/__init__.py +0 -0
  327. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_user_email_login/tests/test_api.py +0 -0
  328. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_user_email_login/tests/test_auth_api.py +0 -0
  329. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_user_email_login/urls.py +0 -0
  330. {django_pfx-1.7.6.dev35 → django_pfx-1.7.6.dev37}/tests_user_email_login/views.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-pfx
3
- Version: 1.7.6.dev35
3
+ Version: 1.7.6.dev37
4
4
  Summary: Django PFX is a toolkit designed to streamline the development of RESTful APIs using the Django framework.
5
5
  Author: Hervé Martinet
6
6
  Author-email: herve.martinet@gmail.com
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-pfx
3
- Version: 1.7.6.dev35
3
+ Version: 1.7.6.dev37
4
4
  Summary: Django PFX is a toolkit designed to streamline the development of RESTful APIs using the Django framework.
5
5
  Author: Hervé Martinet
6
6
  Author-email: herve.martinet@gmail.com
@@ -220,6 +220,7 @@ tests/tests/__init__.py
220
220
  tests/tests/basic_api_errors.py
221
221
  tests/tests/basic_api_test.py
222
222
  tests/tests/mfa_test_utils.py
223
+ tests/tests/parallel_scenarios.py
223
224
  tests/tests/test_api_doc.py
224
225
  tests/tests/test_api_doc_search.py
225
226
  tests/tests/test_auth_api.py
@@ -210,6 +210,7 @@
210
210
  "tests/tests/basic_api_errors.py",
211
211
  "tests/tests/basic_api_test.py",
212
212
  "tests/tests/mfa_test_utils.py",
213
+ "tests/tests/parallel_scenarios.py",
213
214
  "tests/tests/test_api_doc.py",
214
215
  "tests/tests/test_api_doc_search.py",
215
216
  "tests/tests/test_auth_api.py",
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "1.7.5",
3
+ "distance": 37,
4
+ "node": "g213d2ffb86d53a7b1417f5fa4929daa928146735",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-10-20"
8
+ }
@@ -1,6 +1,8 @@
1
+ import copy
1
2
  import json
2
3
  import logging
3
4
  import re
5
+ import traceback
4
6
  from functools import reduce
5
7
  from http.cookies import SimpleCookie
6
8
  from json import JSONDecodeError
@@ -9,7 +11,12 @@ from django.apps import apps
9
11
  from django.db import transaction
10
12
  from django.test import override_settings
11
13
  from django.test.client import Client as DjangoClient
12
- from django.test.runner import DiscoverRunner, ParallelTestSuite
14
+ from django.test.runner import (
15
+ DiscoverRunner,
16
+ ParallelTestSuite,
17
+ RemoteTestResult,
18
+ RemoteTestRunner,
19
+ )
13
20
  from django.test.runner import _init_worker as django_init_worker
14
21
  from django.utils.module_loading import import_string
15
22
 
@@ -351,8 +358,72 @@ def _init_worker(*args, **kwargs):
351
358
  override_settings(**get_test_backends()).enable()
352
359
 
353
360
 
361
+ class UnpicklableTestError(Exception):
362
+ """An error a parallel worker could not send back, as text."""
363
+
364
+
365
+ class UnpicklableTestFailure(UnpicklableTestError, AssertionError):
366
+ """A failure a parallel worker could not send back, as text."""
367
+
368
+
369
+ class _Repr(str):
370
+ def __repr__(self):
371
+ return str(self)
372
+
373
+
374
+ class PicklableRemoteTestResult(RemoteTestResult):
375
+ """Send every outcome of a parallel worker back to the parent.
376
+
377
+ Django aborts the whole run, without the traceback, on an exception it
378
+ cannot pickle (one holding a request, a lock, a local class…). Such an
379
+ exception is sent as its formatted traceback instead, and the run goes
380
+ on."""
381
+
382
+ def _picklable(self, err):
383
+ try:
384
+ self._confirm_picklable(err)
385
+ except Exception:
386
+ cls = (
387
+ UnpicklableTestFailure if issubclass(err[0], AssertionError)
388
+ else UnpicklableTestError)
389
+ return cls, cls(''.join(traceback.format_exception(*err))), None
390
+ return err
391
+
392
+ def _picklable_subtest(self, test, subtest):
393
+ # The subtest holds the running test case, which can become
394
+ # unpicklable after the failure: a fresh one is always sent.
395
+ subtest = copy.copy(subtest)
396
+ subtest.test_case = type(test)(test._testMethodName)
397
+ try:
398
+ self._confirm_picklable(subtest)
399
+ except Exception:
400
+ subtest.params = {
401
+ k: _Repr(repr(v)) for k, v in subtest.params.items()}
402
+ return subtest
403
+
404
+ def addError(self, test, err):
405
+ super().addError(test, self._picklable(err))
406
+
407
+ def addFailure(self, test, err):
408
+ super().addFailure(test, self._picklable(err))
409
+
410
+ def addExpectedFailure(self, test, err):
411
+ super().addExpectedFailure(test, self._picklable(err))
412
+
413
+ def addSubTest(self, test, subtest, err):
414
+ if err is not None:
415
+ err = self._picklable(err)
416
+ subtest = self._picklable_subtest(test, subtest)
417
+ super().addSubTest(test, subtest, err)
418
+
419
+
420
+ class PicklableRemoteTestRunner(RemoteTestRunner):
421
+ resultclass = PicklableRemoteTestResult
422
+
423
+
354
424
  class MemoryBackendsParallelTestSuite(ParallelTestSuite):
355
425
  init_worker = _init_worker
426
+ runner_class = PicklableRemoteTestRunner
356
427
 
357
428
 
358
429
  class MemoryBackendsRunnerMixin:
@@ -371,7 +442,10 @@ class MemoryBackendsRunnerMixin:
371
442
  validated, which ``locmem`` never does.
372
443
 
373
444
  A test class decorated with ``override_settings`` keeps its own
374
- backends."""
445
+ backends.
446
+
447
+ With ``--parallel``, the workers also send back the errors Django
448
+ cannot pickle (see :class:`PicklableRemoteTestResult`)."""
375
449
 
376
450
  parallel_test_suite = MemoryBackendsParallelTestSuite
377
451
 
@@ -4,6 +4,8 @@ pre-commit
4
4
  flake8
5
5
  isort
6
6
  coverage
7
+ # Pickles the tracebacks of the --parallel workers.
8
+ tblib
7
9
  psycopg
8
10
  Babel
9
11
  pyjwt>=2.1
@@ -0,0 +1,89 @@
1
+ """Test cases that fail in ways a parallel worker cannot pickle.
2
+
3
+ Run by test_test_runner.py, not by the discovery (the name does not start
4
+ with ``test``). They live at module level as real test classes do: the
5
+ parent process rebuilds a test case from its class."""
6
+ import threading
7
+ import unittest
8
+
9
+
10
+ class Unpicklable(Exception):
11
+ def __init__(self):
12
+ super().__init__("holds a lock")
13
+ self.lock = threading.Lock()
14
+
15
+
16
+ class KeywordOnly(Exception):
17
+ """Pickles, but cannot be rebuilt from its args."""
18
+
19
+ def __init__(self, *, code):
20
+ super().__init__(f"code {code}")
21
+ self.code = code
22
+
23
+
24
+ class UnpicklableAssertion(AssertionError):
25
+ def __init__(self):
26
+ super().__init__("assertion holding a lock")
27
+ self.lock = threading.Lock()
28
+
29
+
30
+ class Scenarios(unittest.TestCase):
31
+
32
+ def test_plain_failure(self):
33
+ self.assertEqual(1, 2)
34
+
35
+ def test_lock_in_the_exception(self):
36
+ raise Unpicklable()
37
+
38
+ def test_unpicklable_cause(self):
39
+ try:
40
+ raise Unpicklable()
41
+ except Unpicklable as e:
42
+ raise ValueError("wrapped") from e
43
+
44
+ def test_local_class(self):
45
+ class Local(Exception):
46
+ pass
47
+ raise Local("local class")
48
+
49
+ def test_keyword_only_init(self):
50
+ raise KeywordOnly(code=42)
51
+
52
+ def test_unpicklable_assertion(self):
53
+ raise UnpicklableAssertion()
54
+
55
+ @unittest.expectedFailure
56
+ def test_expected_failure(self):
57
+ raise Unpicklable()
58
+
59
+ def test_subtest_then_a_lock(self):
60
+ with self.subTest(i=1):
61
+ self.assertEqual(1, 5)
62
+ self.lock = threading.Lock()
63
+
64
+ def test_subtest_with_a_lock_param(self):
65
+ with self.subTest(lock=threading.Lock()):
66
+ self.fail("with a lock as param")
67
+
68
+ def test_subtest_unpicklable_error(self):
69
+ with self.subTest(n=1):
70
+ raise Unpicklable()
71
+
72
+
73
+ class TearDownError(unittest.TestCase):
74
+
75
+ def tearDown(self):
76
+ raise Unpicklable()
77
+
78
+ def test_ok(self):
79
+ pass
80
+
81
+
82
+ class SetUpClassError(unittest.TestCase):
83
+
84
+ @classmethod
85
+ def setUpClass(cls):
86
+ raise Unpicklable()
87
+
88
+ def test_never_runs(self):
89
+ pass
@@ -0,0 +1,234 @@
1
+ import io
2
+ import pickle
3
+ import re
4
+ import unittest
5
+ from contextlib import redirect_stdout
6
+ from unittest.mock import patch
7
+
8
+ from django.conf import settings
9
+ from django.test import SimpleTestCase, override_settings
10
+ from django.test.runner import RemoteTestRunner
11
+ from django.test.utils import setup_test_environment, teardown_test_environment
12
+
13
+ from pfx.pfxcore.settings import settings as pfx_settings
14
+ from pfx.pfxcore.sms import get_sms_backend
15
+ from pfx.pfxcore.sms.backends.memory import MemorySMSBackend
16
+ from pfx.pfxcore.test import (
17
+ MemoryBackendsParallelTestSuite,
18
+ MemoryBackendsRunnerMixin,
19
+ PicklableRemoteTestResult,
20
+ PicklableRemoteTestRunner,
21
+ SMSTestMixin,
22
+ TestRunner,
23
+ _init_worker,
24
+ get_test_backends,
25
+ )
26
+
27
+ from . import parallel_scenarios
28
+
29
+ MEMORY_EMAIL = 'pfx.emails.email_backend.MemoryEmailBackend'
30
+ MEMORY_SMS = 'pfx.pfxcore.sms.backends.memory.MemorySMSBackend'
31
+
32
+
33
+ class TestMemoryBackendsRunner(SimpleTestCase):
34
+
35
+ def test_the_runner_replaces_the_backends(self):
36
+ """The runner swaps the backends for the whole run, and puts the
37
+ original ones back at the end, locmem restored by Django included.
38
+
39
+ The test environment of the current run is torn down first, as
40
+ Django refuses to set it up twice, and restored afterwards."""
41
+ teardown_test_environment()
42
+ try:
43
+ email = settings.EMAIL_BACKEND
44
+ sms = pfx_settings.PFX_SMS_BACKEND
45
+ runner = TestRunner()
46
+ runner.setup_test_environment()
47
+ try:
48
+ self.assertEqual(settings.EMAIL_BACKEND, MEMORY_EMAIL)
49
+ self.assertEqual(pfx_settings.PFX_SMS_BACKEND, MEMORY_SMS)
50
+ finally:
51
+ runner.teardown_test_environment()
52
+ self.assertEqual(settings.EMAIL_BACKEND, email)
53
+ self.assertEqual(pfx_settings.PFX_SMS_BACKEND, sms)
54
+ finally:
55
+ setup_test_environment(debug=False)
56
+
57
+ def test_the_parallel_workers_get_the_backends(self):
58
+ """A spawned worker sets up the test environment again, locmem
59
+ included: the suite of the runner uses a worker init that puts the
60
+ backends back."""
61
+ self.assertIs(
62
+ TestRunner.parallel_test_suite, MemoryBackendsParallelTestSuite)
63
+ self.assertIs(
64
+ MemoryBackendsParallelTestSuite.init_worker, _init_worker)
65
+
66
+ def test_the_backends_are_configurable(self):
67
+ self.assertEqual(get_test_backends(), dict(
68
+ EMAIL_BACKEND=MEMORY_EMAIL, PFX_SMS_BACKEND=MEMORY_SMS))
69
+ with override_settings(
70
+ PFX_TEST_EMAIL_BACKEND='my.EmailBackend',
71
+ PFX_TEST_SMS_BACKEND='my.SMSBackend'):
72
+ self.assertEqual(get_test_backends(), dict(
73
+ EMAIL_BACKEND='my.EmailBackend',
74
+ PFX_SMS_BACKEND='my.SMSBackend'))
75
+
76
+ def test_the_email_backend_needs_pfx_emails(self):
77
+ """Without pfx.emails, there is no email model to fill: locmem
78
+ stays."""
79
+ with patch('pfx.pfxcore.test.apps.is_installed', return_value=False):
80
+ self.assertEqual(
81
+ get_test_backends(), dict(PFX_SMS_BACKEND=MEMORY_SMS))
82
+
83
+
84
+ def run_in_worker(runner_class, *tests):
85
+ """Run the tests as a parallel worker does, send its events through
86
+ pickle as multiprocessing does, and replay them in a parent result.
87
+
88
+ The tests are listed before the run: the suite drops them as they
89
+ run."""
90
+ suite = unittest.TestSuite(tests)
91
+ listed = list(suite)
92
+ events = pickle.loads(pickle.dumps(runner_class().run(suite).events))
93
+ parent = unittest.TestResult()
94
+ for event in events:
95
+ MemoryBackendsParallelTestSuite([], 1).handle_event(
96
+ parent, listed, event)
97
+ return parent
98
+
99
+
100
+ def outcomes(results):
101
+ """{test id without its module: last line of the traceback}
102
+
103
+ The ``[<object object at 0x…>]`` of a subtest without message is left
104
+ out: unittest compares its message to a sentinel object, which does not
105
+ survive pickling, in Django as here."""
106
+ prefix = f'{parallel_scenarios.__name__}.'
107
+ return {
108
+ re.sub(r' \[<object object at 0x\w+>\]', '', test.id())
109
+ .removeprefix(prefix): text.strip().splitlines()[-1]
110
+ for test, text in results}
111
+
112
+
113
+ class TestPicklableRemoteTestResult(SimpleTestCase):
114
+
115
+ def test_the_runners_use_it(self):
116
+ self.assertIs(
117
+ MemoryBackendsParallelTestSuite.runner_class,
118
+ PicklableRemoteTestRunner)
119
+
120
+ def test_django_aborts_on_an_unpicklable_error(self):
121
+ """Why this result exists: the Django one lets the pickling error
122
+ rise, which aborts the whole run in the parent process."""
123
+ with redirect_stdout(io.StringIO()), self.assertRaises(TypeError):
124
+ run_in_worker(RemoteTestRunner, parallel_scenarios.Scenarios(
125
+ 'test_lock_in_the_exception'))
126
+
127
+ def test_every_outcome_is_sent_back(self):
128
+ """Each way of failing Django cannot pickle reaches the parent,
129
+ under its test, as an error or a failure as it was raised, with
130
+ the original exception at the end of the traceback."""
131
+ names = unittest.TestLoader().getTestCaseNames(
132
+ parallel_scenarios.Scenarios)
133
+ parent = run_in_worker(
134
+ PicklableRemoteTestRunner,
135
+ *map(parallel_scenarios.Scenarios, names),
136
+ parallel_scenarios.TearDownError('test_ok'))
137
+ module = parallel_scenarios.__name__
138
+ lock = f'{module}.Unpicklable: holds a lock'
139
+ self.assertEqual(outcomes(parent.errors), {
140
+ 'Scenarios.test_keyword_only_init':
141
+ f'{module}.KeywordOnly: code 42',
142
+ 'Scenarios.test_local_class':
143
+ f'{module}.Scenarios.test_local_class.<locals>.Local: '
144
+ 'local class',
145
+ 'Scenarios.test_lock_in_the_exception': lock,
146
+ 'Scenarios.test_subtest_unpicklable_error (n=1)': lock,
147
+ 'Scenarios.test_unpicklable_cause': 'ValueError: wrapped',
148
+ 'TearDownError.test_ok': lock,
149
+ })
150
+ [cause] = [
151
+ text for test, text in parent.errors
152
+ if test.id().endswith('test_unpicklable_cause')]
153
+ self.assertIn(lock, cause)
154
+ failures = outcomes(parent.failures)
155
+ # The lock of the subtest params is sent as its repr.
156
+ [lock_param] = [
157
+ k for k in failures if k.startswith(
158
+ 'Scenarios.test_subtest_with_a_lock_param (lock=<unlocked')]
159
+ self.assertEqual(failures, {
160
+ 'Scenarios.test_plain_failure': 'AssertionError: 1 != 2',
161
+ 'Scenarios.test_subtest_then_a_lock (i=1)':
162
+ 'AssertionError: 1 != 5',
163
+ lock_param: 'AssertionError: with a lock as param',
164
+ 'Scenarios.test_unpicklable_assertion':
165
+ f'{module}.UnpicklableAssertion: assertion holding a lock',
166
+ })
167
+ self.assertEqual(
168
+ list(outcomes(parent.expectedFailures)),
169
+ ['Scenarios.test_expected_failure'])
170
+
171
+ def test_a_class_fixture_error_is_sent_back(self):
172
+ """Django sends each class in its own subsuite: a setUpClass error
173
+ comes before the first test, and is reported under the class."""
174
+ parent = run_in_worker(
175
+ PicklableRemoteTestRunner,
176
+ parallel_scenarios.SetUpClassError('test_never_runs'))
177
+ module = parallel_scenarios.__name__
178
+ self.assertEqual(outcomes(parent.errors), {
179
+ f'setUpClass ({module}.SetUpClassError)':
180
+ f'{module}.Unpicklable: holds a lock'})
181
+
182
+ def test_a_picklable_error_is_sent_as_is(self):
183
+ """What pickles goes through untouched, as with Django.
184
+
185
+ Checked without a traceback: a traceback only pickles with tblib,
186
+ and without it every error is sent as text (where Django aborts
187
+ the run and asks for tblib)."""
188
+ err = (AssertionError, AssertionError('1 != 2'), None)
189
+ self.assertIs(PicklableRemoteTestResult()._picklable(err), err)
190
+
191
+
192
+ @override_settings(PFX_SMS_BACKEND=MEMORY_SMS)
193
+ class TestSMSTestMixin(SMSTestMixin, SimpleTestCase):
194
+
195
+ def test_the_sms_are_collected(self):
196
+ get_sms_backend().send_sms('+41791234567', 'Code: 123456')
197
+ self.assertEqual(
198
+ self.sms_outbox(), [('+41791234567', 'Code: 123456')])
199
+ self.clear_sms_outbox()
200
+ self.assertEqual(self.sms_outbox(), [])
201
+
202
+ def test_the_outbox_is_emptied_before_each_test(self):
203
+ """An SMS left by a previous test is gone when the next starts."""
204
+ class ATest(SMSTestMixin, SimpleTestCase):
205
+ def test(self):
206
+ self.outbox_at_start = self.sms_outbox()
207
+
208
+ MemorySMSBackend.outbox.append(('+41791234567', 'Left over'))
209
+ test = ATest('test')
210
+ result = unittest.TestResult()
211
+ test(result)
212
+ self.assertTrue(result.wasSuccessful(), result.errors)
213
+ self.assertEqual(test.outbox_at_start, [])
214
+
215
+ @override_settings(
216
+ PFX_SMS_BACKEND='pfx.pfxcore.sms.backends.console.ConsoleSMSBackend')
217
+ def test_the_helpers_refuse_another_backend(self):
218
+ with self.assertRaises(AssertionError):
219
+ self.sms_outbox()
220
+
221
+
222
+ class TestXMLTestRunner(SimpleTestCase):
223
+
224
+ def test_the_xml_runner_replaces_the_backends(self):
225
+ """The XML variant is the same runner: same backends, same parallel
226
+ workers, and the XML reports."""
227
+ from xmlrunner.extra.djangotestrunner import XMLTestRunner as Base
228
+
229
+ from pfx.pfxcore.xml_test_runner import XMLTestRunner
230
+
231
+ self.assertTrue(issubclass(XMLTestRunner, Base))
232
+ self.assertTrue(issubclass(XMLTestRunner, MemoryBackendsRunnerMixin))
233
+ self.assertIs(
234
+ XMLTestRunner.parallel_test_suite, MemoryBackendsParallelTestSuite)
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "1.7.5",
3
- "distance": 35,
4
- "node": "gb6a06c83048f8ebb878d880aa41c71f04adb2127",
5
- "dirty": false,
6
- "branch": "HEAD",
7
- "node_date": "2026-10-19"
8
- }
@@ -1,117 +0,0 @@
1
- import unittest
2
- from unittest.mock import patch
3
-
4
- from django.conf import settings
5
- from django.test import SimpleTestCase, override_settings
6
- from django.test.utils import setup_test_environment, teardown_test_environment
7
-
8
- from pfx.pfxcore.settings import settings as pfx_settings
9
- from pfx.pfxcore.sms import get_sms_backend
10
- from pfx.pfxcore.sms.backends.memory import MemorySMSBackend
11
- from pfx.pfxcore.test import (
12
- MemoryBackendsParallelTestSuite,
13
- MemoryBackendsRunnerMixin,
14
- SMSTestMixin,
15
- TestRunner,
16
- _init_worker,
17
- get_test_backends,
18
- )
19
-
20
- MEMORY_EMAIL = 'pfx.emails.email_backend.MemoryEmailBackend'
21
- MEMORY_SMS = 'pfx.pfxcore.sms.backends.memory.MemorySMSBackend'
22
-
23
-
24
- class TestMemoryBackendsRunner(SimpleTestCase):
25
-
26
- def test_the_runner_replaces_the_backends(self):
27
- """The runner swaps the backends for the whole run, and puts the
28
- original ones back at the end, locmem restored by Django included.
29
-
30
- The test environment of the current run is torn down first, as
31
- Django refuses to set it up twice, and restored afterwards."""
32
- teardown_test_environment()
33
- try:
34
- email = settings.EMAIL_BACKEND
35
- sms = pfx_settings.PFX_SMS_BACKEND
36
- runner = TestRunner()
37
- runner.setup_test_environment()
38
- try:
39
- self.assertEqual(settings.EMAIL_BACKEND, MEMORY_EMAIL)
40
- self.assertEqual(pfx_settings.PFX_SMS_BACKEND, MEMORY_SMS)
41
- finally:
42
- runner.teardown_test_environment()
43
- self.assertEqual(settings.EMAIL_BACKEND, email)
44
- self.assertEqual(pfx_settings.PFX_SMS_BACKEND, sms)
45
- finally:
46
- setup_test_environment(debug=False)
47
-
48
- def test_the_parallel_workers_get_the_backends(self):
49
- """A spawned worker sets up the test environment again, locmem
50
- included: the suite of the runner uses a worker init that puts the
51
- backends back."""
52
- self.assertIs(
53
- TestRunner.parallel_test_suite, MemoryBackendsParallelTestSuite)
54
- self.assertIs(
55
- MemoryBackendsParallelTestSuite.init_worker, _init_worker)
56
-
57
- def test_the_backends_are_configurable(self):
58
- self.assertEqual(get_test_backends(), dict(
59
- EMAIL_BACKEND=MEMORY_EMAIL, PFX_SMS_BACKEND=MEMORY_SMS))
60
- with override_settings(
61
- PFX_TEST_EMAIL_BACKEND='my.EmailBackend',
62
- PFX_TEST_SMS_BACKEND='my.SMSBackend'):
63
- self.assertEqual(get_test_backends(), dict(
64
- EMAIL_BACKEND='my.EmailBackend',
65
- PFX_SMS_BACKEND='my.SMSBackend'))
66
-
67
- def test_the_email_backend_needs_pfx_emails(self):
68
- """Without pfx.emails, there is no email model to fill: locmem
69
- stays."""
70
- with patch('pfx.pfxcore.test.apps.is_installed', return_value=False):
71
- self.assertEqual(
72
- get_test_backends(), dict(PFX_SMS_BACKEND=MEMORY_SMS))
73
-
74
-
75
- @override_settings(PFX_SMS_BACKEND=MEMORY_SMS)
76
- class TestSMSTestMixin(SMSTestMixin, SimpleTestCase):
77
-
78
- def test_the_sms_are_collected(self):
79
- get_sms_backend().send_sms('+41791234567', 'Code: 123456')
80
- self.assertEqual(
81
- self.sms_outbox(), [('+41791234567', 'Code: 123456')])
82
- self.clear_sms_outbox()
83
- self.assertEqual(self.sms_outbox(), [])
84
-
85
- def test_the_outbox_is_emptied_before_each_test(self):
86
- """An SMS left by a previous test is gone when the next starts."""
87
- class ATest(SMSTestMixin, SimpleTestCase):
88
- def test(self):
89
- self.outbox_at_start = self.sms_outbox()
90
-
91
- MemorySMSBackend.outbox.append(('+41791234567', 'Left over'))
92
- test = ATest('test')
93
- result = unittest.TestResult()
94
- test(result)
95
- self.assertTrue(result.wasSuccessful(), result.errors)
96
- self.assertEqual(test.outbox_at_start, [])
97
-
98
- @override_settings(
99
- PFX_SMS_BACKEND='pfx.pfxcore.sms.backends.console.ConsoleSMSBackend')
100
- def test_the_helpers_refuse_another_backend(self):
101
- with self.assertRaises(AssertionError):
102
- self.sms_outbox()
103
-
104
-
105
- class TestXMLTestRunner(SimpleTestCase):
106
-
107
- def test_the_xml_runner_replaces_the_backends(self):
108
- """The XML variant is the same runner: same backends, same parallel
109
- workers, and the XML reports."""
110
- from xmlrunner.extra.djangotestrunner import XMLTestRunner as Base
111
-
112
- from pfx.pfxcore.xml_test_runner import XMLTestRunner
113
-
114
- self.assertTrue(issubclass(XMLTestRunner, Base))
115
- self.assertTrue(issubclass(XMLTestRunner, MemoryBackendsRunnerMixin))
116
- self.assertIs(
117
- XMLTestRunner.parallel_test_suite, MemoryBackendsParallelTestSuite)