django-migration-zero 2.0.2__tar.gz → 2.1.0__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 (75) hide show
  1. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/.ambient-package-update/templates/snippets/installation.tpl +9 -5
  2. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/.pre-commit-config.yaml +8 -0
  3. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/CHANGES.md +8 -0
  4. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/PKG-INFO +11 -7
  5. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/README.md +9 -5
  6. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/django_migration_zero/__init__.py +1 -1
  7. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/django_migration_zero/helpers/file_system.py +17 -16
  8. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/django_migration_zero/services/local.py +14 -6
  9. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/docs/features/02_configuration.md +2 -9
  10. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/manage.py +1 -1
  11. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/pyproject.toml +1 -1
  12. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/settings.py +1 -2
  13. django_migration_zero-2.1.0/tests/helpers/test_file_system.py +81 -0
  14. django_migration_zero-2.1.0/tests/management/commands/__init__.py +0 -0
  15. django_migration_zero-2.1.0/tests/services/__init__.py +0 -0
  16. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/tests/services/test_local.py +21 -6
  17. django_migration_zero-2.0.2/django_migration_zero/settings.py +0 -19
  18. django_migration_zero-2.0.2/tests/helpers/test_file_system.py +0 -49
  19. django_migration_zero-2.0.2/tests/test_settings.py +0 -18
  20. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/.ambient-package-update/metadata.py +0 -0
  21. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/.ambient-package-update/templates/snippets/content.tpl +0 -0
  22. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/.ambient-package-update/templates/snippets/tagline.tpl +0 -0
  23. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/.coveragerc +0 -0
  24. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/.editorconfig +0 -0
  25. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/.github/workflows/ci.yml +0 -0
  26. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/.gitignore +0 -0
  27. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/.readthedocs.yaml +0 -0
  28. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/LICENSE.md +0 -0
  29. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/MANIFEST.in +0 -0
  30. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/django_migration_zero/admin.py +0 -0
  31. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/django_migration_zero/apps.py +0 -0
  32. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/django_migration_zero/exceptions.py +0 -0
  33. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/django_migration_zero/helpers/__init__.py +0 -0
  34. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/django_migration_zero/helpers/logger.py +0 -0
  35. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/django_migration_zero/locale/de/LC_MESSAGES/django.mo +0 -0
  36. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/django_migration_zero/locale/de/LC_MESSAGES/django.po +0 -0
  37. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/django_migration_zero/management/__init__.py +0 -0
  38. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/django_migration_zero/management/commands/__init__.py +0 -0
  39. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/django_migration_zero/management/commands/handle_migration_zero_reset.py +0 -0
  40. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/django_migration_zero/management/commands/reset_local_migration_files.py +0 -0
  41. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/django_migration_zero/managers.py +0 -0
  42. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/django_migration_zero/migrations/0001_initial.py +0 -0
  43. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/django_migration_zero/migrations/__init__.py +0 -0
  44. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/django_migration_zero/models.py +0 -0
  45. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/django_migration_zero/services/__init__.py +0 -0
  46. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/django_migration_zero/services/deployment.py +0 -0
  47. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/docs/Makefile +0 -0
  48. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/docs/conf.py +0 -0
  49. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/docs/features/01_introduction.md +0 -0
  50. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/docs/features/03_workflow.md +0 -0
  51. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/docs/features/04_common_issues_and_solutions.md +0 -0
  52. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/docs/features/05_architecture.md +0 -0
  53. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/docs/features/06_management_commands.md +0 -0
  54. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/docs/features/07_changelog.rst +0 -0
  55. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/docs/index.rst +0 -0
  56. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/docs/make.bat +0 -0
  57. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/scripts/unix/install_requirements.sh +0 -0
  58. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/scripts/unix/publish_to_pypi.sh +0 -0
  59. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/scripts/windows/install_requirements.ps1 +0 -0
  60. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/scripts/windows/publish_to_pypi.ps1 +0 -0
  61. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/setup.cfg +0 -0
  62. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/testapp/__init__.py +0 -0
  63. {django_migration_zero-2.0.2/tests → django_migration_zero-2.1.0/testapp/nested_app}/__init__.py +0 -0
  64. {django_migration_zero-2.0.2/tests/helpers → django_migration_zero-2.1.0/testapp/nested_app/migrations}/__init__.py +0 -0
  65. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/testapp/urls.py +0 -0
  66. {django_migration_zero-2.0.2/tests/management → django_migration_zero-2.1.0/tests}/__init__.py +0 -0
  67. {django_migration_zero-2.0.2/tests/management/commands → django_migration_zero-2.1.0/tests/helpers}/__init__.py +0 -0
  68. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/tests/helpers/test_logger.py +0 -0
  69. {django_migration_zero-2.0.2/tests/services → django_migration_zero-2.1.0/tests/management}/__init__.py +0 -0
  70. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/tests/management/commands/test_handle_migration_zero_reset.py +0 -0
  71. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/tests/management/commands/test_reset_local_migration_files.py +0 -0
  72. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/tests/services/test_deployment.py +0 -0
  73. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/tests/test_admin.py +0 -0
  74. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/tests/test_managers.py +0 -0
  75. {django_migration_zero-2.0.2 → django_migration_zero-2.1.0}/tests/test_models.py +0 -0
