aa-ledger 1.0.0__py3-none-any.whl → 1.0.0b2__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,9 +29,6 @@ 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
-
35
32
  # AA Ledger
36
33
  from ledger.models.characteraudit import (
37
34
  CharacterAudit,
@@ -41,6 +38,15 @@ if TYPE_CHECKING:
41
38
  logger = LoggerAddTag(get_extension_logger(__name__), __title__)
42
39
 
43
40
 
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
+
44
50
  def require_valid_price_percentage(func):
45
51
  def wrapper(*args, **kwargs):
46
52
  if not isinstance(LEDGER_PRICE_PERCENTAGE, (int, float)):
@@ -168,16 +174,17 @@ class CharacterMiningLedgerEntryManagerBase(models.Manager):
168
174
  token=token,
169
175
  )
170
176
 
171
- mining_items = operation.results(force_refresh=force_refresh)
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)
172
181
 
173
182
  # Process and update or create mining ledger entries
174
183
  self._update_or_create_objs(audit, mining_items)
175
184
 
176
185
  @transaction.atomic()
177
186
  def _update_or_create_objs(
178
- self,
179
- character: "CharacterAudit",
180
- objs: list["CharactersCharacterIdMiningGetItem"],
187
+ self, character: "CharacterAudit", objs: list[MiningLedgerContext]
181
188
  ) -> None:
182
189
  """Update or Create mining ledger entries from objs data."""
183
190
  existings_pks = set(
@@ -21,10 +21,6 @@ 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
-
28
24
  # AA Ledger
29
25
  from ledger.models.general import UpdateSectionResult
30
26
  from ledger.models.planetary import CharacterPlanet, CharacterPlanetDetails
@@ -32,6 +28,68 @@ if TYPE_CHECKING: # pragma: no cover
32
28
  logger = LoggerAddTag(get_extension_logger(__name__), __title__)
33
29
 
34
30
 
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
+
35
93
  def to_json_serializable(data):
36
94
  if isinstance(data, dict):
37
95
  return {k: to_json_serializable(v) for k, v in data.items()}
@@ -73,13 +131,16 @@ class PlanetaryManagerBase(models.Manager):
73
131
  token=token,
74
132
  )
75
133
 
76
- planets_items = operation.results(force_refresh=force_refresh)
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)
77
138
 
78
139
  self._update_or_create_objs(character=audit, objs=planets_items)
79
140
 
80
141
  @transaction.atomic()
81
142
  def _update_or_create_objs(
82
- self, character: "CharacterAudit", objs: list["PlanetGetItem"]
143
+ self, character: "CharacterAudit", objs: list[CharacterPlanetContext]
83
144
  ) -> None:
84
145
  """Update or Create planets entries from objs data."""
85
146
  # pylint: disable=import-outside-toplevel
@@ -154,14 +215,18 @@ class PlanetaryDetailsQuerySet(models.QuerySet):
154
215
  self,
155
216
  character: CharacterAudit,
156
217
  planet: "CharacterPlanetDetails",
157
- objs: list["PlanetDetailsItem"],
218
+ objs: list[CharacterPlanetLayoutContext],
158
219
  ):
159
220
  """Update or Create Layout for a given Planet"""
160
221
  return self._update_or_create(character=character, planet=planet, objs=objs)
161
222
 
162
223
  def _convert_to_dict(
163
224
  self,
164
- result: list,
225
+ result: list[
226
+ CharacterPlanetLayoutContext.LinksContext
227
+ | CharacterPlanetLayoutContext.PinsContext
228
+ | CharacterPlanetLayoutContext.RoutesContext
229
+ ],
165
230
  ) -> tuple:
166
231
  objects_list = []
167
232
  for data in result:
@@ -173,7 +238,7 @@ class PlanetaryDetailsQuerySet(models.QuerySet):
173
238
  self,
174
239
  character: "CharacterAudit",
175
240
  planet: "CharacterPlanetDetails",
176
- objs: list["PlanetDetailsItem"],
241
+ objs: list[CharacterPlanetLayoutContext],
177
242
  ):
178
243
  """Update or Create Layout for a given Planet"""
179
244
  if not isinstance(objs, list):
@@ -340,8 +405,11 @@ class PlanetaryDetailsManagerBase(models.Manager):
340
405
  )
341
406
 
342
407
  try:
343
- planets_details_items = operation.results(force_refresh=force_refresh)
408
+ planets_details_items, response = operation.results(
409
+ return_response=True, force_refresh=force_refresh
410
+ )
344
411
  is_updated = True
412
+ logger.debug("ESI response Status: %s", response.status_code)
345
413
  except HTTPNotModified:
346
414
  continue
347
415
 
