Skip to content

Commit

Permalink
DO NOT MERGE: A combined refactor for testing
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanhiebert committed Jul 20, 2024
1 parent a41cebe commit 7b133bd
Show file tree
Hide file tree
Showing 7 changed files with 329 additions and 188 deletions.
5 changes: 4 additions & 1 deletion HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ Pending
* Add support for Django 5.1.
* Drop support for Django 3.2, 4.0, 4.1.
* Convert ``Safe`` to be a custom class rather than an ``Enum``.
* The valid values for ``safe`` are:
* The standard values of ``Safe`` now support being called. For example:

* ``Safe.before_deploy()``
* ``Safe.after_deploy()``
* ``Safe.always()``
* Add support for allowing a ``Safe.after_deploy(delay=timedelta())``
migration to be migrated after the delay has passed.
* Change the default value of ``safe`` to ``Safe.always``.
This is a better default for third party apps that are not using
``django_safemigrate``.

4.3 (2024-03-28)
++++++++++++++++
Expand Down
28 changes: 12 additions & 16 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ such as a migration to add a column.
from django_safemigrate import Safe
class Migration(migrations.Migration):
safe = Safe.before_deploy()
safe = Safe.before_deploy
At this point you can run the ``safemigrate`` Django command
to run the migrations, and only these migrations will run.
Expand All @@ -66,35 +66,32 @@ Safety Options
There are three options for the value of the
``safe`` property of the migration.

* ``Safe.before_deploy()``
* ``Safe.before_deploy``

This migration is only safe to run before the code change is deployed.
For example, a migration that adds a new field to a model.

* ``Safe.after_deploy(delay=None)``
* ``Safe.after_deploy``

This migration is only safe to run after the code change is deployed.
This is the default that is applied if no ``safe`` property is given.
For example, a migration that removes a field from a model.

By specifying a ``delay`` parameter, you can specify when a
``Safe.after_deploy()`` migration can be run with the ``safemigrate``
``Safe.after_deploy`` migration can be run with the ``safemigrate``
command. For example, if it's desired to wait a week before applying
a migration, you can specify ``Safe.after_deploy(delay=timedelta(days=7))``.

The ``delay`` is used with the datetime when the migration is first detected.
The detection datetime is when the ``safemigrate`` command detects the
migration in a plan that successfully runs. If the migration plan is blocked,
such when a ``Safe.after_deploy(delay=None)`` is in front of a
``Safe.before_deploy()``, no migrations are marked as detected.

Note that a ``Safe.after_deploy()`` migration will not run the first
time it's encountered.
The ``delay`` begins when safemigrate first delays the migration
without it being blocked, on a non-faking run that begins executing.
If the migration is blocked, such as if it is behind a ``Safe.before_deploy``
migration that is behind another ``Safe.after_deploy`` migration,
no migrations are marked as detected.

* ``Safe.always()``
* ``Safe.always``

This migration is safe to run before *and* after
the code change is deployed.
This is the default that is applied if no ``safe`` property is given.
For example, a migration that changes the ``help_text`` of a field.

Pre-commit Hook
Expand Down Expand Up @@ -122,8 +119,7 @@ Nonstrict Mode

Under normal operation, if there are migrations
that must run before the deployment that depend
on any migration that is marked to run after deployment
(or is not marked),
on any migration that is marked to run after deployment,
the command will raise an error to indicate
that there are protected migrations that
should have already been run, but have not been,
Expand Down
16 changes: 8 additions & 8 deletions src/django_safemigrate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,25 @@
from enum import Enum


class SafeEnum(Enum):
always = "always"
before_deploy = "before_deploy"
after_deploy = "after_deploy"
class When(Enum):
ALWAYS = "always"
BEFORE_DEPLOY = "before_deploy"
AFTER_DEPLOY = "after_deploy"


@dataclass
class Safe:
safe: SafeEnum
when: When
delay: timedelta | None = None

@classmethod
def always(cls):
return cls(safe=SafeEnum.always)
return cls(when=When.ALWAYS)

@classmethod
def before_deploy(cls):
return cls(safe=SafeEnum.before_deploy)
return cls(when=When.BEFORE_DEPLOY)

@classmethod
def after_deploy(cls, *, delay: timedelta = None):
return cls(safe=SafeEnum.after_deploy, delay=delay)
return cls(when=When.AFTER_DEPLOY, delay=delay)
Loading

0 comments on commit 7b133bd

Please sign in to comment.