Esempio n. 1
0
 def test_deletable(self):
     FlagState.objects.create(
         name="DBFLAG",
         condition="boolean",
         value="True",
     )
     self.assertFalse(deletable(get_flags().get("MYFLAG")))
     self.assertFalse(deletable(get_flags().get("EMPTYFLAG")))
     self.assertTrue(deletable(get_flags().get("DBFLAG")))
Esempio n. 2
0
    def test_ignore_errors(self):
        # Without ignore_errors
        with self.assertRaises(Exception):
            get_flags(
                sources=["flags.tests.test_sources.ExceptionalFlagsSource"])

        # With ignore_errors
        flags = get_flags(
            sources=["flags.tests.test_sources.ExceptionalFlagsSource"],
            ignore_errors=True,
        )
        self.assertEqual(flags, {})
Esempio n. 3
0
def edit_condition(request, name, condition_pk=None):
    flag = get_flags().get(name)
    try:
        condition = FlagState.objects.get(pk=condition_pk)
    except FlagState.DoesNotExist:
        condition = None

    if request.method == 'POST':
        form = FlagStateForm(request.POST,
                             initial={'name': name},
                             instance=condition)
        if form.is_valid():
            form.save()

            if flag_enabled('WAGTAILFLAGS_ADMIN_BIG_LIST'):
                return redirect('{flags_list}#{flag_name}'.format(
                    flags_list=resolve_url('wagtailflags:list'),
                    flag_name=form.instance.name))
            else:
                return redirect('wagtailflags:flag_index',
                                name=form.instance.name)

    else:
        form = FlagStateForm(initial={'name': name}, instance=condition)

    context = {
        'flag': flag,
        'form': form,
        'condition_str': str(condition),
        'condition_pk': condition_pk,
    }
    return render(request, 'wagtailflags/flags/edit_condition.html', context)
Esempio n. 4
0
def flag_index(request, name):
    flag = get_flags().get(name)

    # If there's a database boolean condition, fetch it and treat it as a
    # on/off switch
    if 'enable' in request.GET or 'disable' in request.GET:
        db_boolean_condition = next(
            (c for c in flag.conditions if c.condition == 'boolean'
             and getattr(c, 'obj', None) is not None), None)

        if db_boolean_condition is None:
            boolean_condition_obj = FlagState.objects.create(
                name=name, condition='boolean', value='True')
        else:
            boolean_condition_obj = db_boolean_condition.obj

        if 'enable' in request.GET and not bool_enabled(flag):
            boolean_condition_obj.value = True
        elif 'disable' in request.GET and bool_enabled(flag):
            boolean_condition_obj.value = False

        boolean_condition_obj.save()

        if flag_enabled('WAGTAILFLAGS_ADMIN_BIG_LIST'):
            return redirect('{flags_list}#{flag_name}'.format(
                flags_list=resolve_url('wagtailflags:list'), flag_name=name))
        else:
            return redirect('wagtailflags:flag_index', name=name)

    context = {
        'flag': flag,
    }
    return render(request, 'wagtailflags/flags/flag_index.html', context)
Esempio n. 5
0
def edit_condition(request, name, condition_pk=None):
    flag = get_flags().get(name)

    if not flag:
        raise Http404

    try:
        condition = FlagState.objects.get(pk=condition_pk)
    except FlagState.DoesNotExist:
        condition = None

    if request.method == "POST":
        form = FlagStateForm(
            request.POST, initial={"name": name}, instance=condition
        )
        if form.is_valid():
            form.save()
            return redirect("wagtailflags:flag_index", name=name)

    else:
        form = FlagStateForm(initial={"name": name}, instance=condition)

    context = {
        "flag": flag,
        "form": form,
        "condition_str": str(condition),
        "condition_pk": condition_pk,
    }
    return render(request, "wagtailflags/flags/edit_condition.html", context)
