Skip to content

Commit

Permalink
Remove Django 1.11 support
Browse files Browse the repository at this point in the history
This change removes Django 1.11 support from our flagged urls, anonymous user condition, and in Django templates.

I've also updated the documentation to remove references to Django 1.11
  • Loading branch information
willbarton committed Jun 10, 2020
1 parent fd57fb0 commit b4b365b
Show file tree
Hide file tree
Showing 14 changed files with 64 additions and 255 deletions.
6 changes: 0 additions & 6 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,15 @@ jobs:
strategy:
matrix:
toxenv:
- py36-dj111
- py36-dj22
- py36-dj30
- py38-dj111
- py38-dj22
- py38-dj30
include:
- toxenv: py36-dj111
python-version: 3.6
- toxenv: py36-dj22
python-version: 3.6
- toxenv: py36-dj30
python-version: 3.6
- toxenv: py38-dj111
python-version: 3.8
- toxenv: py38-dj22
python-version: 3.8
- toxenv: py38-dj30
Expand Down
51 changes: 0 additions & 51 deletions docs/api/urls.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

Flagged URL patterns are an alternative to [flagging views with decorators](../../api/decorators).

## Django 2.0+

```python
from flags.urls import flagged_path, flagged_paths, flagged_re_path, flagged_re_paths
```
Expand Down Expand Up @@ -56,52 +54,3 @@ with flagged_paths('MY_FLAG') as path:

urlpatterns = urlpatterns + flagged_url_patterns
```

## Django 1.x

```python
from flags.urls import flagged_url, flagged_urls
```

### `flagged_url(flag_name, regex, view, kwargs=None, name=None, state=True, fallback=None)`

Make a URL depend on the state of a feature flag.

`flagged_url()` can be used in place of [Django's `url()`](https://docs.djangoproject.com/en/1.11/ref/urls/#django.conf.urls.url).

The `view` and the `fallback` can both be a set of `include()`ed patterns but any matching URL patterns in the includes must match *exactly* in terms of regular expression, keyword arguments, and name, otherwise a `404` may be unexpectedly raised.

If a `fallback` is not given the flagged url will raise a `404` if the flag state does not match the required `state`.

!!! note
When a fallback view is given it *must* take the same arguments as the flagged view.

```python
urlpatterns = [
flagged_url('MY_FLAG', r'a-url/', view_requiring_flag, state=True),
flagged_url('MY_FLAG_WITH_FALLBACK', r'^another-url$',
view_with_fallback, state=True, fallback=other_view)
flagged_url('MY_FLAGGED_INCLUDE', '^myapp/', include('myapp.urls'),
state=True, fallback=other_view)
flagged_url('MY_NEW_APP_FLAG', r'^mynewapp$', include('mynewapp.urls'),
state=True, fallback=include('myoldapp.urls'))
]
```

### `flagged_urls(flag_name, state=True, fallback=None)`

Flag multiple URLs in the same context with a context manager.

`flagged_urls()` returns a function that takes the same arguments as [Django's `url()`](https://docs.djangoproject.com/en/1.11/ref/urls/#django.conf.urls.url).

!!! note
When a fallback view is given it *must* take the same arguments as the flagged view.

```python
with flagged_urls('MY_FLAG') as furl:
flagged_url_patterns = [
furl(^'a-url/', view_requiring_flag),
]

urlpatterns = urlpatterns + flagged_url_patterns
```
28 changes: 0 additions & 28 deletions docs/api/views.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,6 @@ urlpatterns = [
]
```

#### Django 1.x

```python
from django.urls import path
from flags.urls import flagged_path

urlpatterns = [
url(r'^my-url/$', MyFlaggedView.as_view(flag_name='MY_FLAG'))
]
```

### `FlaggedTemplateView`

