aa-ledger 1.0.0b2__py3-none-any.whl → 1.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -29,6 +29,9 @@ from ledger.decorators import log_timing
29
29
  from ledger.providers import esi
30
30
 
31
31
  if TYPE_CHECKING:
32
+ # Alliance Auth
33
+ from esi.stubs import CharactersCharacterIdMiningGetItem
34
+
32
35
  # AA Ledger
33
36
  from ledger.models.characteraudit import (
34
37
  CharacterAudit,
@@ -38,15 +41,6 @@ if TYPE_CHECKING:
38
41
  logger = LoggerAddTag(get_extension_logger(__name__), __title__)
39
42
 
40
43
 
41
- class MiningLedgerContext:
42
- """Context for Character mining ledger ESI operations."""
43
-
44
- date: timezone.datetime
45
- quantity: int
46
- solar_system_id: int
47
- type_id: int
48
-
49
-
50
44
  def require_valid_price_percentage(func):
51
45
  def wrapper(*args, **kwargs):
52
46
  if not isinstance(LEDGER_PRICE_PERCENTAGE, (int, float)):
@@ -174,17 +168,16 @@ class CharacterMiningLedgerEntryManagerBase(models.Manager):
174
168
  token=token,
175
169
  )
176
170
 
177
- mining_items, response = operation.results(
178
- return_response=True, force_refresh=force_refresh
179
- )
180
- logger.debug("ESI response Status: %s", response.status_code)
171
+ mining_items = operation.results(force_refresh=force_refresh)
181
172
 
182
173
  # Process and update or create mining ledger entries
183
174
  self._update_or_create_objs(audit, mining_items)
184
175
 
185
176
  @transaction.atomic()
186
177
  def _update_or_create_objs(
187
- self, character: "CharacterAudit", objs: list[MiningLedgerContext]
178
+ self,
179
+ character: "CharacterAudit",
180
+ objs: list["CharactersCharacterIdMiningGetItem"],
188
181
  ) -> None:
189
182
  """Update or Create mining ledger entries from objs data."""
190
183
  existings_pks = set(
@@ -21,6 +21,10 @@ from ledger.models.characteraudit import CharacterAudit
21
21
  from ledger.providers import esi
22
22
 
23
23
  if TYPE_CHECKING: # pragma: no cover
24
+ # Alliance Auth
25
+ from esi.stubs import CharactersCharacterIdPlanetsGetItem as PlanetGetItem
26
+ from esi.stubs import CharactersCharacterIdPlanetsPlanetIdGet as PlanetDetailsItem
27
+
24
28
  # AA Ledger
25
29
  from ledger.models.general import UpdateSectionResult
26
30
  from ledger.models.planetary import CharacterPlanet, CharacterPlanetDetails
@@ -28,68 +32,6 @@ if TYPE_CHECKING: # pragma: no cover
28
32
  logger = LoggerAddTag(get_extension_logger(__name__), __title__)
29
33
 
30
34
 
31
- class CharacterPlanetContext:
32
- """Context for Get colonies ESI operations."""
33
-
34
- last_update: timezone.datetime
35
- num_pins: int
36
- owner_id: int
37
- planet_id: int
38
- planet_type: str
39
- solar_system_id: int
40
- upgrade_level: int
41
-
42
-
43
- class CharacterPlanetLayoutContext:
44
- """Context for Get colony layout ESI operations."""
45
-
46
- class LinksContext:
47
- destination_pin_id: int
48
- link_level: int
49
- source_pin_id: int
50
-
51
- class PinsContext:
52
- class ContentsContext:
53
- amount: int
54
- type_id: int
55
-
56
- class ExtractorDetailsContext:
57
- head_id: int
58
- installed_time: timezone.datetime
59
- latitude: float
60
- longitude: float
61
- quantity_per_cycle: int
62
- type_id: int
63
- cycle_time: int
64
-
65
- class FactoryDetailsContext:
66
- schematic_id: int
67
-
68
- contents: list[ContentsContext] | list
69
- expiry_time: timezone.datetime
70
- extractor_details: ExtractorDetailsContext | None
71
- factory_details: FactoryDetailsContext | None
72
- install_time: timezone.datetime | None
73
- last_cycle_start: timezone.datetime | None
74
- latitude: float
75
- longitude: float
76
- pin_id: int
77
- schematic_id: int | None
78
- type_id: int
79
-
80
- class RoutesContext:
81
- content_type_id: int
82
- destination_pin_id: int
83
- quantity: int
84
- route_id: int
85
- source_pin_id: int
86
- waypoints: list
87
-
88
- links: list[LinksContext]
89
- pins: list[PinsContext]
90
- routes: list[RoutesContext]
91
-
92
-
93
35
  def to_json_serializable(data):
94
36
  if isinstance(data, dict):
95
37
  return {k: to_json_serializable(v) for k, v in data.items()}
@@ -131,16 +73,13 @@ class PlanetaryManagerBase(models.Manager):
131
73
  token=token,
132
74
  )