Esempio n. 6
0
def flags(request):
    q_flag = request.GET.get('flag', False)

    list_flags = get_flags(sources=None, ignore_errors=False)

    if not q_flag:
        # We return the list of all flags.
        data = []
        for (flag, fobject) in list_flags.items():
            data.append({
                'name': flag
            })
        return JsonResponse(data, safe=False)
    else:
        # We return the enabled settings for the set flag.
        if q_flag in list_flags:
            data = [{'name': q_flag, "conditions": []}]
            for condition in list_flags[q_flag].conditions:
                data[0]['conditions'].append({
                    'required': condition.__dict__['required'],
                    'type': condition.__dict__['condition'],
                    'value': condition.__dict__['value']
                })
            return JsonResponse(data, safe=False)
        else:
            return JsonResponse([{'error': 'The flag does not exist.'}], safe=False)
 def test_state_str_required_non_required_bool_false(self):
     flag = get_flags().get("MYFLAG")
     self.assertEqual(
         "MYFLAG is <b>enabled</b> when <i>all</i> required conditions "
         "and <i>any</i> non-required condition is met.",
         state_str(flag),
     )
Esempio n. 8
0
def flag_conditions_check(app_configs, **kwargs):
    from flags.sources import get_flags

    errors = []

    flags = get_flags(ignore_errors=True)
    for name, flag in flags.items():
        for condition in flag.conditions:
            if condition.fn is None:
                errors.append(
                    Warning(
                        (f"Flag {name} has non-existent condition "
                         f"'{condition.condition}'."),
                        hint=(f"Register '{condition.condition}' as a "
                              "Django-Flags condition."),
                        id="flags.E001",
                    ))
            elif condition.fn.validate is not None:
                try:
                    condition.fn.validate(condition.value)
                except ValidationError as e:
                    errors.append(
                        Warning(
                            (f"Flag {name}'s '{condition.condition}' "
                             "condition has an invalid value."),
                            hint=e.message,
                            id="flags.E002",
                        ))

    return errors
Esempio n. 9
0
def _set_flag_state(
    flag_name, state, create_boolean_condition=True, request=None
):
    """ A private function to set a boolean condition to the desired state """
    flags = get_flags(request=request)
    flag = flags.get(flag_name)
    if flag is None:
        raise KeyError(f"No flag with name {flag_name} exists")

    db_boolean_condition = next(
        (
            c
            for c in flag.conditions
            if c.condition == "boolean" and getattr(c, "obj", None) is not None
        ),
        None,
    )

    if db_boolean_condition is not None:
        # We already have a boolean condition
        boolean_condition_obj = db_boolean_condition.obj
    elif db_boolean_condition is None and create_boolean_condition:
        # We can create a boolean condition and we need to.
        boolean_condition_obj = FlagState.objects.create(
            name=flag_name, condition="boolean", value="True"
        )
    else:
        raise ValueError(f"Flag {flag_name} does not have a boolean condition")

    boolean_condition_obj.value = state
    boolean_condition_obj.save()
 def test_state_str_required_no_non_required_no_bool(self):
     flag = get_flags().get("MYFLAG")
     self.assertEqual(
         "MYFLAG is <b>enabled</b> when <i>all</i> required conditions "
         "are met.",
         state_str(flag),
     )
 def test_state_str_required_no_non_required_bool_false(self):
     flag = get_flags().get("MYFLAG")
     self.assertEqual(
         "MYFLAG is <b>disabled</b> for all requests, "
         "even when <i>all</i> required conditions are met.",
         state_str(flag),
     )
 def render(self, path):
     request = RequestFactory().get(path)
     request.flag_conditions = get_flags()
     template = Template(
         "{% load hmda_banners %}" "{% hmda_outage_banner request %}"
     )
     return template.render(Context({"request": request}))
Esempio n. 13
0
    def __init__(self, *args, **kwargs):
        super(FlagStateForm, self).__init__(*args, **kwargs)

        self.fields["name"].choices = [(f, f)
                                       for f in sorted(get_flags().keys())]

        self.fields["condition"].choices = [(c, c)
                                            for c in sorted(get_conditions())]
Esempio n. 14
0
 def render(self, path):
     request = RequestFactory().get(path)
     request.flag_conditions = get_flags()
     template = Template(
         '{% load hmda_banners %}'
         '{% hmda_outage_banner request %}'
     )
     return template.render(Context({'request': request}))
Esempio n. 15
0
 def render(self, path):
     request = RequestFactory().get(path)
     request.flag_conditions = get_flags()
     template = Template(
         '{% load complaint_banners %}'
         '{% complaint_maintenance_banner request %}'
     )
     return template.render(Context({'request': request}))