A combination of [`TemplateView`](https://docs.djangoproject.com/en/2.2/ref/class-based-views/base/#templateview) and [`FlaggedViewMixin`](#flaggedviewmixin).
Expand Down Expand Up @@ -92,20 +81,3 @@ urlpatterns = [
),
]
```

#### Django 1.x

```
from django.urls import url
from flags.views import FlaggedTemplateView
urlpatterns = [
url(
r'^my_url/$',
FlaggedTemplateView.as_view(
template_name='mytemplate.html',
flag_name='MY_FLAG'
)
),
]
```
15 changes: 1 addition & 14 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Feature flags allow you to toggle functionality in both Django code and the Djan

## Dependencies

- Django 1.11+ (including Django 2)
- Django 2.2, 3.0
- Python 3.6+

## Installation
Expand Down Expand Up @@ -85,8 +85,6 @@ Then use the flag in a Django template (`mytemplate.html`):

Configure a URL for that template (`urls.py`):

Django 2.0:

```python
from django.urls import path
from django.views.generic import TemplateView
Expand All @@ -96,17 +94,6 @@ urlpatterns = [
]
```

Django 1.x:

```python
from django.conf.urls import url
from django.views.generic import TemplateView

urlpatterns = [
url(r'^mypage/$', TemplateView.as_view(template_name='mytemplate.html')),
]
```

Then in the Django admin add conditions for the flag in "Django Flags", "Flag states":

![Creating conditions in the Django admin](images/screenshot_create.png)
Expand Down
9 changes: 7 additions & 2 deletions docs/releasenotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,16 @@

### Deprecations

- Deprecated the optional `flags.middleware.FlagConditionsMiddleware` in favor of always lazily caching flags on the request object.
- Deprecated the optional `flags.middleware.FlagConditionsMiddleware` in favor of always lazily caching flags on the request object.

### Removals

- Django Flags 4.1 deprecated support for using a single dictionary to hold key/values of conditions for a settings-based feature flag, and this has been removed. Use [a list of dictionaries or tuples instead](/settings/#flags).
- Django Flags 4.1 deprecated support for using a single dictionary to hold key/values of conditions for a settings-based feature flag, and this has been removed. Use [a list of dictionaries or tuples instead](/settings/#flags).
- Removed support for Django 1.11.

### Upgrading

Django Flags 5.0 introduces validator support for flag conditions and includes validators for all built-in conditions.


## 4.2.4
Expand Down
16 changes: 3 additions & 13 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ if flag_enabled('FLAG_WITH_ANY_CONDITIONS', request=a_request):
print("My feature flag is enabled")
```

Django templates:
In Django templates:

```django
{% load feature_flags %}
Expand All @@ -45,7 +45,7 @@ Django templates:
{% endif %}
```

Jinja2 templates (after [adding `flag_enabled` to the Jinja2 environment](../api/jinja2/)):
In Jinja2 templates (after [adding `flag_enabled` to the Jinja2 environment](../api/jinja2/)):

```jinja
{% if flag_enabled('FLAG_WITH_ANY_CONDITIONS', request) %}
Expand All @@ -55,7 +55,7 @@ Jinja2 templates (after [adding `flag_enabled` to the Jinja2 environment](../api
{% endif %}
```

Django 2.0 `urls.py`:
In `urls.py`:

```python
from flags.urls import flagged_path
Expand All @@ -65,14 +65,4 @@ urlpatterns = [
]
```

And Django 1.x `urls.py`:

```python
from flags.urls import flagged_url

urlpatterns = [
flagged_url('FLAG_WITH_REQUIRED_CONDITIONS', r'^a-url$', view_requiring_flag, state=True),
]
```

See the [API reference](/api/state) for more details and examples.
6 changes: 1 addition & 5 deletions flags/conditions/conditions.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import re
from distutils.util import strtobool

import django
from django.contrib.auth import get_user_model
from django.utils import dateparse, timezone

Expand Down Expand Up @@ -46,10 +45,7 @@ def anonymous_condition(boolean_value, request=None, **kwargs):
"request is required for condition 'anonymous'"
)