133
75
 
134
- planets_items, response = operation.results(
135
- return_response=True, force_refresh=force_refresh
136
- )
137
- logger.debug("ESI response Status: %s", response.status_code)
76
+ planets_items = operation.results(force_refresh=force_refresh)
138
77
 
139
78
  self._update_or_create_objs(character=audit, objs=planets_items)
140
79
 
141
80
  @transaction.atomic()
142
81
  def _update_or_create_objs(
143
- self, character: "CharacterAudit", objs: list[CharacterPlanetContext]
82
+ self, character: "CharacterAudit", objs: list["PlanetGetItem"]
144
83
  ) -> None:
145
84
  """Update or Create planets entries from objs data."""
146
85
  # pylint: disable=import-outside-toplevel
@@ -215,18 +154,14 @@ class PlanetaryDetailsQuerySet(models.QuerySet):
215
154
  self,
216
155
  character: CharacterAudit,
217
156
  planet: "CharacterPlanetDetails",
218
- objs: list[CharacterPlanetLayoutContext],
157
+ objs: list["PlanetDetailsItem"],
219
158
  ):
220
159
  """Update or Create Layout for a given Planet"""
221
160
  return self._update_or_create(character=character, planet=planet, objs=objs)
222
161
 
223
162
  def _convert_to_dict(
224
163
  self,
225
- result: list[
226
- CharacterPlanetLayoutContext.LinksContext
227
- | CharacterPlanetLayoutContext.PinsContext
228
- | CharacterPlanetLayoutContext.RoutesContext
229
- ],
164
+ result: list,
230
165
  ) -> tuple:
231
166
  objects_list = []
232
167
  for data in result:
@@ -238,7 +173,7 @@ class PlanetaryDetailsQuerySet(models.QuerySet):
238
173
  self,
239
174
  character: "CharacterAudit",
240
175
  planet: "CharacterPlanetDetails",
241
- objs: list[CharacterPlanetLayoutContext],
176
+ objs: list["PlanetDetailsItem"],
242
177
  ):
243
178
  """Update or Create Layout for a given Planet"""
244
179
  if not isinstance(objs, list):
@@ -405,11 +340,8 @@ class PlanetaryDetailsManagerBase(models.Manager):
405
340
  )
406
341
 
407
342
  try:
408
- planets_details_items, response = operation.results(
409
- return_response=True, force_refresh=force_refresh
410
- )
343
+ planets_details_items = operation.results(force_refresh=force_refresh)
411
344
  is_updated = True
412
- logger.debug("ESI response Status: %s", response.status_code)
413
345
  except HTTPNotModified:
414
346
  continue
415
347
 
@@ -426,7 +358,7 @@ class PlanetaryDetailsManagerBase(models.Manager):
426
358
  def _update_or_create_objs(
427
359
  self,
428
360
  character: "CharacterAudit",
429
- objs: list[CharacterPlanetLayoutContext],
361
+ objs: list["PlanetDetailsItem"],
430
362
  planet_id: int,
431
363
  ) -> None:
432
364
  """Update or Create planets entries from objs data."""
@@ -23,6 +23,12 @@ from ledger.models.general import EveEntity
23
23
  from ledger.providers import esi
24
24
 
25
25
  if TYPE_CHECKING:
26
+ # Alliance Auth
27
+ from esi.stubs import CorporationsCorporationIdDivisionsGet as DivisionItem
28
+ from esi.stubs import (
29
+ CorporationsCorporationIdWalletsDivisionJournalGetItem as JournalItem,
30
+ )
31
+
26
32
  # AA Ledger
27
33
  from ledger.models.corporationaudit import (
28
34
  CorporationAudit,
@@ -32,43 +38,6 @@ if TYPE_CHECKING:
32
38
  logger = LoggerAddTag(get_extension_logger(__name__), __title__)
33
39
 
34
40
 
35
- # pylint: disable=duplicate-code
36
- class CorporationJournalContext:
37
- """Context for corporation wallet journal ESI operations."""
38
-
39
- amount: float
40
- balance: float
41
- context_id: int
42
- context_id_type: str
43
- date: str
44
- description: str
45
- first_party_id: int
46
- id: int
47
- reason: str
48
- ref_type: str
49
- second_party_id: int
50
- tax: float
51
- tax_receiver_id: int
52
-
53
-
54
- class CorporationDivisionContext:
55
- class WalletContext:
56
- division: int
57
- name: str | None
58
-
59
- class HangerContext:
60
- division: int
61
- name: str | None
62
-
63
- hanger: list[HangerContext]
64
- wallet: list[WalletContext]
65
-
66
-
67
- class CorporationWalletContext:
68
- division: int
69
- balance: float
70
-
71
-
72
41
  class CorporationWalletQuerySet(models.QuerySet):
73
42
  # pylint: disable=duplicate-code
74
43
  def annotate_bounty_income(
@@ -231,12 +200,10 @@ class CorporationWalletManagerBase(models.Manager):
231
200
  )
232
201
  )
233
202
 
203
+ # pylint: disable=duplicate-code
234
204
  try:
235
- journal_items, response = operation.results(
236
- return_response=True, force_refresh=force_refresh
237
- )
205
+ journal_items = operation.results(force_refresh=force_refresh)
238
206
  is_updated = True
239
- logger.debug("ESI response Status: %s", response.status_code)
240
207
  except HTTPNotModified:
241
208
  continue
242
209
 
@@ -249,7 +216,7 @@ class CorporationWalletManagerBase(models.Manager):
249
216
  def _update_or_create_objs(
250
217
  self,
251
218
  division: "CorporationWalletDivision",
252
- objs: list[CorporationJournalContext],
219
+ objs: list["JournalItem"],
253
220
  ) -> None:
254
221
  """Update or Create wallet journal entries from objs data."""
255
222
  _new_names = []
@@ -346,11 +313,7 @@ class CorporationDivisionManagerBase(models.Manager):
346
313
  corporation_id=audit.corporation.corporation_id,
347
314
  token=token,
348
315
  )
349
- division_items, response = operation.results(
350
- return_response=True, force_refresh=force_refresh
351
- )
352
-
353
- logger.debug("ESI response Status: %s", response.status_code)
316
+ division_items = operation.results(force_refresh=force_refresh)
354
317
 
355
318
  self._update_or_create_objs(corporation=audit, objs=division_items)
356
319
 
@@ -380,11 +343,7 @@ class CorporationDivisionManagerBase(models.Manager):
380
343
  corporation_id=audit.corporation.corporation_id,
381
344
  token=token,
382
345
  )
383
- division_items, response = operation.results(
384
- return_response=True, force_refresh=force_refresh
385
- )
386
-
387
- logger.debug("ESI response Status: %s", response.status_code)
346
+ division_items = operation.results(force_refresh=force_refresh)
388
347
 
389
348
  self._update_or_create_objs_division(corporation=audit, objs=division_items)
390
349
 
@@ -392,7 +351,7 @@ class CorporationDivisionManagerBase(models.Manager):
392
351
  def _update_or_create_objs_division(
393
352
  self,
394
353
  corporation: "CorporationAudit",
395
- objs: list[CorporationDivisionContext],
354
+ objs: list["DivisionItem"],
396
355
  ) -> None:
397
356
  """Update or Create division entries from objs data."""
398
357
  for division in objs: # list (hanger, wallet)
ledger/models/general.py CHANGED
@@ -9,8 +9,7 @@ from dataclasses import dataclass
9
9
  from typing import Any, NamedTuple
