|
1 | | -import json |
2 | | -from collections.abc import Iterator |
3 | | -from contextlib import contextmanager |
4 | | -from logging import getLogger |
| 1 | +from logging import WARNING |
5 | 2 | from typing import TYPE_CHECKING |
6 | 3 | from typing import Any |
7 | 4 |
|
8 | | -from django.conf import settings |
| 5 | +import requests |
9 | 6 | from django.db import models |
10 | | -from django.utils import timezone |
11 | | -from django_celery_beat.models import IntervalSchedule |
12 | | -from django_celery_beat.models import PeriodicTask |
13 | 7 |
|
14 | 8 | from democrasite.users.models import User |
15 | 9 |
|
16 | 10 | from .constitution import is_constitutional |
17 | 11 |
|
18 | | -logger = getLogger(__name__) |
19 | | - |
20 | 12 | if TYPE_CHECKING: |
21 | 13 | from .models import Bill # pragma: no cover |
22 | 14 | from .models import PullRequest # pragma: no cover |
@@ -102,85 +94,49 @@ def annotate_user_vote( |
102 | 94 |
|
103 | 95 | def create_from_github( |
104 | 96 | self, |
105 | | - title: str, |
106 | | - body: str, |
107 | | - author: User, |
108 | | - diff_text: str, |
109 | 97 | pull_request: "PullRequest", |
110 | | - ) -> T: |
| 98 | + desc: str, |
| 99 | + author_uid: str, |
| 100 | + ) -> T | None: |
111 | 101 | """Validate and create a :class:`~democrasite.webiscite.models.Bill` from a |
112 | 102 | GitHub pull request |
113 | 103 |
|
114 | 104 | Args: |
115 | | - title: The title of the pull request |
116 | | - body: The body of the pull request |
117 | | - author: The user who created the pull request |
118 | | - diff_text: The text of the diff of the pull request |
119 | 105 | pull_request: The pull request instance to associate with the bill |
| 106 | + desc: The description of the bill (pull request body) |
| 107 | + author_uid: The GitHub UID of the pull request author |
120 | 108 |
|
121 | 109 | Returns: |
122 | | - The new bill instance |
| 110 | + The new bill instance, or None if the author has no linked account |
123 | 111 | """ |
124 | | - draft = pull_request.draft |
125 | | - with self._create_submit_task(enabled=not draft) as submit_task: |
126 | | - self._bill: Bill = self.model( |
127 | | - name=title, |
128 | | - description=body, |
129 | | - author=author, |
130 | | - pull_request=pull_request, |
131 | | - status=self.model.Status.DRAFT if draft else self.model.Status.OPEN, |
132 | | - constitutional=bool(is_constitutional(diff_text)), |
133 | | - _submit_task=submit_task, |
| 112 | + try: |
| 113 | + author = User.objects.filter(socialaccount__provider="github").get( |
| 114 | + socialaccount__uid=author_uid |
134 | 115 | ) |
135 | | - self._bill.full_clean() |
136 | | - self._bill.save() |
137 | | - bill = self._bill |
138 | | - bill.log("Created") |
139 | | - |
140 | | - return bill |
141 | | - |
142 | | - @contextmanager |
143 | | - def _create_submit_task(self, *, enabled: bool = True) -> Iterator[PeriodicTask]: |
144 | | - """Schedule a task to submit this bill for voting |
| 116 | + except User.DoesNotExist: |
| 117 | + # If the creator of the pull request does not have a linked account, |
| 118 | + # a Bill cannot be created and the pr is ignored. |
| 119 | + pull_request.log("No bill created (user does not exist)", level=WARNING) |
| 120 | + return None |
145 | 121 |
|
146 | | - Args: |
147 | | - enabled: Whether the task should be enabled immediately. Set to False |
148 | | - for draft bills whose voting period hasn't started yet. |
| 122 | + diff_text = requests.get(pull_request.diff_url, timeout=10).text |
| 123 | + constitutional = bool(is_constitutional(diff_text)) |
149 | 124 |
|
150 | | - Returns: |
151 | | - The task that was scheduled |
152 | | - """ |
153 | | - # This might be better as a signal but I want to keep it localized |
154 | | - voting_ends, __ = IntervalSchedule.objects.get_or_create( |
155 | | - every=settings.WEBISCITE_VOTING_PERIOD, period=IntervalSchedule.DAYS |
| 125 | + status = ( |
| 126 | + self.model.Status.DRAFT if pull_request.draft else self.model.Status.OPEN |
156 | 127 | ) |
157 | 128 |
|
158 | | - submit_task = PeriodicTask.objects.create( |
159 | | - interval=voting_ends, |
160 | | - name="bill_submit:temp", |
161 | | - task="democrasite.webiscite.tasks.submit_bill", |
162 | | - one_off=True, |
163 | | - enabled=enabled, |
164 | | - # If last_run_at is not set, the task will run relative to when the |
165 | | - # scheduler started, not when it was created |
166 | | - last_run_at=timezone.now(), |
| 129 | + bill = self.model( |
| 130 | + name=pull_request.title, |
| 131 | + description=desc, |
| 132 | + author=author, |
| 133 | + pull_request=pull_request, |
| 134 | + status=status, |
| 135 | + constitutional=constitutional, |
167 | 136 | ) |
168 | | - try: |
169 | | - yield submit_task |
170 | | - finally: |
171 | | - if not ( |
172 | | - hasattr(self, "_bill") |
173 | | - and hasattr(self._bill, "id") |
174 | | - and isinstance(self._bill.id, int) |
175 | | - ): |
176 | | - raise AttributeError( |
177 | | - "self._bill was not saved in the submit task context" |
178 | | - ) |
179 | | - |
180 | | - submit_task.name = f"bill_submit:{self._bill.id}" |
181 | | - submit_task.args = json.dumps([self._bill.id]) |
182 | | - submit_task.save() |
183 | | - self._bill.log("Scheduled %s", submit_task.name) |
184 | | - |
185 | | - # Attribute could be shared between model instances |
186 | | - del self._bill |
| 137 | + |
| 138 | + bill.full_clean() |
| 139 | + bill.save() |
| 140 | + bill.log("Created") |
| 141 | + |
| 142 | + return bill |
0 commit comments