aa-ledger 1.0.4__py3-none-any.whl → 2.0.0__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.
Files changed (280) hide show
  1. {aa_ledger-1.0.4.dist-info → aa_ledger-2.0.0.dist-info}/METADATA +5 -6
  2. aa_ledger-2.0.0.dist-info/RECORD +267 -0
  3. ledger/__init__.py +2 -2
  4. ledger/admin.py +23 -18
  5. ledger/api/__init__.py +23 -7
  6. ledger/api/{ledger/admin.py → admin.py} +25 -31
  7. ledger/api/alliance.py +755 -0
  8. ledger/api/character.py +786 -0
  9. ledger/api/corporation.py +1141 -0
  10. ledger/api/{helpers.py → helpers/core.py} +33 -33
  11. ledger/api/helpers/icons.py +372 -0
  12. ledger/api/helpers/planetary_helper.py +354 -0
  13. ledger/api/planetary.py +354 -0
  14. ledger/api/schema.py +240 -15
  15. ledger/app_settings.py +11 -27
  16. ledger/auth_hooks.py +2 -2
  17. ledger/constants.py +50 -177
  18. ledger/decorators.py +2 -46
  19. ledger/forms.py +133 -39
  20. ledger/helpers/billboard.py +194 -144
  21. ledger/helpers/cache.py +105 -0
  22. ledger/helpers/discord.py +2 -4
  23. ledger/helpers/eveonline.py +160 -0
  24. ledger/helpers/ledger_data.py +23 -0
  25. ledger/helpers/ref_type.py +53 -78
  26. ledger/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
  27. ledger/locale/cs_CZ/LC_MESSAGES/django.po +349 -193
  28. ledger/locale/de/LC_MESSAGES/django.mo +0 -0
  29. ledger/locale/de/LC_MESSAGES/django.po +528 -379
  30. ledger/locale/django.pot +721 -546
  31. ledger/locale/es/LC_MESSAGES/django.mo +0 -0
  32. ledger/locale/es/LC_MESSAGES/django.po +349 -194
  33. ledger/locale/fr_FR/LC_MESSAGES/django.mo +0 -0
  34. ledger/locale/fr_FR/LC_MESSAGES/django.po +349 -193
  35. ledger/locale/it_IT/LC_MESSAGES/django.mo +0 -0
  36. ledger/locale/it_IT/LC_MESSAGES/django.po +349 -193
  37. ledger/locale/ja/LC_MESSAGES/django.mo +0 -0
  38. ledger/locale/ja/LC_MESSAGES/django.po +348 -193
  39. ledger/locale/ko_KR/LC_MESSAGES/django.mo +0 -0
  40. ledger/locale/ko_KR/LC_MESSAGES/django.po +349 -193
  41. ledger/locale/nl_NL/LC_MESSAGES/django.mo +0 -0
  42. ledger/locale/nl_NL/LC_MESSAGES/django.po +349 -193
  43. ledger/locale/pl_PL/LC_MESSAGES/django.mo +0 -0
  44. ledger/locale/pl_PL/LC_MESSAGES/django.po +350 -193
  45. ledger/locale/ru/LC_MESSAGES/django.mo +0 -0
  46. ledger/locale/ru/LC_MESSAGES/django.po +348 -193
  47. ledger/locale/sk/LC_MESSAGES/django.mo +0 -0
  48. ledger/locale/sk/LC_MESSAGES/django.po +348 -193
  49. ledger/locale/uk/LC_MESSAGES/django.mo +0 -0
  50. ledger/locale/uk/LC_MESSAGES/django.po +348 -193
  51. ledger/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
  52. ledger/locale/zh_Hans/LC_MESSAGES/django.po +348 -193
  53. ledger/managers/character_audit_manager.py +28 -20
  54. ledger/managers/character_journal_manager.py +185 -357
  55. ledger/managers/character_mining_manager.py +52 -26
  56. ledger/managers/character_planetary_manager.py +178 -136
  57. ledger/managers/corporation_audit_manager.py +36 -27
  58. ledger/managers/corporation_journal_manager.py +92 -56
  59. ledger/managers/general_manager.py +8 -7
  60. ledger/migrations/0018_remove_characterplanet_ledger_char_planet__58a5b6_idx_and_more.py +44 -0
  61. ledger/migrations/0019_rename_characteraudit_characterowner_and_more.py +48 -0
  62. ledger/models/__init__.py +5 -11
  63. ledger/models/characteraudit.py +101 -109
  64. ledger/models/corporationaudit.py +94 -49
  65. ledger/models/general.py +105 -211
  66. ledger/models/helpers/update_manager.py +302 -0
  67. ledger/models/planetary.py +60 -205
  68. ledger/providers.py +101 -0
  69. ledger/static/ledger/css/{ledger.css → aa-ledger.css} +54 -28
  70. ledger/static/ledger/js/aa-ledger.js +124 -0
  71. ledger/static/ledger/js/charts.js +25 -1
  72. ledger/static/ledger/js/view-alliance-ledger.js +383 -0
  73. ledger/static/ledger/js/view-character-ledger.js +388 -0
  74. ledger/static/ledger/js/view-corporation-ledger.js +402 -0
  75. ledger/static/ledger/js/view-planetary.js +492 -0
  76. ledger/static/ledger/libs/amCharts/5.14.4/js/flow.js +2 -0
  77. ledger/static/ledger/libs/amCharts/5.14.4/js/index.js +2 -0
  78. ledger/static/ledger/libs/amCharts/5.14.4/js/percent.js +2 -0
  79. ledger/static/ledger/libs/amCharts/5.14.4/js/themes/Animated.js +2 -0
  80. ledger/static/ledger/libs/amCharts/5.14.4/js/themes/Dark.js +2 -0
  81. ledger/static/ledger/libs/amCharts/5.14.4/js/xy.js +2 -0
  82. ledger/static/ledger/libs/datatables/2.3.5/css/dataTables.bootstrap5.css +610 -0
  83. ledger/static/ledger/libs/datatables/2.3.5/js/dataTables.bootstrap5.js +122 -0
  84. ledger/static/ledger/libs/datatables/2.3.5/js/dataTables.js +14127 -0
  85. ledger/static/ledger/libs/datatables/Extensions/ColumnControl/1.1.1/css/columnControl.bootstrap5.css +516 -0
  86. ledger/static/ledger/libs/datatables/Extensions/ColumnControl/1.1.1/css/columnControl.dataTables.css +529 -0
  87. ledger/static/ledger/libs/datatables/Extensions/ColumnControl/1.1.1/js/columnControl.bootstrap5.js +73 -0
  88. ledger/static/ledger/libs/datatables/Extensions/ColumnControl/1.1.1/js/dataTables.columnControl.js +3090 -0
  89. ledger/static/ledger/libs/datatables/Extensions/FixedHeader/4.0.4/css/fixedHeader.bootstrap5.css +20 -0
  90. ledger/static/ledger/libs/datatables/Extensions/FixedHeader/4.0.4/js/dataTables.fixedHeader.js +1203 -0
  91. ledger/static/ledger/libs/datatables/Extensions/FixedHeader/4.0.4/js/fixedHeader.bootstrap5.js +59 -0
  92. ledger/tasks.py +157 -141
  93. ledger/templates/ledger/base.html +59 -21
  94. ledger/templates/ledger/bundles/aa-ledger-css.html +3 -0
  95. ledger/templates/ledger/bundles/aa-ledger-js.html +3 -0
  96. ledger/templates/ledger/bundles/view-alliance-ledger-js.html +14 -0
  97. ledger/templates/ledger/bundles/view-character-ledger-js.html +15 -0
  98. ledger/templates/ledger/bundles/view-character-planetary-css.html +3 -0
  99. ledger/templates/ledger/bundles/view-character-planetary-js.html +4 -0
  100. ledger/templates/ledger/bundles/view-corporation-ledger-js.html +15 -0
  101. ledger/templates/ledger/partials/modal/confirm.html +0 -1
  102. ledger/templates/ledger/partials/modal/request-accept-delete-alliance.html +38 -0
  103. ledger/templates/ledger/partials/modal/request-accept-delete-character.html +38 -0
  104. ledger/templates/ledger/partials/modal/request-accept-delete-corporation.html +38 -0
  105. ledger/templates/ledger/partials/modal/request-accept-switch-notification.html +38 -0
  106. ledger/templates/ledger/partials/modal/request-view-alliance-details.html +26 -0
  107. ledger/templates/ledger/partials/modal/request-view-character-details.html +26 -0
  108. ledger/templates/ledger/partials/modal/request-view-corporation-details.html +26 -0
  109. ledger/templates/ledger/partials/modal/request-view-extractor.html +32 -0
  110. ledger/templates/ledger/partials/modal/request-view-factory.html +31 -0
  111. ledger/templates/ledger/partials/{menu → navigation}/administration.html +8 -0
  112. ledger/templates/ledger/partials/{menu → navigation}/navigation.html +2 -2
  113. ledger/templates/ledger/partials/{administration → view-alliance-administration}/alliance_corporations.html +3 -3
  114. ledger/templates/ledger/partials/view-alliance-administration/dashboard.html +81 -0
  115. ledger/templates/ledger/partials/view-alliance-ledger/alliance-billboard.html +25 -0
  116. ledger/templates/ledger/partials/view-alliance-ledger/alliance-ledger-details.html +21 -0
  117. ledger/templates/ledger/partials/view-alliance-ledger/alliance-table.html +24 -0
  118. ledger/templates/ledger/partials/view-alliance-ledger/information/daily.html +18 -0
  119. ledger/templates/ledger/partials/view-alliance-ledger/information/hourly.html +18 -0
  120. ledger/templates/ledger/partials/view-alliance-ledger/information/summary.html +19 -0
  121. ledger/templates/ledger/partials/{administration → view-character-administration}/character.html +1 -9
  122. ledger/templates/ledger/partials/{administration → view-character-administration}/dashboard.html +0 -34
  123. ledger/templates/ledger/partials/view-character-ledger/character-billboard.html +25 -0
  124. ledger/templates/ledger/partials/view-character-ledger/character-ledger-details.html +21 -0
  125. ledger/templates/ledger/partials/view-character-ledger/character-table.html +25 -0
  126. ledger/templates/ledger/partials/view-character-ledger/information/daily.html +18 -0
  127. ledger/templates/ledger/partials/view-character-ledger/information/hourly.html +18 -0
  128. ledger/templates/ledger/partials/view-character-ledger/information/summary.html +19 -0
  129. ledger/templates/ledger/partials/view-character-planetary/extractor-table.html +24 -0
  130. ledger/templates/ledger/partials/view-character-planetary/factory-table.html +24 -0
  131. ledger/templates/ledger/partials/view-character-planetary/planetary-table.html +22 -0
  132. ledger/templates/ledger/partials/view-character-planetary/storage-table.html +23 -0
  133. ledger/templates/ledger/partials/{administration → view-corporation-administration}/corporation.html +5 -13
  134. ledger/templates/ledger/partials/{administration → view-corporation-administration}/corporation_characters.html +1 -1
  135. ledger/templates/ledger/partials/view-corporation-administration/dashboard.html +81 -0
  136. ledger/templates/ledger/partials/view-corporation-ledger/corporation-billboard.html +25 -0
  137. ledger/templates/ledger/partials/view-corporation-ledger/corporation-ledger-details.html +21 -0
  138. ledger/templates/ledger/partials/view-corporation-ledger/corporation-table.html +26 -0
  139. ledger/templates/ledger/partials/view-corporation-ledger/information/daily.html +18 -0
  140. ledger/templates/ledger/partials/view-corporation-ledger/information/hourly.html +18 -0
  141. ledger/templates/ledger/partials/view-corporation-ledger/information/summary.html +19 -0
  142. ledger/templates/ledger/view-administration.html +62 -0
  143. ledger/templates/ledger/view-alliance-administration.html +49 -0
  144. ledger/templates/ledger/view-alliance-ledger.html +72 -0
  145. ledger/templates/ledger/view-alliance-overview.html +131 -0
  146. ledger/templates/ledger/view-character-administration.html +42 -0
  147. ledger/templates/ledger/view-character-ledger.html +73 -0
  148. ledger/templates/ledger/view-character-overview.html +135 -0
  149. ledger/templates/ledger/view-character-planetary-overview.html +135 -0
  150. ledger/templates/ledger/view-character-planetary.html +73 -0
  151. ledger/templates/ledger/view-corporation-administration.html +42 -0
  152. ledger/templates/ledger/view-corporation-ledger.html +73 -0
  153. ledger/templates/ledger/view-corporation-overview.html +131 -0
  154. ledger/templatetags/ledger.py +3 -5
  155. ledger/tests/__init__.py +187 -0
  156. ledger/tests/test_admin.py +164 -68
  157. ledger/tests/test_auth_hook.py +31 -13
  158. ledger/tests/test_decarators.py +14 -79
  159. ledger/tests/test_discord_installed.py +0 -1
  160. ledger/tests/test_helpers/test_ledger_data.py +19 -0
  161. ledger/tests/test_managers/test_character_audit_manager.py +111 -69
  162. ledger/tests/test_managers/test_character_journal_manager.py +48 -208
  163. ledger/tests/test_managers/test_character_mining_manager.py +37 -16
  164. ledger/tests/test_managers/test_corporation_division_manager.py +66 -28
  165. ledger/tests/test_managers/test_corporation_journal_manager.py +39 -42
  166. ledger/tests/test_managers/test_general_manager.py +78 -18
  167. ledger/tests/test_managers/test_planetary_manager.py +73 -32
  168. ledger/tests/test_models/test_characteraudit.py +58 -74
  169. ledger/tests/test_models/test_characterminingledger.py +20 -26
  170. ledger/tests/test_models/test_characterwalletjournal.py +10 -33
  171. ledger/tests/test_models/test_corporationaudit.py +41 -35
  172. ledger/tests/test_models/test_corporationwalletjournal.py +35 -32
  173. ledger/tests/test_models/test_general.py +44 -11
  174. ledger/tests/test_models/test_planetary.py +14 -80
  175. ledger/tests/test_templatetags.py +2 -7
  176. ledger/tests/test_views/corporation/test_add_corp.py +16 -35
  177. ledger/tests/test_views/corporation/test_delete_corporation.py +66 -42
  178. ledger/tests/test_views/test_access.py +512 -545
  179. ledger/tests/test_views/test_add_ally.py +57 -46
  180. ledger/tests/test_views/test_add_char.py +21 -33
  181. ledger/tests/test_views/test_delete_character.py +24 -21
  182. ledger/tests/testdata/README_ESI_STUB.md +430 -0
  183. ledger/tests/testdata/esi_stub_openapi.py +511 -0
  184. ledger/tests/testdata/integrations/__init__.py +0 -0
  185. ledger/tests/testdata/{load_eveuniverse.py → integrations/eveuniverse.py} +0 -1
  186. ledger/tests/testdata/integrations/planetary.py +13 -0
  187. ledger/tests/testdata/json/factory.json +281 -0
  188. ledger/tests/testdata/json/inactive.json +281 -0
  189. ledger/tests/testdata/json/pins.json +175 -272
  190. ledger/tests/testdata/json/route.json +95 -528
  191. ledger/tests/testdata/test_esi_stub.py +468 -0
  192. ledger/tests/testdata/utils.py +601 -0
  193. ledger/thirdparty/charlink_hook.py +60 -30
  194. ledger/urls.py +0 -135
  195. ledger/views/alliance/add_ally.py +2 -4
  196. ledger/views/alliance/alliance_ledger.py +64 -147
  197. ledger/views/character/add_char.py +8 -10
  198. ledger/views/character/character_ledger.py +60 -126
  199. ledger/views/character/planetary.py +5 -98
  200. ledger/views/corporation/add_corp.py +10 -12
  201. ledger/views/corporation/corporation_ledger.py +65 -327
  202. ledger/views/index.py +92 -30
  203. aa_ledger-1.0.4.dist-info/RECORD +0 -236
  204. ledger/api/api_helper/planetary_helper.py +0 -107
  205. ledger/api/ledger/__init__.py +0 -7
  206. ledger/api/ledger/planetary.py +0 -231
  207. ledger/helpers/alliance.py +0 -317
  208. ledger/helpers/character.py +0 -251
  209. ledger/helpers/core.py +0 -665
  210. ledger/helpers/corporation.py +0 -427
  211. ledger/helpers/data_exporter.py +0 -452
  212. ledger/static/ledger/js/planetary-confirm.js +0 -66
  213. ledger/static/ledger/js/planetary.js +0 -143
  214. ledger/templates/ledger/admin.html +0 -43
  215. ledger/templates/ledger/allyledger/admin/alliance_administration.html +0 -46
  216. ledger/templates/ledger/allyledger/admin/alliance_overview.html +0 -108
  217. ledger/templates/ledger/allyledger/alliance_ledger.html +0 -86
  218. ledger/templates/ledger/bundles/character-ledger-bundles.html +0 -66
  219. ledger/templates/ledger/bundles/corporation-ledger-bundles.html +0 -75
  220. ledger/templates/ledger/bundles/ledger-bundles.html +0 -23
  221. ledger/templates/ledger/bundles/ledger-css.html +0 -3
  222. ledger/templates/ledger/bundles/planetary-bundles.html +0 -50
  223. ledger/templates/ledger/bundles/table-css.html +0 -3
  224. ledger/templates/ledger/charledger/admin/character_administration.html +0 -39
  225. ledger/templates/ledger/charledger/admin/character_overview.html +0 -106
  226. ledger/templates/ledger/charledger/character_ledger.html +0 -94
  227. ledger/templates/ledger/charledger/planetary/admin/planetary_overview.html +0 -123
  228. ledger/templates/ledger/charledger/planetary/planetary_ledger.html +0 -54
  229. ledger/templates/ledger/corpledger/admin/corporation_administration.html +0 -39
  230. ledger/templates/ledger/corpledger/admin/corporation_overview.html +0 -108
  231. ledger/templates/ledger/corpledger/corporation_ledger.html +0 -129
  232. ledger/templates/ledger/data-export.html +0 -78
  233. ledger/templates/ledger/error.html +0 -31
  234. ledger/templates/ledger/partials/form/error-message.html +0 -1
  235. ledger/templates/ledger/partials/information/daily.html +0 -56
  236. ledger/templates/ledger/partials/information/day.html +0 -48
  237. ledger/templates/ledger/partials/information/error.html +0 -8
  238. ledger/templates/ledger/partials/information/hourly.html +0 -53
  239. ledger/templates/ledger/partials/information/summary.html +0 -88
  240. ledger/templates/ledger/partials/information/view_character_content.html +0 -35
  241. ledger/templates/ledger/partials/modal/switchalarm_confirm.html +0 -39
  242. ledger/templates/ledger/partials/modal/view_extractor.html +0 -48
  243. ledger/templates/ledger/partials/modal/view_factory.html +0 -123
  244. ledger/templates/ledger/partials/table/char-ledger.html +0 -85
  245. ledger/templates/ledger/partials/table/corp-ledger.html +0 -66
  246. ledger/templates/ledger/partials/table/planetary.html +0 -18
  247. ledger/templates/ledger/partials/thirdparty/billboard.html +0 -22
  248. ledger/templates/ledger/partials/view/card.html +0 -160
  249. ledger/templates/ledger/permission.html +0 -2
  250. ledger/tests/test_helpers/test_billboard.py +0 -11
  251. ledger/tests/test_helpers/test_data_exporter.py +0 -207
  252. ledger/tests/test_tasks.py +0 -282
  253. ledger/tests/test_view_helpers/test_core.py +0 -47
  254. ledger/tests/test_views/corporation/test_corporation.py +0 -267
  255. ledger/tests/test_views/test_planetary.py +0 -137
  256. ledger/tests/testdata/esi_stub.py +0 -109
  257. ledger/tests/testdata/esi_stub_migration.py +0 -80
  258. ledger/tests/testdata/generate_characteraudit.py +0 -106
  259. ledger/tests/testdata/generate_corporationaudit.py +0 -74
  260. ledger/tests/testdata/generate_events.py +0 -31
  261. ledger/tests/testdata/generate_miningledger.py +0 -13
  262. ledger/tests/testdata/generate_planets.py +0 -48
  263. ledger/tests/testdata/generate_walletjournal.py +0 -42
  264. ledger/tests/testdata/json/czarno-pins.json +0 -240
  265. ledger/tests/testdata/json/czarno-routes.json +0 -165
  266. ledger/tests/testdata/json/pins2.json +0 -538
  267. {aa_ledger-1.0.4.dist-info → aa_ledger-2.0.0.dist-info}/WHEEL +0 -0
  268. {aa_ledger-1.0.4.dist-info → aa_ledger-2.0.0.dist-info}/licenses/LICENSE +0 -0
  269. /ledger/{tests/test_view_helpers → api/helpers}/__init__.py +0 -0
  270. /ledger/templates/ledger/bundles/{ally-administration-bundles.html → view-alliance-administration-js.html} +0 -0
  271. /ledger/templates/ledger/bundles/{char-administration-bundles.html → view-character-administration-js.html} +0 -0
  272. /ledger/templates/ledger/bundles/{corp-administration-bundles.html → view-corporation-administration-js.html} +0 -0
  273. /ledger/templates/ledger/partials/{administration → view-alliance-administration}/alliance.html +0 -0
  274. /ledger/tests/testdata/{esi.json → esi_test_data.json} +0 -0
  275. /ledger/tests/testdata/{allianceauth.json → integrations/allianceauth.json} +0 -0
  276. /ledger/tests/testdata/{load_allianceauth.py → integrations/allianceauth.py} +0 -0
  277. /ledger/tests/testdata/{eveentity.json → integrations/eveentity.json} +0 -0
  278. /ledger/tests/testdata/{load_eveentity.py → integrations/eveentity.py} +0 -0
  279. /ledger/tests/testdata/{eveuniverse.json → integrations/eveuniverse.json} +0 -0
  280. /ledger/tests/testdata/{planetary.json → integrations/planetary.json} +0 -0