10
10
 
11
11
  # Third Party
12
- from aiopenapi3.errors import ContentTypeError
13
- from bravado.exception import HTTPInternalServerError
12
+ from aiopenapi3.errors import ContentTypeError, HTTPClientError, HTTPServerError
14
13
 
15
14
  # Django
16
15
  from django.core.validators import MinValueValidator
@@ -34,7 +33,6 @@ from app_utils.logging import LoggerAddTag
34
33
 
35
34
  # AA Ledger
36
35
  from ledger import __title__, app_settings
37
- from ledger.errors import HTTPGatewayTimeoutError
38
36
  from ledger.managers.general_manager import EveEntityManager
39
37
 
40
38
  logger = LoggerAddTag(get_extension_logger(__name__), __title__)
@@ -147,6 +145,8 @@ class UpdateSectionResult(NamedTuple):
147
145
 
148
146
  is_changed: bool | None
149
147
  is_updated: bool
148
+ has_token_error: bool = False
149
+ error_message: str | None = None
150
150
  data: Any = None
151
151
 
152
152
 
@@ -231,19 +231,27 @@ class AuditBase(models.Model):
231
231
  try:
232
232
  data = fetch_func(audit=self, force_refresh=force_refresh)
233
233
  logger.debug("%s: Update has changed, section: %s", self, section.label)
234
- except HTTPInternalServerError as exc:
234
+ except HTTPServerError as exc:
235
235
  logger.debug("%s: Update has an HTTP internal server error: %s", self, exc)
236
236
  return UpdateSectionResult(is_changed=False, is_updated=False)