Esempio n. 16
0
def _get_flag_state(flag_name, **kwargs):
    """ A private function that performs the actual state checking """
    flags = get_flags(request=kwargs.get("request"))

    flag = flags.get(flag_name)
    if flag is not None:
        return flag.check_state(**kwargs)

    return None
Esempio n. 17
0
 def test_get_flags(self):
     flags = get_flags(sources=[
         "flags.sources.SettingsFlagsSource",
         "flags.tests.test_sources.TestFlagsSource",
     ])
     self.assertIn("OTHER_FLAG", flags)
     self.assertIn("SOURCED_FLAG", flags)
     self.assertEqual(len(flags["OTHER_FLAG"].conditions), 0)
     self.assertEqual(len(flags["SOURCED_FLAG"].conditions), 1)
Esempio n. 18
0
    def generate_stats(self, request, response):
        flags = get_flags(request=request)

        self.record_stats({
            "request":
            request,
            "flags":
            sorted(flags.values(), key=lambda x: x.name),
        })
Esempio n. 19
0
 def test_get_flags(self):
     flags = get_flags(sources=[
         'flags.sources.SettingsFlagsSource',
         'flags.tests.test_sources.TestFlagsSource',
     ])
     self.assertIn('OTHER_FLAG', flags)
     self.assertIn('SOURCED_FLAG', flags)
     self.assertEqual(len(flags['OTHER_FLAG'].conditions), 0)
     self.assertEqual(len(flags['SOURCED_FLAG'].conditions), 1)
Esempio n. 20
0
 def test_get_flags_ensure_combined_conditions_work(self):
     FlagState.objects.create(name='MY_FLAG',
                              condition='boolean',
                              value='True')
     flags = get_flags(sources=[
         'flags.sources.SettingsFlagsSource',
         'flags.sources.DatabaseFlagsSource',
     ])
     self.assertIn('MY_FLAG', flags)
     my_flag = flags['MY_FLAG']
     self.assertTrue(my_flag.check_state())
Esempio n. 21
0
 def test_get_flags_ensure_combined_conditions_work(self):
     FlagState.objects.create(name="MY_FLAG",
                              condition="boolean",
                              value="True")
     flags = get_flags(sources=[
         "flags.sources.SettingsFlagsSource",
         "flags.sources.DatabaseFlagsSource",
     ])
     self.assertIn("MY_FLAG", flags)
     my_flag = flags["MY_FLAG"]
     self.assertTrue(my_flag.check_state())
Esempio n. 22
0
    def generate_stats(self, request, response):
        if hasattr(request, FlagConditionsMiddleware.request_attribute):
            flags = getattr(request,
                            FlagConditionsMiddleware.request_attribute)
        else:
            flags = get_flags()

        self.record_stats({
            "request":
            request,
            "flags":
            sorted(flags.values(), key=lambda x: x.name),
        })
Esempio n. 23
0
def flag_state(flag_name, **kwargs):
    """ Return the value for the flag by passing kwargs to its conditions """
    flags = None

    # If the request is given as a kwargs, and the FlagConditionsMiddleware is
    # enabled, use the flag conditions attached to the request.
    if 'request' in kwargs:
        flags = getattr(kwargs['request'],
                        FlagConditionsMiddleware.request_attribute, None)

    if flags is None:
        flags = get_flags()

    flag = flags.get(flag_name)
    if flag is not None:
        return flag.check_state(**kwargs)

    return None
Esempio n. 24
0
def delete_condition(request, name, condition_pk):
    flag = get_flags().get(name)

    if not flag:
        raise Http404

    condition = get_object_or_404(FlagState, pk=condition_pk)

    if request.method == "POST":
        condition.delete()
        return redirect("wagtailflags:flag_index", name=name)

    context = {
        "flag": flag,
        "condition_str": str(condition),
        "condition_pk": condition.pk,
    }
    return render(request, "wagtailflags/flags/delete_condition.html", context)
