Skip to content

Commit 9de55a0

Browse files
committed
Always exit if failsafe is exceeded
1 parent 0573525 commit 9de55a0

File tree

2 files changed

+66
-44
lines changed

2 files changed

+66
-44
lines changed

pupa/cli/commands/clean.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from datetime import datetime, timezone, timedelta
2+
import sys
23

34
import django
45
from django.apps import apps
@@ -104,8 +105,10 @@ def handle(self, args, other):
104105

105106
if num_stale_objects > args.max:
106107
print(
107-
f"WARNING: {num_stale_objects} exceeds the failsafe limit of {args.max}."
108+
f"{num_stale_objects} exceeds the failsafe limit of {args.max}. "
109+
"Run this command with a larger --max value to proceed."
108110
)
111+
sys.exit()
109112

110113
if args.yes:
111114
print("Proceeding to deletion because you specified --yes.")

pupa/tests/clean/test_clean.py

+62-43
Original file line numberDiff line numberDiff line change
@@ -24,40 +24,58 @@ def subparsers():
2424
return parser.add_subparsers(dest="subcommand")
2525

2626

27-
def create_jurisdiction():
27+
@pytest.fixture
28+
def jurisdiction():
2829
Division.objects.create(id="ocd-division/country:us", name="USA")
2930
return Jurisdiction.objects.create(id="jid", division_id="ocd-division/country:us")
3031

3132

33+
@pytest.fixture
34+
def organization(jurisdiction):
35+
return Organization.objects.create(name="WWE", jurisdiction_id="jid")
36+
37+
38+
@pytest.fixture
39+
def person():
40+
class PersonFactory:
41+
def build(self, **kwargs):
42+
person_info = {
43+
"name": "George Washington",
44+
"family_name": "Washington",
45+
}
46+
47+
person_info.update(kwargs)
48+
49+
return Person.objects.create(**person_info)
50+
51+
return PersonFactory()
52+
53+
3254
@pytest.mark.django_db
33-
def test_get_stale_objects(subparsers):
34-
_ = create_jurisdiction()
35-
o = Organization.objects.create(name="WWE", jurisdiction_id="jid")
36-
p = Person.objects.create(name="George Washington", family_name="Washington")
37-
m = p.memberships.create(organization=o)
55+
def test_get_stale_objects(subparsers, organization, person):
56+
stale_person = person.build()
57+
membership = stale_person.memberships.create(organization=organization)
3858

39-
expected_stale_objects = {p, o, m}
59+
expected_stale_objects = {stale_person, organization, membership}
4060

4161
a_week_from_now = datetime.now(tz=timezone.utc) + timedelta(days=7)
4262
with freeze_time(a_week_from_now):
43-
p = Person.objects.create(name="Thomas Jefferson", family_name="Jefferson")
44-
p.memberships.create(organization=o)
63+
fresh_person = person.build(name="Thomas Jefferson", family_name="Jefferson")
64+
fresh_person.memberships.create(organization=organization)
4565
assert set(Command(subparsers).get_stale_objects(7)) == expected_stale_objects
4666

4767

4868
@pytest.mark.django_db
49-
def test_remove_stale_objects(subparsers):
50-
_ = create_jurisdiction()
51-
o = Organization.objects.create(name="WWE", jurisdiction_id="jid")
52-
p = Person.objects.create(name="George Washington", family_name="Washington")
53-
m = p.memberships.create(organization=o)
69+
def test_remove_stale_objects(subparsers, organization, person):
70+
stale_person = person.build()
71+
membership = stale_person.memberships.create(organization=organization)
5472

55-
expected_stale_objects = {p, o, m}
73+
expected_stale_objects = {stale_person, organization, membership}
5674

5775
a_week_from_now = datetime.now(tz=timezone.utc) + timedelta(days=7)
5876
with freeze_time(a_week_from_now):
59-
p = Person.objects.create(name="Thomas Jefferson", family_name="Jefferson")
60-
p.memberships.create(organization=o)
77+
fresh_person = person.build(name="Thomas Jefferson", family_name="Jefferson")
78+
fresh_person.memberships.create(organization=organization)
6179