@@ -358,7 +426,7 @@ class PlanetaryDetailsManagerBase(models.Manager):
358
426
  def _update_or_create_objs(
359
427
  self,
360
428
  character: "CharacterAudit",
361
- objs: list["PlanetDetailsItem"],
429
+ objs: list[CharacterPlanetLayoutContext],
362
430
  planet_id: int,
363
431
  ) -> None:
364
432
  """Update or Create planets entries from objs data."""
@@ -23,12 +23,6 @@ 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
-
32
26
  # AA Ledger
33
27
  from ledger.models.corporationaudit import (
34
28
  CorporationAudit,
@@ -38,6 +32,43 @@ if TYPE_CHECKING:
38
32
  logger = LoggerAddTag(get_extension_logger(__name__), __title__)
39
33
 
40
34
 
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
+
41
72
  class CorporationWalletQuerySet(models.QuerySet):
42
73
  # pylint: disable=duplicate-code
43
74
  def annotate_bounty_income(
@@ -200,10 +231,12 @@ class CorporationWalletManagerBase(models.Manager):
200
231
  )
201
232
  )
202
233
 
203
- # pylint: disable=duplicate-code
204
234
  try:
205
- journal_items = operation.results(force_refresh=force_refresh)
235
+ journal_items, response = operation.results(
236
+ return_response=True, force_refresh=force_refresh
237
+ )
206
238
  is_updated = True
239
+ logger.debug("ESI response Status: %s", response.status_code)
207
240
  except HTTPNotModified:
208
241
  continue
209
242
 
@@ -216,7 +249,7 @@ class CorporationWalletManagerBase(models.Manager):
216
249
  def _update_or_create_objs(
217
250
  self,
218
251
  division: "CorporationWalletDivision",
219
- objs: list["JournalItem"],
252
+ objs: list[CorporationJournalContext],
220
253
  ) -> None:
221
254
  """Update or Create wallet journal entries from objs data."""
222
255
  _new_names = []
@@ -313,7 +346,11 @@ class CorporationDivisionManagerBase(models.Manager):
313
346
  corporation_id=audit.corporation.corporation_id,
314
347
  token=token,
315
348
  )
316
- division_items = operation.results(force_refresh=force_refresh)
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)
317
354
 
318
355
  self._update_or_create_objs(corporation=audit, objs=division_items)
319
356
 
@@ -343,7 +380,11 @@ class CorporationDivisionManagerBase(models.Manager):
343
380
  corporation_id=audit.corporation.corporation_id,
344
381
  token=token,
345
382
  )
346
- division_items = operation.results(force_refresh=force_refresh)
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)
347
388
 
348
389
  self._update_or_create_objs_division(corporation=audit, objs=division_items)
349
390
 
@@ -351,7 +392,7 @@ class CorporationDivisionManagerBase(models.Manager):
351
392
  def _update_or_create_objs_division(
352
393
  self,
353
394
  corporation: "CorporationAudit",
354
- objs: list["DivisionItem"],
395
+ objs: list[CorporationDivisionContext],
355
396
  ) -> None:
356
397
  """Update or Create division entries from objs data."""
357
398
  for division in objs: # list (hanger, wallet)
ledger/models/general.py CHANGED
@@ -9,7 +9,8 @@ from dataclasses import dataclass
9
9
  from typing import Any, NamedTuple
10
10
 
11
11
  # Third Party
12
- from aiopenapi3.errors import ContentTypeError, HTTPClientError, HTTPServerError
12
+ from aiopenapi3.errors import ContentTypeError
13
+ from bravado.exception import HTTPInternalServerError
13
14
 
14
15
  # Django
15
16
  from django.core.validators import MinValueValidator
@@ -33,6 +34,7 @@ from app_utils.logging import LoggerAddTag
33
34
 
34
35
  # AA Ledger
35
36
  from ledger import __title__, app_settings
37
+ from ledger.errors import HTTPGatewayTimeoutError
36
38
  from ledger.managers.general_manager import EveEntityManager
37
39
 
38
40
  logger = LoggerAddTag(get_extension_logger(__name__), __title__)
@@ -145,8 +147,6 @@ class UpdateSectionResult(NamedTuple):
145
147
 
146
148
  is_changed: bool | None
147
149
  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,27 +231,19 @@ 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 HTTPServerError as exc:
234
+ except HTTPInternalServerError 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 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",
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",
242
243
  self,
243
244
  section.label,
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,
245
+ exc,
252
246
  )
253
- except HTTPNotModified:
254
- logger.debug("%s: Update has not changed, section: %s", self, section.label)
255
247
  return UpdateSectionResult(is_changed=False, is_updated=False)
256
248
  except (OSError, ContentTypeError) as exc:
257
249
  logger.info(
@@ -294,6 +286,7 @@ class AuditBase(models.Model):
294
286
  try:
295
287
  result = method(*args, **kwargs)
296
288
  except Exception as exc:
289
+ # TODO ADD DISCORD/AUTH NOTIFICATION?
297
290
  error_message = f"{type(exc).__name__}: {str(exc)}"
298
291
  is_token_error = isinstance(exc, (TokenError))
299
292
  logger.error(
@@ -319,23 +312,24 @@ class AuditBase(models.Model):
319
312
 
320
313
  def update_section_log(
321
314
  self,
322
- section: models.TextChoices,
323
- result: UpdateSectionResult,
315
+ section,
316
+ is_success: bool,
317
+ is_updated: bool = False,
318
+ error_message: str = None,
324
319
  ) -> None:
325
320
  """Update the status of a specific section."""
326
- error_message = result.error_message if result.error_message else ""
327
- is_success = not result.has_token_error
321
+ error_message = error_message if error_message else ""
328
322
  defaults = {
329
323
  "is_success": is_success,
330
324
  "error_message": error_message,
331
- "has_token_error": result.has_token_error,
325
+ "has_token_error": False,
332
326
  "last_run_finished_at": timezone.now(),
333
327
  }
334
- obj: UpdateStatus = self.update_status.update_or_create(
328
+ obj = self.update_status.update_or_create(
335
329
  section=section,
336
330
  defaults=defaults,
337
331
  )[0]
338
- if result.is_updated:
332
+ if is_updated:
339
333
  obj.last_update_at = obj.last_run_at
340
334
  obj.last_update_finished_at = timezone.now()
341
335
  obj.save()
@@ -347,7 +341,7 @@ class AuditBase(models.Model):
347
341
  sections_needs_update = {
348
342
  section: True for section in self.UpdateSection.get_sections()
349
343
  }
350
- existing_sections: models.QuerySet[UpdateStatus] = self.update_status.all()
344
+ existing_sections = self.update_status.all()
351
345
  needs_update = {
352
346
  obj.section: obj.need_update()
353
347
  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, result)
272
+ character.update_section_log(section, is_success=True, is_updated=result.is_updated)
273
273
 
274
274
 
275
275
  # Corporation Audit - Tasks
@@ -420,7 +420,9 @@ 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(section, result)
423
+ corporation.update_section_log(
424
+ section, is_success=True, is_updated=result.is_updated
425
+ )
424
426
 
425
427
 
426
428
  @shared_task(**TASK_DEFAULTS_ONCE)
@@ -47,48 +47,56 @@ _endpoints = [
47
47
  "GetCharactersCharacterIdWalletJournal",
48
48
  "character_id",
49
49
  needs_token=False,
50
+ return_response=True,
50
51
  ),
51
52
  EsiEndpoint(
52
53
  "Wallet",
53
54
  "GetCharactersCharacterIdWallet",
54
55
  "character_id",
55
56
  needs_token=False,
57
+ return_response=True,
56
58
  ),
57
59
  EsiEndpoint(
58
60
  "Corporation",
59
61
  "GetCorporationsCorporationIdDivisions",
60
62
  "corporation_id",
61
63
  needs_token=False,
64
+ return_response=True,
62
65
  ),
63
66
  EsiEndpoint(
64
67
  "Wallet",
65
68
  "GetCorporationsCorporationIdWallets",
66
69
  "corporation_id",
67
70
  needs_token=False,
71
+ return_response=True,
68
72
  ),
69
73
  EsiEndpoint(
70
74
  "Wallet",
71
75
  "GetCorporationsCorporationIdWalletsDivisionJournal",
72
76
  "corporation_id",
73
77
  needs_token=False,
78
+ return_response=True,
74
79
  ),
75
80
  EsiEndpoint(
76
81
  "Industry",
77
82
  "GetCharactersCharacterIdMining",
78
83
  "character_id",
79
84
  needs_token=False,
85
+ return_response=True,
80
86
  ),
81
87
  EsiEndpoint(
82
88
  "Planetary_Interaction",
83
89
  "GetCharactersCharacterIdPlanets",
84
90
  "character_id",
85
91
  needs_token=False,
92
+ return_response=True,
86
93
  ),
87
94
  EsiEndpoint(
88
95
  "Planetary_Interaction",
89
96
  "GetCharactersCharacterIdPlanetsPlanetId",
90
97
  ("character_id", "planet_id"),
91
98
  needs_token=False,
99
+ return_response=True,
92
100
  ),
93
101
  EsiEndpoint(
94
102
  "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" # pylint: disable=invalid-name
18
+ app_name: str = "ledger"
19
19
 
20
20
  urlpatterns = [
21
21
  path("", index, name="index"),