@@ -0,0 +1,430 @@
1
+ # ESI OpenAPI Stub System
2
+
3
+ Ein eigenständiges Stub-System für ESI OpenAPI-Clients, das für Tests verwendet werden kann, um vordefinierte Testdaten zurückzugeben, ohne echte API-Aufrufe zu machen.
4
+
5
+ ## Übersicht
6
+
7
+ **Wichtig:** Dieses Stub-System gibt Objekte mit Attributen zurück (wie OpenAPI 3 Clients), **nicht** Dictionaries!
8
+
9
+ ```python
10
+ # ✓ Richtig - Attributzugriff
11
+ result.total_sp
12
+ result.skills[0].skill_id
13
+
14
+ # ✗ Falsch - Dictionary-Zugriff
15
+ result["total_sp"] # AttributeError!
16
+ result["skills"][0]["skill_id"] # AttributeError!
17
+ ```
18
+
19
+ Dieses System bietet vier Hauptklassen:
20
+
21
+ - **`EsiEndpoint`**: Definition eines ESI-Endpoints mit optionalem Side-Effect
22
+ - **`EsiOperationStub`**: Simuliert eine ESI-Operation und stellt `result()` und `results()` Methoden bereit
23
+ - **`EsiCategoryStub`**: Repräsentiert eine ESI-Kategorie (z.B. Skills, Character, Wallet)
24
+ - **`EsiClientStub`**: Der Haupt-Client, der `ESIClientProvider.client` nachahmt
25
+
26
+ ## Verwendung
27
+
28
+ ### Endpoints sind erforderlich!
29
+
30
+ **Wichtig:** Die `endpoints` Liste ist IMMER erforderlich! Sie definiert, welche ESI-Methoden verfügbar sind.
31
+
32
+ ```python
33
+ from taxsystem.tests.testdata.esi_stub_openapi import (
34
+ EsiEndpoint,
35
+ create_esi_client_stub,
36
+ )
37
+
38
+ # Endpoints definieren (ERFORDERLICH!)
39
+ endpoints = [
40
+ EsiEndpoint("Character", "GetCharactersCharacterId", "character_id"),
41
+ EsiEndpoint("Skills", "GetCharactersCharacterIdSkills", "character_id"),
42
+ ]
43
+
44
+ test_data = {
45
+ "Character": {"GetCharactersCharacterId": {"character_id": 12345, "name": "Test"}},
46
+ "Skills": {"GetCharactersCharacterIdSkills": {"total_sp": 50000000, "skills": []}},
47
+ }
48
+
49
+ # Stub erstellen - endpoints MÜSSEN angegeben werden
50
+ stub = create_esi_client_stub(test_data, endpoints=endpoints)
51
+
52
+ # Nur registrierte Endpoints sind verfügbar
53
+ operation = stub.Character.GetCharactersCharacterId(character_id=12345)
54
+ result = operation.result()
55
+ ```
56
+
57
+ Ohne `endpoints` wird ein `ValueError` geworfen:
58
+
59
+ ```python
60
+ # Dies wirft ValueError!
61
+ stub = create_esi_client_stub(test_data) # ❌ Fehler: endpoints fehlt
62
+ ```
63
+
64
+ ### Grundlegende Verwendung
65
+
66
+ ```python
67
+ from taxsystem.tests.testdata.esi_stub_openapi import (
68
+ EsiEndpoint,
69
+ create_esi_client_stub,
70
+ )
71
+
72
+ # Testdaten definieren
73
+ test_data = {
74
+ "Skills": {
75
+ "GetCharactersCharacterIdSkills": {
76
+ "skills": [
77
+ {"skill_id": 12345, "trained_skill_level": 5, "active_skill_level": 5}
78
+ ],
79
+ "total_sp": 50000000,
80
+ "unallocated_sp": 100000,
81
+ }
82
+ }
83
+ }
84
+
85
+ # Endpoints definieren (ERFORDERLICH!)
86
+ endpoints = [
87
+ EsiEndpoint("Skills", "GetCharactersCharacterIdSkills", "character_id"),
88
+ ]
89
+
90
+ # Stub erstellen
91
+ stub = create_esi_client_stub(test_data, endpoints=endpoints)
92
+
93
+ # Verwenden wie echten ESI-Client
94
+ operation = stub.Skills.GetCharactersCharacterIdSkills(character_id=12345)
95
+ result = operation.result()
96
+
97
+ # Ergebnis ist ein Objekt mit Attributen (wie OpenAPI 3)
98
+ print(result.total_sp) # 50000000
99
+ print(result.skills[0].skill_id) # 12345
100
+ ```
101
+
102
+ ### Mit `result()` für einzelne Ergebnisse
103
+
104
+ ```python
105
+ # Für Methoden, die ein einzelnes Objekt zurückgeben
106
+ operation = stub.Character.GetCharactersCharacterId(character_id=12345)
107
+ data = operation.result()
108
+ ```
109
+
110
+ ### Mit `results()` für Listen
111
+
112
+ ```python
113
+ # Für Methoden, die eine Liste zurückgeben (paginierte Daten)
114
+ operation = stub.Skills.GetCharactersCharacterIdSkillqueue(character_id=12345)
115
+ data_list = operation.results()
116
+ ```
117
+
118
+ ### Mit Mock/Patch in Tests
119
+
120
+ ```python
121
+ from unittest.mock import patch, PropertyMock
122
+ from taxsystem.tests.testdata.esi_stub_openapi import (
123
+ EsiEndpoint,
124
+ create_esi_client_stub,
125
+ )
126
+
127
+
128
+ @patch("taxsystem.providers.esi")
129
+ def test_something(self, mock_esi):
130
+ # Endpoints definieren
131
+ endpoints = [
132
+ EsiEndpoint("Skills", "GetCharactersCharacterIdSkills", "character_id"),
133
+ ]
134
+
135
+ # Stub erstellen
136
+ stub = create_esi_client_stub(test_data, endpoints=endpoints)
137
+
138
+ # ESI-Client durch Stub ersetzen (client ist eine Property)
139
+ type(mock_esi).client = PropertyMock(return_value=stub)
140
+
141
+ # Ihre Testlogik hier...
142
+ ```
143
+
144
+ ### Dynamische Testdaten
145
+
146
+ Sie können auch Callables verwenden, um dynamische Testdaten basierend auf Eingabeparametern zu generieren:
147
+
148
+ ```python
149
+ def dynamic_skills(character_id, **kwargs):
150
+ return {"total_sp": character_id * 1000, "skills": [], "unallocated_sp": 0}
151
+
152
+
153
+ test_data = {"Skills": {"GetCharactersCharacterIdSkills": dynamic_skills}}
154
+
155
+ # Endpoints definieren
156
+ endpoints = [
157
+ EsiEndpoint("Skills", "GetCharactersCharacterIdSkills", "character_id"),
158
+ ]
159
+
160
+ stub = create_esi_client_stub(test_data, endpoints=endpoints)
161
+ operation = stub.Skills.GetCharactersCharacterIdSkills(character_id=100)
162
+ result = operation.result()
163
+ # result.total_sp wird 100000 sein
164
+ ```
165
+
166
+ ### Exceptions/Side-Effects simulieren
167
+
168
+ Sie können ESI-Exceptions über Endpoint-Definitionen simulieren:
169
+
170
+ ```python
171
+ from esi.exceptions import HTTPNotModified, HTTPClientError, HTTPServerError
172
+ from taxsystem.tests.testdata.esi_stub_openapi import (
173
+ EsiEndpoint,
174
+ create_esi_client_stub,
175
+ )
176
+
177
+ # Endpoints mit Side-Effects definieren
178
+ endpoints = [
179
+ EsiEndpoint(
180
+ "Character",
181
+ "GetCharactersCharacterId",
182
+ "character_id",
183
+ side_effect=HTTPNotModified(304, {}),
184
+ ),
185
+ EsiEndpoint(
186
+ "Skills",
187
+ "GetCharactersCharacterIdSkills",
188
+ "character_id",
189
+ side_effect=HTTPClientError(404, {}, b"Not Found"),
190
+ ),
191
+ ]
192
+
193
+ # Testdaten (werden nur zurückgegeben, wenn kein side_effect auftritt)
194
+ test_data = {
195
+ "Character": {"GetCharactersCharacterId": {"character_id": 12345, "name": "Test"}},
196
+ "Skills": {"GetCharactersCharacterIdSkills": {"total_sp": 0, "skills": []}},
197
+ }
198
+
199
+ stub = create_esi_client_stub(test_data, endpoints=endpoints)
200
+
201
+ # Wirft HTTPNotModified
202
+ try:
203
+ operation = stub.Character.GetCharactersCharacterId(character_id=12345)
204
+ result = operation.result()
205
+ except HTTPNotModified:
206
+ print("Cached data is still valid!")
207
+
208
+ # Wirft HTTPClientError
209
+ try:
210
+ operation = stub.Skills.GetCharactersCharacterIdSkills(character_id=12345)
211
+ result = operation.result()
212
+ except HTTPClientError:
213
+ print("Client error occurred!")
214
+ ```
215
+
216
+ #### Unterstützte Exceptions:
217
+
218
+ - `HTTPNotModified` (304) - Cached data ist noch gültig
219
+ - `HTTPClientError` (4xx) - Client-Fehler (z.B. 404, 403)
220
+ - `HTTPServerError` (5xx) - Server-Fehler
221
+ - `OSError` - Netzwerk-/Verbindungsfehler
222
+ - Jede andere Python Exception
223
+
224
+ #### Ohne Side-Effect:
225
+
226
+ Endpoints ohne `side_effect` geben normale Testdaten zurück:
227
+
228
+ ```python
229
+ endpoints = [
230
+ EsiEndpoint(
231
+ "Character",
232
+ "GetCharactersCharacterId",
233
+ "character_id",
234
+ # Kein side_effect - gibt Testdaten zurück
235
+ ),
236
+ ]
237
+
238
+ test_data = {
239
+ "Character": {
240
+ "GetCharactersCharacterId": {"character_id": 12345, "name": "Test Pilot"}
241
+ }
242
+ }
243
+
244
+ stub = create_esi_client_stub(test_data, endpoints=endpoints)
245
+ operation = stub.Character.GetCharactersCharacterId(character_id=12345)
246
+ result = operation.result()
247
+ print(result.name) # "Test Pilot"
248
+ ```
249
+
250
+ ### Mit return_response Parameter
251
+
252
+ ```python
253
+ # Tuple aus (data, response) erhalten
254
+ operation = stub.Character.GetCharactersCharacterId(character_id=12345)
255
+ data, response = operation.result(return_response=True)
256
+
257
+ print(data.character_id) # 12345678
258
+ print(response.status_code) # 200
259
+ print(response.headers) # {}
260
+ ```
261
+
262
+ ## Struktur der Testdaten
263
+
264
+ Die Testdaten sollten folgende Struktur haben:
265
+
266
+ ```python
267
+ {
268
+ "KategorieName": {
269
+ "MethodenName": {...}, # Dict oder Liste von Dicts
270
+ "AndereMethode": {...},
271
+ },
272
+ "AndereKategorie": {"MethodenName": {...}},
273
+ }
274
+ ```
275
+
276
+ ### Beispiel:
277
+
278
+ ```python
279
+ {
280
+ "Skills": {
281
+ "GetCharactersCharacterIdSkills": {"skills": [...], "total_sp": 50000000},
282
+ "GetCharactersCharacterIdSkillqueue": [
283
+ {"skill_id": 111, "queue_position": 0},
284
+ {"skill_id": 222, "queue_position": 1},
285
+ ],
286
+ },
287
+ "Character": {
288
+ "GetCharactersCharacterId": {"character_id": 12345, "name": "Test Pilot"}
289
+ },
290
+ }
291
+ ```
292
+
293
+ ### Auswahl von Methodendaten per Parameterwert
294
+
295
+ Die Stub-Implementierung unterstützt auch Mapping-Objekte, bei denen die Werte nach
296
+ eingehenden Parametern ausgewählt werden. Wenn für eine Methode statt eines einfachen
297
+ Objekts ein Dictionary angegeben wird, versucht der Stub, einen passenden Eintrag
298
+ zu finden, dessen Schlüssel dem Parameterwert (als String oder Integer) entspricht.
299
+
300
+ Beispiel: Wenn der Endpoint `character_id` als Parameter verwendet wird, kann das
301
+ Testdaten-Format so aussehen:
302
+
303
+ ```python
304
+ {
305
+ "Character": {
306
+ "GetCharactersCharacterId": {
307
+ "12345": {"character_id": 12345, "name": "Alpha"},
308
+ "67890": {"character_id": 67890, "name": "Beta"},
309
+ }
310
+ }
311
+ }
312
+ ```
313
+
314
+ Aufruf mit `character_id=12345` liefert dann automatisch den Eintrag für den Schlüssel
315
+ `"12345"`. Numerische Schlüssel werden ebenfalls unterstützt (z. B. `12345` statt
316
+ `"12345"`).
317
+
318
+ Wenn das Mapping nur einen Eintrag enthält, wird dieser Eintrag als Fallback immer
319
+ zurückgegeben (praktisch für einfache Defaults oder wenn nur ein Testfall benötigt wird).
320
+
321
+ ### Sequentielle Side-Effects
322
+
323
+ Endpoints können als `side_effect` eine Exception oder eine Liste von Exceptions/Werten
324
+ haben. Wird eine Liste übergeben, werden die Einträge sequenziell verbraucht (nützlich
325
+ für Tests, die mehrere Aufrufe mit unterschiedlichen Ergebnissen simulieren).
326
+
327
+ ### Automatisches Laden aus JSON
328
+
329
+ `create_esi_client_stub(test_data_config=None, endpoints=...)` lädt automatisch
330
+ Testdaten aus der Datei `esi_test_data.json` im gleichen Verzeichnis, wenn
331
+ `test_data_config` nicht übergeben wird. Die `endpoints`-Liste bleibt weiterhin
332
+ erforderlich und wird validiert.
333
+
334
+ ### Mit Endpoints und Side-Effects:
335
+
336
+ ```python
337
+ from esi.exceptions import HTTPNotModified, HTTPClientError
338
+ from taxsystem.tests.testdata.esi_stub_openapi import (
339
+ EsiEndpoint,
340
+ create_esi_client_stub,
341
+ )
342
+
343
+ # Endpoints definieren
344
+ endpoints = [
345
+ EsiEndpoint(
346
+ "Skills",
347
+ "GetCharactersCharacterIdSkills",
348
+ "character_id",
349
+ side_effect=HTTPNotModified(304, {}),
350
+ ),
351
+ EsiEndpoint(
352
+ "Skills",
353
+ "GetCharactersCharacterIdSkillqueue",
354
+ "character_id",
355
+ # Kein side_effect
356
+ ),
357
+ ]
358
+
359
+ # Testdaten
360
+ test_data = {
361
+ "Skills": {
362
+ "GetCharactersCharacterIdSkills": {"total_sp": 0, "skills": []},
363
+ "GetCharactersCharacterIdSkillqueue": [{"skill_id": 123}],
364
+ }
365
+ }
366
+
367
+ # Stub erstellen
368
+ stub = create_esi_client_stub(test_data, endpoints=endpoints)
369
+ ```
370
+
371
+ ````
372
+
373
+ ## Unterschied zwischen `result()` und `results()`
374
+
375
+ - **`result()`**: Gibt die Testdaten als Objekt zurück (für einzelne Ergebnisse)
376
+ - Dictionaries werden in SimpleNamespace-Objekte konvertiert
377
+ - Zugriff über Attribute: `result.total_sp`
378
+ - **`results()`**:
379
+ - Wenn Testdaten bereits eine Liste sind, wird sie als Liste von Objekten zurückgegeben
380
+ - Wenn Testdaten ein einzelnes Objekt sind, wird es in eine Liste gewrappt
381
+ - Zugriff: `results[0].skill_id`
382
+
383
+ ## Parameter
384
+
385
+ Beide Methoden akzeptieren die gleichen Parameter wie die echten ESI-Operationen:
386
+
387
+ ```python
388
+ operation.result(
389
+ use_etag=True, return_response=False, force_refresh=False, use_cache=True
390
+ )
391
+
392
+ operation.results(
393
+ use_etag=True, return_response=False, force_refresh=False, use_cache=True
394
+ )
395
+ ```
396
+
397
+ Diese Parameter werden im Stub ignoriert, aber akzeptiert, um die echte API-Signatur zu matchen.
398
+
399
+ ## Beispiele
400
+
401
+ Siehe `test_esi_stub.py` für vollständige Beispiele der Verwendung, einschließlich:
402
+
403
+ - Grundlegende `result()` und `results()` Aufrufe
404
+ - Verwendung mit `return_response=True`
405
+ - Simulation von Exceptions (HTTPNotModified, HTTPClientError, etc.)
406
+ - Sequentielle Side-Effects
407
+ - Dynamische Testdaten
408
+ - Integration mit Mock/Patch
409
+
410
+ ## Datenkonvertierung
411
+
412
+ Alle Testdaten (JSON/Dict) werden automatisch in Objekte mit Attributen konvertiert:
413
+
414
+ ```python
415
+ # Testdaten als Dict
416
+ test_data = {
417
+ "Skills": {
418
+ "GetCharactersCharacterIdSkills": {
419
+ "total_sp": 50000000,
420
+ "skills": [{"skill_id": 123}],
421
+ }
422
+ }
423
+ }
424
+
425
+ # Wird zu Objekten konvertiert
426
+ result = operation.result()
427
+ result.total_sp # 50000000 (Attributzugriff!)
428
+ result.skills[0].skill_id # 123 (Attributzugriff!)
429
+ ```
430
+ ````