Skip to content

Commit

Permalink
feat: add management command create_client (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
lovvskillz committed Oct 10, 2022
1 parent 6e2f2bc commit 5732ae5
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 0 deletions.
Empty file added durin/management/__init__.py
Empty file.
Empty file.
59 changes: 59 additions & 0 deletions durin/management/commands/create_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from django.core.management.base import BaseCommand, CommandError
from django.utils.translation import gettext_lazy as _

from durin.serializers import ClientSerializer


class Command(BaseCommand):
help = "Creates a new client with the given values."

def add_arguments(self, parser):
parser.add_argument(
"name", type=str, help=_("A unique identification name for the client.")
)
parser.add_argument(
"--token-ttl",
type=str,
default="",
help=_(
"Token Time To Live (TTL) in timedelta. "
"Format: <code>DAYS HH:MM:SS</code>."
),
)
parser.add_argument(
"--throttle-rate",
type=str,
default="",
help=_(
"Follows the same format as DRF's throttle rates. "
"Format: <em>'number_of_requests/period'</em> "
"where period should be one of: ('s', 'm', 'h', 'd'). "
"Example: '100/h' implies 100 requests each hour."
),
)

def handle(self, *args, **options):
client = ClientSerializer(
data={
"name": options["name"],
"token_ttl": options["token_ttl"],
"throttle_rate": options["throttle_rate"],
}
)
if client.is_valid():
client.save()
self.stdout.write(
self.style.SUCCESS("Client {} created!".format(client.data.get("name")))
)
return
raise CommandError(
(
"Can't create client!\n"
+ "\n".join(
(
"{field}: {errors}".format(field=field, errors=" ".join(errors))
for field, errors in client.errors.items()
)
)
)
)
14 changes: 14 additions & 0 deletions durin/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,17 @@ def create(self, validated_data):
validated_data["user"] = user
validated_data["client"] = Client.objects.get(name=client_name)
return super().create(validated_data)


class ClientSerializer(rfs.ModelSerializer):
"""
Used in :class:`durin.management.commands.create_client.Command`.
"""

class Meta:
model = Client
fields = [
"name",
"token_ttl",
"throttle_rate",
]
57 changes: 57 additions & 0 deletions tests/test_commands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from io import StringIO

from django.core import management
from django.core.management import CommandError
from django.test import TestCase

from durin.models import Client


class ClientCommandTestCase(TestCase):
@staticmethod
def call_command(*args, **kwargs):
out = StringIO()
management.call_command(
"create_client", *args, stdout=out, stderr=StringIO(), **kwargs
)
return out.getvalue()

def test__create_client__valid_name(self):
client_name = "web"
self.assertEqual(Client.objects.count(), 0)

out = self.call_command(client_name)

self.assertEqual(out, "Client {} created!\n".format(client_name))
self.assertEqual(Client.objects.count(), 1)

def test__create_client__valid_data(self):
client_name = "web"
ttl = "14 00:00"
throttle_rate = "1/s"
self.assertEqual(Client.objects.count(), 0)

out = self.call_command(client_name, token_ttl=ttl, throttle_rate=throttle_rate)

self.assertEqual(out, "Client {} created!\n".format(client_name))
self.assertEqual(Client.objects.count(), 1)

def test__create_client__name_not_set_raises_exc(self):
with self.assertRaises(CommandError):
self.call_command()

def test_create_client__blank_name_raises_exc(self):
with self.assertRaisesMessage(
CommandError, "name: This field may not be blank."
):
self.call_command("")

def test_create_client__invalid_ttl_raises_exc(self):
with self.assertRaisesMessage(
CommandError,
(
"token_ttl: Duration has wrong format. "
"Use one of these formats instead: [DD] [HH:[MM:]]ss[.uuuuuu]."
),
):
self.call_command("web", token_ttl="invalid")

0 comments on commit 5732ae5

Please sign in to comment.