Esempio n. 25
0
def delete_flag(request, name):
    """ Delete a database flag. """
    flag = get_flags().get(name)

    if not flag:
        raise Http404

    if not deletable(flag):
        return HttpResponseForbidden(name)

    if request.method == "POST":
        FlagState.objects.filter(name=name).delete()
        return redirect("wagtailflags:list")

    context = {
        "flag": flag,
    }
    return render(request, "wagtailflags/flags/delete_flag.html", context)
Esempio n. 26
0
def delete_condition(request, name, condition_pk):
    flag = get_flags().get(name)
    condition = get_object_or_404(FlagState, pk=condition_pk)

    if request.method == 'POST':
        condition.delete()

        if flag_enabled('WAGTAILFLAGS_ADMIN_BIG_LIST'):
            return redirect('{flags_list}#{flag_name}'.format(
                flags_list=resolve_url('wagtailflags:list'), flag_name=name))
        else:
            return redirect('wagtailflags:flag_index', name=name)

    context = {
        'flag': flag,
        'condition_str': str(condition),
        'condition_pk': condition.pk,
    }
    return render(request, 'wagtailflags/flags/delete_condition.html', context)
Esempio n. 27
0
    def test_uses_cached_flags_from_request(self):
        request = HttpRequest()

        # The initial call looks up flag conditions from the database source.
        with self.assertNumQueries(1):
            get_flags(request=request)

        # Subsequent calls with a request object don't need to redo the lookup
        # because they have the cached flags.
        with self.assertNumQueries(0):
            get_flags(request=request)

        # But subsequent calls without a request object still redo the lookup.
        with self.assertNumQueries(1):
            get_flags()
Esempio n. 28
0
def flag_conditions_check(app_configs, **kwargs):
    from flags.sources import get_flags

    error_str = 'Flag {flag} has non-existent condition "{condition}"'
    error_hint = 'Register "{condition}" as a Django-Flags condition.'

    errors = []

    flags = get_flags(ignore_errors=True)
    for name, flag in flags.items():
        for condition in flag.conditions:
            if condition.fn is None:
                errors.append(
                    Warning(
                        error_str.format(flag=name,
                                         condition=condition.condition),
                        hint=error_hint.format(condition=condition.condition),
                        id='flags.E001',
                    ))

    return errors
Esempio n. 29
0
def _flag_state(flag_name, **kwargs):
    """ This is a private function that performs the actual state checking """
    flags = None

    # If the request is given as a kwargs, and the FlagConditionsMiddleware is
    # enabled, use the flag conditions attached to the request.
    if 'request' in kwargs:
        flags = getattr(
            kwargs['request'],
            FlagConditionsMiddleware.request_attribute,
            None
        )

    if flags is None:
        flags = get_flags()

    flag = flags.get(flag_name)
    if flag is not None:
        return flag.check_state(**kwargs)

    return None
Esempio n. 30
0
def flag_index(request, name):
    flag = get_flags().get(name)

    if not flag:
        raise Http404

    # If there's a database boolean condition, fetch it and treat it as a
    # on/off switch
    if "enable" in request.GET or "disable" in request.GET:
        db_boolean_condition = next(
            (
                c
                for c in flag.conditions
                if c.condition == "boolean"
                and getattr(c, "obj", None) is not None
            ),
            None,
        )

        if db_boolean_condition is None:
            boolean_condition_obj = FlagState.objects.create(
                name=name, condition="boolean", value="True"
            )
        else:
            boolean_condition_obj = db_boolean_condition.obj

        if "enable" in request.GET and not bool_enabled(flag):
            boolean_condition_obj.value = True
            flag_enabled.send(sender=flag_index, flag_name=flag.name)
        elif "disable" in request.GET and bool_enabled(flag):
            boolean_condition_obj.value = False
            flag_disabled.send(sender=flag_index, flag_name=flag.name)

        boolean_condition_obj.save()
        return redirect("wagtailflags:flag_index", name=name)

    context = {
        "flag": flag,
    }
    return render(request, "wagtailflags/flags/flag_index.html", context)
Esempio n. 31
0
 def test_disablable_enabled_required(self):
     flag = get_flags().get("MYFLAG")
     self.assertFalse(disablable(flag))
Esempio n. 32
0
 def test_disablable_disabled_not_required(self):
     flag = get_flags().get("MYFLAG")
     self.assertTrue(disablable(flag))