@@ -26,9 +26,13 @@
26
26
  - Add this block to your loggers in your main Django `settings.py` to show logs in your console.
27
27
 
28
28
  ```python
29
- "django_migration_zero": {
30
- "handlers": ["console"],
31
- "level": "INFO",
32
- "propagate": True,
33
- },
29
+ LOGGING = {
30
+ "loggers": {
31
+ "django_migration_zero": {
32
+ "handlers": ["console"],
33
+ "level": "INFO",
34
+ "propagate": True,
35
+ },
36
+ },
37
+ }
34
38
  ```
@@ -11,6 +11,14 @@ repos:
11
11
  # Run the Ruff formatter.
12
12
  - id: ruff-format
13
13
 
14
+ - repo: https://github.com/adamchainz/blacken-docs
15
+ rev: 1.16.0
16
+ hooks:
17
+ - id: blacken-docs
18
+ additional_dependencies:
19
+ - black==24.4.2
20
+ files: '(?:README\.md|docs\/.*\.(?:md|rst))'
21
+
14
22
  - repo: https://github.com/asottile/pyupgrade
15
23
  rev: v3.16.0
16
24
  hooks:
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ * *2.1.0* (2024-07-09)
4
+ * Discover apps in nested directories
5
+ * Use `BASE_DIR` instead of `MIGRATION_ZERO_APPS_DIR`
6
+ * Fixed bug for migrations with > 4 leading digits
7
+
8
+ * *2.0.3* (2024-06-21)
9
+ * Linted docs with `blacken-docs` via `ambient-package-update`
10
+
3
11
  * *2.0.2* (2024-06-20)
4
12
  * Internal updates via `ambient-package-update`
5
13
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-migration-zero
3
- Version: 2.0.2
3
+ Version: 2.1.0
4
4
  Summary: Holistic implementation of "migration zero" pattern for Django covering local changes and in-production database adjustments.
5
5
  Author-email: Ambient Digital <hello@ambient.digital>
6
6
  Description-Content-Type: text/markdown
@@ -34,7 +34,7 @@ Requires-Dist: sphinx-rtd-theme~=2.0 ; extra == "dev"
34
34
  Requires-Dist: m2r2==0.3.3.post2 ; extra == "dev"
35
35
  Requires-Dist: mistune<2.0.0 ; extra == "dev"
36
36
  Requires-Dist: flit~=3.9 ; extra == "dev"
37
- Requires-Dist: ambient-package-update~=24.6.3 ; extra == "dev"
37
+ Requires-Dist: ambient-package-update~=24.6.4 ; extra == "dev"
38
38
  Requires-Dist: unittest-parametrize~=1.3 ; extra == "dev"
39
39
  Project-URL: Bugtracker, https://github.com/ambient-innovation/django-migration-zero/issues
40
40
  Project-URL: Changelog, https://django-migration-zero.readthedocs.io/en/latest/features/changelog.html
@@ -120,11 +120,15 @@ fixing squashed migrations you won't need, you can use the "migration zero" patt
120
120
  - Add this block to your loggers in your main Django `settings.py` to show logs in your console.