if django.VERSION[0] >= 2: # pragma: no cover
is_anonymous = bool(request.user.is_anonymous)
else: # pragma: no cover
is_anonymous = bool(request.user.is_anonymous())
is_anonymous = bool(request.user.is_anonymous)

try:
return strtobool(boolean_value.strip().lower()) == is_anonymous
Expand Down
10 changes: 2 additions & 8 deletions flags/templatetags/feature_flags.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import django
from django import template

from flags.state import (
Expand All @@ -9,25 +8,20 @@

register = template.Library()

if django.VERSION >= (1, 9): # pragma: no cover
simple_tag = register.simple_tag
else: # pragma: no cover
simple_tag = register.assignment_tag


# Creates template tags flag_enabled and flag_disabled that call
# base_flag_enabled and base_flag_disabled, passing in any arguments, including
# the request (which could be passed explicitly, or pulled from the context).


@simple_tag(takes_context=True)
@register.simple_tag(takes_context=True)
def flag_enabled(context, flag_name, request=None, **kwargs):
if request is None:
request = context.get("request")
return base_flag_enabled(flag_name, request=request, **kwargs)


@simple_tag(takes_context=True)
@register.simple_tag(takes_context=True)
def flag_disabled(context, flag_name, request=None, **kwargs):
if request is None:
request = context.get("request")
Expand Down
20 changes: 6 additions & 14 deletions flags/tests/settings.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import os

import django

from flags.conditions import register


Expand Down Expand Up @@ -32,18 +30,12 @@

INSTALLED_APPS += ("flags", "flags.tests.testapp")

if django.VERSION >= (1, 10): # pragma: no cover
MIDDLEWARE = (
"debug_toolbar.middleware.DebugToolbarMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
)
else: # pragma: no cover
MIDDLEWARE_CLASSES = (
"django.contrib.sessions.middleware.SessionMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
)
MIDDLEWARE = (
"debug_toolbar.middleware.DebugToolbarMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
)

TEMPLATES = [
{
Expand Down
7 changes: 1 addition & 6 deletions flags/tests/test_admin.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
from django.contrib import admin
from django.contrib.auth.models import User
from django.test import Client, TestCase, override_settings


try:
from django.urls import re_path
except ImportError: # pragma: no cover
from django.conf.urls import url as re_path
from django.urls import re_path


urlpatterns = [
Expand Down
39 changes: 12 additions & 27 deletions flags/tests/test_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,9 @@

from django.http import Http404, HttpResponse
from django.test import RequestFactory, TestCase, override_settings
from django.urls import include, path, re_path, resolve


try:
from django.urls import include, path, resolve, re_path
except ImportError: # pragma: no cover
from django.core.urlresolvers import resolve
from django.conf.urls import include, url as re_path

path = None

try:
from flags.urls import flagged_path, flagged_re_path, flagged_re_paths
except ImportError: # pragma: no cover
from flags.urls import (
flagged_url as flagged_re_path,
flagged_urls as flagged_re_paths,
)
from flags.urls import flagged_path, flagged_re_path, flagged_re_paths


def view(request):
Expand Down Expand Up @@ -119,17 +105,16 @@ def fallback(request):
]
urlpatterns = urlpatterns + flagged_patterns_true_fallback

if path: # pragma: no cover
path_patterns = [
flagged_path(
"FLAGGED_URL",
"path-true-no-fallback",
view,
name="some-view",
state=True,
),
]
urlpatterns = urlpatterns + path_patterns
path_patterns = [
flagged_path(
"FLAGGED_URL",
"path-true-no-fallback",
view,
name="some-view",
state=True,
),
]
urlpatterns = urlpatterns + path_patterns


@override_settings(ROOT_URLCONF=__name__,)
Expand Down

0 comments on commit b4b365b

Please sign in to comment.