6280
Command(subparsers).remove_stale_objects(7)
6381
for obj in expected_stale_objects:
@@ -66,56 +84,57 @@ def test_remove_stale_objects(subparsers):
6684

6785

6886
@pytest.mark.django_db
69-
def test_clean_command(subparsers):
70-
_ = create_jurisdiction()
71-
o = Organization.objects.create(name="WWE", jurisdiction_id="jid")
72-
73-
stale_person = Person.objects.create(
74-
name="George Washington", family_name="Washington"
75-
)
76-
stale_membership = stale_person.memberships.create(organization=o)
87+
def test_clean_command(subparsers, organization, person):
88+
stale_person = person.build()
89+
stale_membership = stale_person.memberships.create(organization=organization)
7790

7891
a_week_from_now = datetime.now(tz=timezone.utc) + timedelta(days=7)
7992
with freeze_time(a_week_from_now):
80-
not_stale_person = Person.objects.create(
81-
name="Thomas Jefferson", family_name="Jefferson"
93+
fresh_person = person.build(name="Thomas Jefferson", family_name="Jefferson")
94+
not_stale_membership = fresh_person.memberships.create(
95+
organization=organization
8296
)
83-
not_stale_membership = not_stale_person.memberships.create(organization=o)
84-
o.save() # Update org's last_seen field
97+
organization.save() # Update org's last_seen field
8598

8699
# Call clean command
87100
Command(subparsers).handle(
88-
argparse.Namespace(noinput=True, report=False, window=7, yes=False), []
101+
argparse.Namespace(report=False, window=7, yes=True, max=10), []
89102
)
90103

91104
expected_stale_objects = {stale_person, stale_membership}
92105
for obj in expected_stale_objects:
93106
was_deleted = not type(obj).objects.filter(id=obj.id).exists()
94107
assert was_deleted
95108

96-
expected_not_stale_objects = {o, not_stale_person, not_stale_membership}
109+
expected_not_stale_objects = {organization, fresh_person, not_stale_membership}
97110
for obj in expected_not_stale_objects:
98111
was_not_deleted = type(obj).objects.filter(id=obj.id).exists()
99112
assert was_not_deleted
100113

101114

102115
@pytest.mark.django_db
103-
def test_clean_command_failsafe(subparsers):
104-
_ = create_jurisdiction()
105-
o = Organization.objects.create(name="WWE", jurisdiction_id="jid")
106-
107-
stale_people = [
108-
Person.objects.create(name="George Washington", family_name="Washington")
109-
for i in range(20)
110-
]
111-
stale_memberships = [ # noqa
112-
p.memberships.create(organization=o) for p in stale_people
113-
]
116+
def test_clean_command_failsafe(subparsers, organization, person):
117+
stale_people = [person.build() for i in range(20)]
118+
for p in stale_people:
119+
p.memberships.create(organization=organization)
114120

115121
a_week_from_now = datetime.now(tz=timezone.utc) + timedelta(days=7)
116122
with freeze_time(a_week_from_now):
117123
with pytest.raises(SystemExit):
118124
# Should trigger failsafe exist when deleting more than 10 objects
119125
Command(subparsers).handle(
120-
argparse.Namespace(noinput=True, report=False, window=7, yes=False), []
126+
argparse.Namespace(report=False, window=7, yes=False, max=10), []
121127
)
128+
129+
with pytest.raises(SystemExit):
130+
# Should trigger failsafe exist when deleting more than 10 objects,
131+
# even when yes is specified
132+
Command(subparsers).handle(
133+
argparse.Namespace(report=False, window=7, yes=True, max=10), []
134+
)
135+
136+
# Should proceed without error, since max is increased (1 organization,
137+
# 20 people, 20 memberships)
138+
Command(subparsers).handle(
139+
argparse.Namespace(report=False, window=7, max=41, yes=True), []
140+
)

0 commit comments

Comments
 (0)