121
121
 
122
122
  ```python
123
- "django_migration_zero": {
124
- "handlers": ["console"],
125
- "level": "INFO",
126
- "propagate": True,
127
- },
123
+ LOGGING = {
124
+ "loggers": {
125
+ "django_migration_zero": {
126
+ "handlers": ["console"],
127
+ "level": "INFO",
128
+ "propagate": True,
129
+ },
130
+ },
131
+ }
128
132
  ```
129
133
 
130
134
  ## Contribute
@@ -75,11 +75,15 @@ fixing squashed migrations you won't need, you can use the "migration zero" patt
75
75
  - Add this block to your loggers in your main Django `settings.py` to show logs in your console.
76
76
 
77
77
  ```python
78
- "django_migration_zero": {
79
- "handlers": ["console"],
80
- "level": "INFO",
81
- "propagate": True,
82
- },
78
+ LOGGING = {
79
+ "loggers": {
80
+ "django_migration_zero": {
81
+ "handlers": ["console"],
82
+ "level": "INFO",
83
+ "propagate": True,
84
+ },
85
+ },
86
+ }
83
87
  ```
84
88
 
85
89
  ## Contribute
@@ -3,4 +3,4 @@
3
3
  Holistic implementation of "migration zero" pattern for Django covering local changes and in-production database adjustments.
4
4
  """
5
5
 
6
- __version__ = "2.0.2"
6
+ __version__ = "2.1.0"
@@ -5,59 +5,60 @@ from pathlib import Path
5
5
  from typing import List
6
6
 
7
7
  from django.apps import apps
8
+ from django.apps.config import AppConfig
9
+ from django.conf import settings
8
10
 
9
11
  from django_migration_zero.helpers.logger import get_logger
10
- from django_migration_zero.settings import get_migration_zero_apps_dir
11
12
 
12
13
  logger = get_logger()
13
14
 
14
15
 
15
- def build_migration_directory_path(*, app_label: str) -> Path:
16
+ def build_migration_directory_path(*, app_path: Path) -> Path:
16
17
  """
17
18
  Get directory to the migration directory of a given local Django app
18
19
  """
19
- return get_migration_zero_apps_dir() / app_label / "migrations"
20
+ return app_path / "migrations"
20
21
 
21
22
 
22
- def get_local_django_apps() -> List[str]:
23
+ def get_local_django_apps() -> List[AppConfig]:
23
24
  """
24
25
  Iterate all installed Django apps and detect local ones.
25
26
  """
26
27
  local_apps = []
28
+ local_path = str(settings.BASE_DIR).replace("\\", "/")
27
29
  logger.info("Getting local Django apps...")
28
30
  for app_config in apps.get_app_configs():
29
- local_path = str(get_migration_zero_apps_dir())
30
- app_path = str(Path(app_config.path))
31
- if local_path in app_path and "site-packages" not in app_path:
31
+ app_path = str(app_config.path).replace("\\", "/")
32
+ if app_path.startswith(local_path) and "site-packages" not in app_path:
32
33
  logger.info(f"Local app {app_config.label!r} discovered.")
33
- local_apps.append(app_config.label)
34
+ local_apps.append(app_config)
34
35
  else:
35
36
  logger.debug(f"App {app_config.label!r} ignored since it's not local.")
36
37
 
37
38
  return local_apps
38
39
 
39
40
 
40
- def has_migration_directory(*, app_label: str) -> bool:
41
+ def has_migration_directory(*, app_path: Path) -> bool:
41
42
  """
42
43
  Determines if the given Django app has a migrations directory and therefore migrations
43
44
  """
44
- possible_migration_dir = build_migration_directory_path(app_label=app_label)
45
+ possible_migration_dir = build_migration_directory_path(app_path=app_path)
45
46
  return True if isdir(possible_migration_dir) else False
46
47
 
47
48
 
48
- def get_migration_files(*, app_label: str, exclude_initials: bool = False) -> List[str]:
49
+ def get_migration_files(*, app_label: str, app_path: Path, exclude_initials: bool = False) -> List[str]:
49
50
  """
50
51
  Returns a list of all migration files detected in the given Django app.