237
- except HTTPNotModified:
238
- logger.debug("%s: Update has not changed, section: %s", self, section.label)
239
- return UpdateSectionResult(is_changed=False, is_updated=False)
240
- except HTTPGatewayTimeoutError as exc:
241
- logger.debug(
242
- "%s: Update has a gateway timeout error, section: %s: %s",
237
+ except HTTPClientError as exc:
238
+ error_message = f"{type(exc).__name__}: {str(exc)}"
239
+ # TODO ADD DISCORD/AUTH NOTIFICATION?
240
+ logger.error(
241
+ "%s: %s: Update has Client Error: %s %s",
243
242
  self,
244
243
  section.label,
245
- exc,
244
+ error_message,
245
+ exc.status_code,
246
+ )
247
+ return UpdateSectionResult(
248
+ is_changed=False,
249
+ is_updated=False,
250
+ has_token_error=True,
251
+ error_message=error_message,
246
252
  )
253
+ except HTTPNotModified:
254
+ logger.debug("%s: Update has not changed, section: %s", self, section.label)
247
255
  return UpdateSectionResult(is_changed=False, is_updated=False)
248
256
  except (OSError, ContentTypeError) as exc:
249
257
  logger.info(
@@ -286,7 +294,6 @@ class AuditBase(models.Model):
286
294
  try:
287
295
  result = method(*args, **kwargs)
288
296
  except Exception as exc:
289
- # TODO ADD DISCORD/AUTH NOTIFICATION?
290
297
  error_message = f"{type(exc).__name__}: {str(exc)}"
291
298
  is_token_error = isinstance(exc, (TokenError))
292
299
  logger.error(
@@ -312,24 +319,23 @@ class AuditBase(models.Model):
312
319
 
313
320
  def update_section_log(
314
321
  self,
315
- section,
316
- is_success: bool,
317
- is_updated: bool = False,
318
- error_message: str = None,
322
+ section: models.TextChoices,
323
+ result: UpdateSectionResult,
319
324
  ) -> None:
320
325
  """Update the status of a specific section."""
321
- error_message = error_message if error_message else ""
326
+ error_message = result.error_message if result.error_message else ""
327
+ is_success = not result.has_token_error
322
328
  defaults = {
323
329
  "is_success": is_success,
324
330
  "error_message": error_message,
325
- "has_token_error": False,
331
+ "has_token_error": result.has_token_error,
326
332
  "last_run_finished_at": timezone.now(),
327
333
  }
328
- obj = self.update_status.update_or_create(
334
+ obj: UpdateStatus = self.update_status.update_or_create(
329
335
  section=section,
330
336
  defaults=defaults,
331
337
  )[0]
332
- if is_updated:
338
+ if result.is_updated:
333
339
  obj.last_update_at = obj.last_run_at
334
340
  obj.last_update_finished_at = timezone.now()
335
341
  obj.save()
@@ -341,7 +347,7 @@ class AuditBase(models.Model):
341
347
  sections_needs_update = {
342
348
  section: True for section in self.UpdateSection.get_sections()
343
349
  }
344
- existing_sections = self.update_status.all()
350
+ existing_sections: models.QuerySet[UpdateStatus] = self.update_status.all()
345
351
  needs_update = {
346
352
  obj.section: obj.need_update()
347
353
  for obj in existing_sections
ledger/tasks.py CHANGED
@@ -269,7 +269,7 @@ def _update_character_section(character_pk: int, section: str, force_refresh: bo
269
269
  else:
270
270
  kwargs = {}
271
271
  result = character.perform_update_status(section, method, **kwargs)
272
- character.update_section_log(section, is_success=True, is_updated=result.is_updated)
272
+ character.update_section_log(section, result)
273
273
 
274
274
 
275
275
  # Corporation Audit - Tasks
@@ -420,9 +420,7 @@ def _update_corporation_section(corporation_pk: int, section: str, force_refresh
420
420
  kwargs = {}
421
421
 
422
422
  result = corporation.perform_update_status(section, method, **kwargs)
423
- corporation.update_section_log(
424
- section, is_success=True, is_updated=result.is_updated
425
- )
423
+ corporation.update_section_log(section, result)
426
424
 
427
425
 
428
426
  @shared_task(**TASK_DEFAULTS_ONCE)
@@ -47,56 +47,48 @@ _endpoints = [
47
47
  "GetCharactersCharacterIdWalletJournal",
48
48
  "character_id",
49
49
  needs_token=False,
50
- return_response=True,
51
50
  ),
52
51
  EsiEndpoint(
53
52
  "Wallet",
54
53
  "GetCharactersCharacterIdWallet",
55
54
  "character_id",
56
55
  needs_token=False,
57
- return_response=True,
58
56
  ),
59
57
  EsiEndpoint(
60
58
  "Corporation",
61
59
  "GetCorporationsCorporationIdDivisions",
62
60
  "corporation_id",
63
61
  needs_token=False,
64
- return_response=True,
65
62
  ),
66
63
  EsiEndpoint(
67
64
  "Wallet",
68
65
  "GetCorporationsCorporationIdWallets",
69
66
  "corporation_id",
70
67
  needs_token=False,
71
- return_response=True,
72
68
  ),
73
69
  EsiEndpoint(
74
70
  "Wallet",
75
71
  "GetCorporationsCorporationIdWalletsDivisionJournal",
76
72
  "corporation_id",
77
73
  needs_token=False,
78
- return_response=True,
79
74
  ),
80
75
  EsiEndpoint(
81
76
  "Industry",
82
77
  "GetCharactersCharacterIdMining",
83
78
  "character_id",
84
79
  needs_token=False,
85
- return_response=True,
86
80
  ),
87
81
  EsiEndpoint(
88
82
  "Planetary_Interaction",
89
83
  "GetCharactersCharacterIdPlanets",
90
84
  "character_id",
91
85
  needs_token=False,
92
- return_response=True,
93
86
  ),
94
87
  EsiEndpoint(
95
88
  "Planetary_Interaction",
96
89
  "GetCharactersCharacterIdPlanetsPlanetId",
97
90
  ("character_id", "planet_id"),
98
91
  needs_token=False,
99
- return_response=True,
100
92
  ),
101
93
  EsiEndpoint(
102
94
  "Universe",
ledger/urls.py CHANGED
@@ -15,7 +15,7 @@ from ledger.views.corporation.add_corp import add_corp
15
15
  # AA Example App
16
16
  from ledger.views.index import admin, index
17
17
 
18
- app_name: str = "ledger"
18
+ app_name: str = "ledger" # pylint: disable=invalid-name
19
19
 
20
20
  urlpatterns = [
21
21
  path("", index, name="index"),