Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,34 @@ Change Log

.. There should always be an "Unreleased" section for changes pending release.

[2.0.0] - 2020-11-05
~~~~~~~~~~~~~~~~~~~~

* BREAKING CHANGE: The ``WaffleFlagNamespace`` and ``WaffleSwitchNamespace`` classes have been removed. You can either rename to ``LegacyWaffleFlagNamespace`` and ``LegacyWaffleSwitchNamespace``, which are deprecated, or you can move to the newer waffle classes that no longer use these Namespace classes (see below).
* BREAKING CHANGE: The ``WaffleFlag`` and ``WaffleSwitch`` classes exposed in ``toggles`` no longer use the Namespace classes and are now the classes which were previously only available in ``toggles.__future__``.

* If you were importing from ``edx_toggles.toggles.__future__`` before, then you simply need to import from ``edx_toggles.toggles``. Importing from ``__future__`` will continue to work but will trigger a deprecation warning.
* If you were importing from ``edx_toggles.toggles``, then you either need to:

* Migrate your legacy namespaced classes to the new-style classes (see the new behaviour below), or
* Import ``LegacyWaffleFlag`` instead of ``WaffleFlag`` and ``LegacyWaffleSwitch`` instead of ``WaffleSwitch``. Note that these classes will be removed soon, so it's preferable to migrate to the new classes already.

* The new Waffle classes introduce the following changes:

* They no longer use Namespace classes like ``WaffleSwitchNamespace`` or ``WaffleFlagNamespace``.
* The ``WaffleSwitchNamespace._namespaced_name`` and ``WaffleFlagNamespace._namespaced_name`` methods are replaced by the ``WaffleSwitch.name`` and ``WaffleFlag.name`` attributes.
* The ``WaffleSwitchNamespace.is_enabled`` method is replaced by the ``WaffleSwitch.is_enabled`` method.
* The ``WaffleSwitchNamespace.set_request_cache_with_short_name`` method has no replacement because an alternative solution should be found. You could (but really shouldn't) use the ``WaffleSwitch._cached_switches`` property.
* The ``WaffleSwitch.switch_name`` attribute is deprecated: switches should only ever be referred to using their fully namespaced names.
* The ``WaffleSwitch.switch_name`` attribute no longer exists. Switches should only ever be referred to using their fully namespaced names. If you need the non-namespaced name, it must be parsed from the namespaced name.
* The ``WaffleFlagNamespace.is_flag_active`` method is replaced by ``WaffleFlag.is_enabled``.
* The ``WaffleFlagNamespace._monitor_value`` method is replaced by ``WaffleFlag.set_monitor_value``.
* The ``WaffleFlagNamespace._cached_flags`` attribute is replaced by the ``WaffleFlag.cached_flags`` method.
* The ``WaffleFlag`` and ``WaffleSwitch`` ``module_name`` constructor argument is now mandatory.
* The ``WaffleFlag.flag_name`` attribute is deprecated.
* The ``WaffleFlag.flag_name`` attribute no longer exists. Flags should only ever be referred to using their fully namespaced names. If you need the non-namespaced name, it must be parsed from the namespaced name.
* The ``WaffleFlag.waffle_namespace`` attribute no longer exists, since there is no longer a separate namespace object.

[1.2.2] - 2020-12-22
~~~~~~~~~~~~~~~~~~~~

Expand All @@ -25,7 +53,6 @@ More improvements to monitoring of legacy waffle class imports.

* Improve monitoring of legacy Waffle class imports. We should watch for "edx_toggles.toggles.internal.waffle.legacy.WaffleSwitch" custom attributes.


[1.2.0] - 2020-11-05
~~~~~~~~~~~~~~~~~~~~

Expand Down
2 changes: 1 addition & 1 deletion edx_toggles/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
Library and utilities for feature toggles.
"""

__version__ = '1.2.2'
__version__ = '2.0.0'

default_app_config = 'edx_toggles.apps.TogglesConfig' # pylint: disable=invalid-name
4 changes: 1 addition & 3 deletions edx_toggles/tests/test_testutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@
from django.test.client import RequestFactory
from edx_django_utils.cache import RequestCache

# TODO import from edx_toggles.toggles once we remove the legacy classes from the exposed API
from edx_toggles.toggles.internal.waffle.flag import WaffleFlag
from edx_toggles.toggles.internal.waffle.switch import WaffleSwitch
from edx_toggles.toggles import WaffleFlag, WaffleSwitch
from edx_toggles.toggles.testutils import override_waffle_flag, override_waffle_switch


Expand Down
4 changes: 1 addition & 3 deletions edx_toggles/tests/test_waffle.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@

from django.test import TestCase

from edx_toggles.toggles import NonNamespacedWaffleFlag, NonNamespacedWaffleSwitch, WaffleFlag, WaffleSwitch
from edx_toggles.toggles.internal.waffle.base import BaseWaffle
# TODO import from edx_toggles.toggles once we remove the legacy classes from the exposed API
from edx_toggles.toggles.internal.waffle.flag import NonNamespacedWaffleFlag, WaffleFlag
from edx_toggles.toggles.internal.waffle.switch import NonNamespacedWaffleSwitch, WaffleSwitch


class NaiveWaffle(BaseWaffle):
Expand Down
19 changes: 13 additions & 6 deletions edx_toggles/toggles/__future__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
"""
Expose new-style waffle classes. In the future, these imports will be moved to edx_toggles.toggles. Applications that
want to migrate to the new-style API can do so right now by importing from this module.
This module had been created to expose new-style waffle classes. These are now available from edx_toggles.toggles.
"""
# pylint: disable=unused-import
from .internal.setting_toggle import SettingDictToggle, SettingToggle
Comment thread
robrap marked this conversation as resolved.
from .internal.waffle.flag import NonNamespacedWaffleFlag, WaffleFlag
from .internal.waffle.switch import NonNamespacedWaffleSwitch, WaffleSwitch
import warnings

from . import * # pylint: disable=unused-import,wildcard-import
Comment thread
regisb marked this conversation as resolved.

warnings.warn(
(
"Importing from edx_toggles.toggles.__future__ is now deprecated."
" You should import from edx_toggles.toggles instead."
),
DeprecationWarning,
stacklevel=2,
)
26 changes: 15 additions & 11 deletions edx_toggles/toggles/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,31 @@
Expose public feature toggle API.
"""
from .internal.setting_toggle import SettingDictToggle, SettingToggle
from .internal.waffle.legacy import WaffleFlag, WaffleFlagNamespace, WaffleSwitch, WaffleSwitchNamespace
from .internal.waffle.flag import NonNamespacedWaffleFlag, WaffleFlag
from .internal.waffle.legacy import WaffleFlag as _LegacyWaffleFlag
from .internal.waffle.legacy import WaffleFlagNamespace as _LegacyWaffleFlagNamespace
from .internal.waffle.legacy import WaffleSwitch as _LegacyWaffleSwitch
from .internal.waffle.legacy import WaffleSwitchNamespace as _LegacyWaffleSwitchNamespace
from .internal.waffle.switch import NonNamespacedWaffleSwitch, WaffleSwitch


# Create waffle aliases for forward compatibility
# We create new classes instead of using `LegacyClass = Class` statements
# We create new classes instead of simply importing the legacy classes
# for better monitoring of legacy class usage.
class LegacyWaffleFlag(WaffleFlag):
class LegacyWaffleFlag(_LegacyWaffleFlag):
def _get_legacy_custom_attribute_name(self):
return 'deprecated_compatible_legacy_waffle_class'
return "deprecated_compatible_legacy_waffle_class"


class LegacyWaffleFlagNamespace(WaffleFlagNamespace):
class LegacyWaffleFlagNamespace(_LegacyWaffleFlagNamespace):
def _get_legacy_custom_attribute_name(self):
return 'deprecated_compatible_legacy_waffle_class'
return "deprecated_compatible_legacy_waffle_class"


class LegacyWaffleSwitch(WaffleSwitch):
class LegacyWaffleSwitch(_LegacyWaffleSwitch):
def _get_legacy_custom_attribute_name(self):
return 'deprecated_compatible_legacy_waffle_class'
return "deprecated_compatible_legacy_waffle_class"


class LegacyWaffleSwitchNamespace(WaffleSwitchNamespace):
class LegacyWaffleSwitchNamespace(_LegacyWaffleSwitchNamespace):
def _get_legacy_custom_attribute_name(self):
return 'deprecated_compatible_legacy_waffle_class'
return "deprecated_compatible_legacy_waffle_class"
16 changes: 8 additions & 8 deletions edx_toggles/toggles/internal/waffle/legacy.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,24 @@

To upgrade your code, use the following guidelines. Where previously you had::

from edx_toggles.toggles import WaffleSwitch, WaffleSwitchNamespace
SOME_NAMESPACE = WaffleSwitchNamespace("some_namespace")
SOME_SWITCH = WaffleSwitch(SOME_NAMESPACE, "some_switch", module_name=__name__)
from edx_toggles.toggles import LegacyWaffleSwitch, LegacyWaffleSwitchNamespace
SOME_NAMESPACE = LegacyWaffleSwitchNamespace("some_namespace")
SOME_SWITCH = LegacyWaffleSwitch(SOME_NAMESPACE, "some_switch", module_name=__name__)

You should now write::

from edx_toggles.toggles.__future__ import WaffleSwitch
from edx_toggles.toggles import WaffleSwitch
SOME_SWITCH = WaffleSwitch("some_namespace.some_switch", module_name=__name__)

And similarly for waffle flags, replace::

from edx_toggles.toggles import WaffleFlag, WaffleFlagNamespace
SOME_NAMESPACE = WaffleFlagNamespace("some_namespace", log_prefix="some_namespace")
SOME_FLAG = WaffleFlag(SOME_NAMESPACE, "some_flag", module_name=__name__)
from edx_toggles.toggles import LegacyWaffleFlag, LegacyWaffleFlagNamespace
SOME_NAMESPACE = LegacyWaffleFlagNamespace("some_namespace", log_prefix="some_namespace")
SOME_FLAG = LegacyWaffleFlag(SOME_NAMESPACE, "some_flag", module_name=__name__)

by::

from edx_toggles.toggles.__future__ import WaffleFlag
from edx_toggles.toggles import WaffleFlag
SOME_FLAG = WaffleFlag("some_namespace.some_flag", module_name=__name__, log_prefix="some_namespace")
"""
from abc import ABC
Expand Down