51
52
  """
52
53
  migration_file_list = []
53
54
 
54
55
  logger.info(f"Getting migration files from app {app_label!r}...")
55
- migration_dir = build_migration_directory_path(app_label=app_label)
56
- file_pattern = r"^\d{4}_\w+\.py$"
56
+ migration_dir = build_migration_directory_path(app_path=app_path)
57
+ file_pattern = r"^\d{4,}_\w+\.py$"
57
58
  for filename in os.listdir(migration_dir):
58
59
  if re.match(file_pattern, filename):
59
60
  if exclude_initials:
60
- initial_pattern = r"^\d{4}_initial.py$"
61
+ initial_pattern = r"^\d{4,}_initial.py$"
61
62
  if re.match(initial_pattern, filename):
62
63
  logger.debug(f"File {filename!r} ignored since it's an initial migration.")
63
64
  continue
@@ -70,11 +71,11 @@ def get_migration_files(*, app_label: str, exclude_initials: bool = False) -> Li
70
71
  return migration_file_list
71
72
 
72
73
 
73
- def delete_file(*, filename: str, app_label: str, dry_run: bool = False) -> None:
74
+ def delete_file(*, filename: str, app_path: Path, dry_run: bool = False) -> None:
74
75
  """
75
76
  Physically delete the given file
76
77
  """
77
- file_path = build_migration_directory_path(app_label=app_label) / filename
78
+ file_path = build_migration_directory_path(app_path=app_path) / filename
78
79
  if not dry_run:
79
80
  try:
80
81
  os.unlink(file_path)
@@ -1,3 +1,5 @@
1
+ from pathlib import Path
2
+
1
3
  from django.core.management import call_command
2
4
 
3
5
  from django_migration_zero.helpers.file_system import (
@@ -23,17 +25,23 @@ class ResetMigrationFiles:
23
25
 
24
26
  def process(self):
25
27
  logger = get_logger()
26
- local_app_list = get_local_django_apps()
28
+ local_apps = get_local_django_apps()
29
+
30
+ for app_config in local_apps:
31
+ app_path = Path(app_config.path)
27
32
 
28
- for app_label in local_app_list:
29
- if not has_migration_directory(app_label=app_label):
30
- logger.debug(f"Skipping app {app_label!r}. No migration package detected.")
33
+ if not has_migration_directory(app_path=app_path):
34
+ logger.debug(f"Skipping app {app_config.label!r}. No migration package detected.")
31
35
  continue
32
36
 
33
- migration_file_list = get_migration_files(app_label=app_label, exclude_initials=self.exclude_initials)
37
+ migration_file_list = get_migration_files(
38
+ app_label=app_config.label,
39
+ app_path=app_path,
40
+ exclude_initials=self.exclude_initials,
41
+ )
34
42
 
35
43
  for migration_file in migration_file_list:
36
- delete_file(filename=migration_file, app_label=app_label, dry_run=self.dry_run)
44
+ delete_file(filename=migration_file, app_path=app_path, dry_run=self.dry_run)
37
45
 
38
46
  logger.info("Recreating new initial migration files...")
39
47
  call_command("makemigrations")
@@ -2,17 +2,11 @@
2
2
 
3
3
  # Settings
4
4
 
5
- This package requires all local Django apps to be inside a single directory. This directory needs to be defined in the
6
- main django settings.
7
-
8
- Usually, you can use the `BASE_DIR` variable from Django's default setup and add a path.
5
+ This package requires all local Django apps to be inside a `BASE_DIR` directory. This directory should be already
6
+ defined in the main django settings.
9
7
 
10
8
  Note that this variable has to be of type `pathlib.Path`.
11
9
 
12
- ```python
13
- MIGRATION_ZERO_APPS_DIR = BASE_DIR / "apps"
14
- ```
15
-
16
10
  ## Logging
17
11
 
18
12
  The scripts are quite chatty. If you want to see what's going on under the hood, just configure a quite default-looking
@@ -28,7 +22,6 @@ LOGGING = {
28
22
  "level": "INFO",
29
23
  "propagate": True,
30
24
  },
31
- ...
32
25
  },
33
26
  }
34
27
  ```
@@ -7,7 +7,7 @@ import sys
7
7
 
8
8
  def main():
9
9
  """Run administrative tasks."""
10
- os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_migration_zero.settings")
10
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
11
11
  try:
12
12
  from django.core.management import execute_from_command_line
13
13
  except ImportError as exc:
@@ -48,7 +48,7 @@ dev = [
48
48
  'm2r2==0.3.3.post2',
49
49
  'mistune<2.0.0',
50
50
  'flit~=3.9',
51
- 'ambient-package-update~=24.6.3',
51
+ 'ambient-package-update~=24.6.4',
52
52
  'unittest-parametrize~=1.3',
53
53
  ]
54
54
 
@@ -42,6 +42,7 @@ INSTALLED_APPS = [
42
42
  "django_migration_zero",
43
43
  # Local
44
44
  "testapp",
45
+ "testapp.nested_app",
45
46
  ]
46
47
 
47
48
  MIDDLEWARE = [
@@ -81,8 +82,6 @@ DATABASES = {
81
82
  }
82
83
  }
83
84
 
84
- MIGRATION_ZERO_APPS_DIR = BASE_DIR / "django-migration-zero"
85
-
86
85
  # Password validation
87
86
  # https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
88
87
 
@@ -0,0 +1,81 @@
1
+ from pathlib import Path
2
+ from unittest import mock
3
+
4
+ from django.apps import apps
5
+ from django.test import TestCase
6
+
7
+ from django_migration_zero.helpers.file_system import (
8
+ build_migration_directory_path,
9
+ delete_file,
10
+ get_local_django_apps,
11
+ get_migration_files,
12
+ has_migration_directory,
13
+ )
14
+
15
+
16
+ class HelperFileSystemTest(TestCase):
17
+ def setUp(self):
18
+ self.django_migration_zero_config = apps.get_app_config("django_migration_zero")
19
+ self.testapp_config = apps.get_app_config("testapp")
20
+ self.nested_app_config = apps.get_app_config("nested_app")
21
+
22
+ def test_build_migration_directory_path_regular(self, *args):
23
+ path = Path("/user/workspace/migration_zero/ilyta")
24
+ self.assertEqual(
25
+ build_migration_directory_path(app_path=path), Path("/user/workspace/migration_zero/ilyta/migrations")
26
+ )
27
+
28
+ def test_get_local_django_apps_regular(self):
29
+ self.assertEqual(
30
+ get_local_django_apps(),
31
+ [
32
+ self.django_migration_zero_config,
33
+ self.testapp_config,
34
+ self.nested_app_config,
35
+ ],
36
+ )
37
+
38
+ def test_has_migration_directory_positive_case(self):
39
+ app_path = Path(self.django_migration_zero_config.path)
40
+ self.assertTrue(has_migration_directory(app_path=app_path))
41
+
42
+ def test_has_migration_directory_negative_case(self):
43
+ app_path = Path(self.testapp_config.path)
44
+ self.assertFalse(has_migration_directory(app_path=app_path))
45
+
46
+ def test_has_migration_directory_positive_case_no_migrations(self):
47
+ app_path = Path(self.nested_app_config.path)
48
+ self.assertTrue(has_migration_directory(app_path=app_path))
49
+
50
+ def test_get_migration_files_regular(self):
51
+ self.assertEqual(
52
+ get_migration_files(
53
+ app_label=self.django_migration_zero_config.label,
54
+ app_path=Path(self.django_migration_zero_config.path),
55
+ ),
56
+ ["0001_initial.py"],
57
+ )
58
+
59
+ def test_get_migration_files_exclude_initials(self):
60
+ self.assertEqual(
61
+ get_migration_files(
62
+ app_label=self.django_migration_zero_config.label,
63
+ app_path=Path(self.django_migration_zero_config.path),
64
+ exclude_initials=True,
65
+ ),
66
+ [],
67
+ )
68
+
69
+ @mock.patch("django_migration_zero.helpers.file_system.os.unlink")
70
+ def test_delete_file_regular(self, mocked_unlink):
71
+ delete_file(app_path=Path(self.testapp_config.path), filename="my_file.py")
72
+ mocked_unlink.assert_called_once()
73
+
74
+ @mock.patch("django_migration_zero.helpers.file_system.os.unlink")
75
+ def test_delete_file_dry_run(self, mocked_unlink):
76
+ delete_file(app_path=Path(self.testapp_config.path), filename="my_file.py", dry_run=True)
77
+ mocked_unlink.assert_not_called()
78
+
79
+ @mock.patch("django_migration_zero.helpers.file_system.os.unlink", side_effect=OSError)
80
+ def test_delete_file_os_error(self, *args):
81
+ self.assertIsNone(delete_file(app_path=Path(self.testapp_config.path), filename="my_file.py", dry_run=False))
File without changes
@@ -1,5 +1,7 @@
1
+ from pathlib import Path
1
2
  from unittest import mock
2
3
 
4
+ from django.apps import apps
3
5
  from django.test import TestCase
4
6
 
5
7
  from django_migration_zero.services.local import ResetMigrationFiles
@@ -7,26 +9,39 @@ from django_migration_zero.services.local import ResetMigrationFiles
7
9
 
8
10
  @mock.patch("django_migration_zero.services.local.delete_file")
9
11
  class ResetMigrationFilesTest(TestCase):
12
+ def setUp(self):
13
+ self.django_migration_zero_config = apps.get_app_config("django_migration_zero")
14
+ self.testapp_config = apps.get_app_config("testapp")
15
+ self.nested_app_config = apps.get_app_config("nested_app")
16
+
10
17
  def test_init_regular(self, *args):
11
18
  service = ResetMigrationFiles(dry_run=True, exclude_initials=True)
12
19
 
13
20
  self.assertTrue(service.dry_run)
14
21
  self.assertTrue(service.exclude_initials)
15
22
 
16
- @mock.patch("django_migration_zero.services.local.get_local_django_apps", return_value=["django_migration_zero"])
17
23
  @mock.patch("django_migration_zero.services.local.has_migration_directory", return_value=True)
18
24
  def test_process_case_app_with_migration_found(self, mocked_has_migration_directory, *args):
19
25
  service = ResetMigrationFiles()
20
- service.process()
26
+
27
+ with mock.patch(
28
+ "django_migration_zero.services.local.get_local_django_apps",
29
+ return_value=[self.django_migration_zero_config],
30
+ ):
31
+ service.process()
21
32
 
22
33
  # Assertion
23
34
  mocked_has_migration_directory.assert_called()
24
35
 
25
- @mock.patch("django_migration_zero.services.local.get_local_django_apps", return_value=["django_migration_zero"])
26
36
  @mock.patch("django_migration_zero.services.local.has_migration_directory", return_value=False)
27
37
  def test_process_case_app_with_no_migration_found(self, mocked_has_migration_directory, *args):
28
38
  service = ResetMigrationFiles()
29
- service.process()
39
+
40
+ with mock.patch(
41
+ "django_migration_zero.services.local.get_local_django_apps",
42
+ return_value=[self.testapp_config, self.nested_app_config],
43
+ ):
44
+ service.process()
30
45
 
31
46
  # Assertion
32
47
  mocked_has_migration_directory.assert_called()
@@ -37,7 +52,7 @@ class ResetMigrationFilesTest(TestCase):
37
52
 
38
53
  # Assertion
39
54
  mocked_delete_file.assert_called_with(
40
- filename="0001_initial.py", app_label="django_migration_zero", dry_run=False
55
+ filename="0001_initial.py", app_path=Path(self.django_migration_zero_config.path), dry_run=False
41
56
  )
42
57
 
43
58
  def test_process_delete_file_case_dry_run(self, mocked_delete_file):
@@ -46,7 +61,7 @@ class ResetMigrationFilesTest(TestCase):
46
61
 
47
62
  # Assertion
48
63
  mocked_delete_file.assert_called_with(
49
- filename="0001_initial.py", app_label="django_migration_zero", dry_run=True
64
+ filename="0001_initial.py", app_path=Path(self.django_migration_zero_config.path), dry_run=True
50
65
  )
51
66
 
52
67
  def test_process_delete_file_case_exclude_initials(self, mocked_delete_file):
@@ -1,19 +0,0 @@
1
- from pathlib import Path
2
-
3
- from django.conf import settings
4
-
5
- from django_migration_zero.exceptions import InvalidMigrationAppsDirPathError
6
-
7
-
8
- def get_migration_zero_apps_dir() -> Path:
9
- """
10
- Helper method to get the settings variable and validate the type
11
- """
12
- migration_zero_apps_dir = getattr(settings, "MIGRATION_ZERO_APPS_DIR", Path("/"))
13
-
14
- if not isinstance(migration_zero_apps_dir, Path):
15
- raise InvalidMigrationAppsDirPathError(
16
- 'Settings variable "MIGRATION_ZERO_APPS_DIR" has to be of type pathlib.Path.'
17
- )
18
-
19
- return migration_zero_apps_dir
@@ -1,49 +0,0 @@
1
- from pathlib import Path
2
- from unittest import mock
3
-
4
- from django.test import TestCase, override_settings
5
-
6
- from django_migration_zero.helpers.file_system import (
7
- build_migration_directory_path,
8
- delete_file,
9
- get_local_django_apps,
10
- get_migration_files,
11
- has_migration_directory,
12
- )
13
-
14
-
15
- class HelperFileSystemTest(TestCase):
16
- @override_settings(MIGRATION_ZERO_APPS_DIR=Path("/user/workspace/migration_zero/"))
17
- def test_build_migration_directory_path_regular(self, *args):
18
- self.assertEqual(
19
- build_migration_directory_path(app_label="ilyta"), Path("/user/workspace/migration_zero/ilyta/migrations")
20
- )
21
-
22
- def test_get_local_django_apps_regular(self):
23
- self.assertEqual(get_local_django_apps(), ["django_migration_zero", "testapp"])
24
-
25
- def test_has_migration_directory_positive_case(self):
26
- self.assertTrue(has_migration_directory(app_label="django_migration_zero"))
27
-
28
- def test_has_migration_directory_negative_case(self):
29
- self.assertFalse(has_migration_directory(app_label="testapp"))
30
-
31
- def test_get_migration_files_regular(self):
32
- self.assertEqual(get_migration_files(app_label="django_migration_zero"), ["0001_initial.py"])
33
-
34
- def test_get_migration_files_exclude_initials(self):
35
- self.assertEqual(get_migration_files(app_label="django_migration_zero", exclude_initials=True), [])
36
-
37
- @mock.patch("django_migration_zero.helpers.file_system.os.unlink")
38
- def test_delete_file_regular(self, mocked_unlink):
39
- delete_file(app_label="testapp", filename="my_file.py")
40
- mocked_unlink.assert_called_once()
41
-
42
- @mock.patch("django_migration_zero.helpers.file_system.os.unlink")
43
- def test_delete_file_dry_run(self, mocked_unlink):
44
- delete_file(app_label="testapp", filename="my_file.py", dry_run=True)
45
- mocked_unlink.assert_not_called()
46
-
47
- @mock.patch("django_migration_zero.helpers.file_system.os.unlink", side_effect=OSError)
48
- def test_delete_file_os_error(self, *args):
49
- self.assertIsNone(delete_file(app_label="testapp", filename="my_file.py", dry_run=False))
@@ -1,18 +0,0 @@
1
- from django.conf import settings
2
- from django.test import TestCase, override_settings
3
-
4
- from django_migration_zero.exceptions import InvalidMigrationAppsDirPathError
5
- from django_migration_zero.settings import get_migration_zero_apps_dir
6
-
7
-
8
- class SettingsTest(TestCase):
9
- def test_get_migration_zero_apps_dir_regular(self):
10
- self.assertEqual(get_migration_zero_apps_dir(), settings.MIGRATION_ZERO_APPS_DIR)
11
-
12
- @override_settings(MIGRATION_ZERO_APPS_DIR="/usr/path/to/apps")
13
- def test_get_migration_zero_apps_dir_wrong_type(self):
14
- with self.assertRaisesMessage(
15
- InvalidMigrationAppsDirPathError,
16
- 'Settings variable "MIGRATION_ZERO_APPS_DIR" has to be of type pathlib.Path.',
17
- ):
18
- get_migration_zero_apps_dir()