aa-intel-tool 2.11.2__py3-none-any.whl → 2.12.1__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 (56) hide show
  1. aa_intel_tool/__init__.py +1 -1
  2. aa_intel_tool/admin.py +1 -3
  3. aa_intel_tool/app_settings.py +109 -11
  4. aa_intel_tool/helper/eve_character.py +2 -4
  5. aa_intel_tool/helper/urls.py +20 -0
  6. aa_intel_tool/locale/cs_CZ/LC_MESSAGES/django.po +9 -9
  7. aa_intel_tool/locale/de/LC_MESSAGES/django.po +9 -9
  8. aa_intel_tool/locale/django.pot +10 -10
  9. aa_intel_tool/locale/es/LC_MESSAGES/django.po +9 -9
  10. aa_intel_tool/locale/fr_FR/LC_MESSAGES/django.po +9 -9
  11. aa_intel_tool/locale/it_IT/LC_MESSAGES/django.po +9 -9
  12. aa_intel_tool/locale/ja/LC_MESSAGES/django.mo +0 -0
  13. aa_intel_tool/locale/ja/LC_MESSAGES/django.po +47 -47
  14. aa_intel_tool/locale/ko_KR/LC_MESSAGES/django.po +9 -9
  15. aa_intel_tool/locale/nl_NL/LC_MESSAGES/django.po +9 -9
  16. aa_intel_tool/locale/pl_PL/LC_MESSAGES/django.po +9 -9
  17. aa_intel_tool/locale/ru/LC_MESSAGES/django.po +9 -9
  18. aa_intel_tool/locale/sk/LC_MESSAGES/django.po +9 -9
  19. aa_intel_tool/locale/uk/LC_MESSAGES/django.po +9 -9
  20. aa_intel_tool/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
  21. aa_intel_tool/locale/zh_Hans/LC_MESSAGES/django.po +20 -20
  22. aa_intel_tool/management/commands/aa_intel_tool_load_eve_types.py +2 -2
  23. aa_intel_tool/parser/general.py +2 -4
  24. aa_intel_tool/parser/module/chatlist.py +2 -2
  25. aa_intel_tool/parser/module/dscan.py +2 -2
  26. aa_intel_tool/parser/module/fleetcomp.py +2 -2
  27. aa_intel_tool/providers.py +43 -0
  28. aa_intel_tool/static/aa_intel_tool/javascript/aa-intel-tool-chatscan.js +1 -1
  29. aa_intel_tool/static/aa_intel_tool/javascript/aa-intel-tool-chatscan.min.js +1 -1
  30. aa_intel_tool/static/aa_intel_tool/javascript/aa-intel-tool-chatscan.min.js.map +1 -1
  31. aa_intel_tool/static/aa_intel_tool/javascript/aa-intel-tool-dscan.js +1 -1
  32. aa_intel_tool/static/aa_intel_tool/javascript/aa-intel-tool-dscan.min.js +1 -1
  33. aa_intel_tool/static/aa_intel_tool/javascript/aa-intel-tool-dscan.min.js.map +1 -1
  34. aa_intel_tool/static/aa_intel_tool/javascript/aa-intel-tool-fleetcomposition.js +1 -1
  35. aa_intel_tool/static/aa_intel_tool/javascript/aa-intel-tool-fleetcomposition.min.js +1 -1
  36. aa_intel_tool/static/aa_intel_tool/javascript/aa-intel-tool-fleetcomposition.min.js.map +1 -1
  37. aa_intel_tool/tasks.py +2 -4
  38. aa_intel_tool/templates/aa_intel_tool/base.html +6 -1
  39. aa_intel_tool/templates/aa_intel_tool/partials/scan/chatlist/alliances.html +1 -1
  40. aa_intel_tool/templates/aa_intel_tool/partials/scan/chatlist/corporations.html +1 -1
  41. aa_intel_tool/templates/aa_intel_tool/partials/scan/chatlist/pilots.html +1 -1
  42. aa_intel_tool/templates/aa_intel_tool/partials/scan/dscan/interesting-on-grid/items.html +1 -1
  43. aa_intel_tool/templates/aa_intel_tool/partials/scan/dscan/ships-breakdown/ship-classes.html +1 -1
  44. aa_intel_tool/templates/aa_intel_tool/partials/scan/dscan/ships-breakdown/ship-types.html +1 -1
  45. aa_intel_tool/templates/aa_intel_tool/partials/scan/fleetcomp/fleet-details/pilots.html +1 -1
  46. aa_intel_tool/tests/test_access.py +1 -4
  47. aa_intel_tool/tests/test_app_settings.py +198 -1
  48. aa_intel_tool/tests/test_auth_hooks.py +1 -4
  49. aa_intel_tool/tests/test_helper_urls.py +70 -0
  50. aa_intel_tool/tests/test_providers.py +98 -0
  51. aa_intel_tool/tests/utils.py +68 -0
  52. aa_intel_tool/views/general.py +2 -4
  53. {aa_intel_tool-2.11.2.dist-info → aa_intel_tool-2.12.1.dist-info}/METADATA +1 -2
  54. {aa_intel_tool-2.11.2.dist-info → aa_intel_tool-2.12.1.dist-info}/RECORD +56 -52
  55. {aa_intel_tool-2.11.2.dist-info → aa_intel_tool-2.12.1.dist-info}/WHEEL +1 -1
  56. {aa_intel_tool-2.11.2.dist-info → aa_intel_tool-2.12.1.dist-info}/licenses/LICENSE +0 -0
@@ -10,12 +10,209 @@ from django.conf import settings
10
10
  from django.test import override_settings
11
11
 
12
12
  # AA Intel Tool
13
- from aa_intel_tool.app_settings import AppSettings, debug_enabled
13
+ from aa_intel_tool.app_settings import AppSettings, _clean_setting, debug_enabled
14
14
  from aa_intel_tool.tests import BaseTestCase
15
15
 
16
16
  SETTINGS_PATH = "aa_intel_tool.app_settings"
17
17
 
18
18
 
19
+ class TestHelperCleanSetting(BaseTestCase):
20
+ """
21
+ Tests for the _clean_setting helper function
22
+ """
23
+
24
+ def test_returns_default_value_when_setting_is_absent(self):
25
+ """
26
+ Test returns default value when setting is absent
27
+
28
+ :return:
29
+ :rtype:
30
+ """
31
+
32
+ if hasattr(settings, "TEST_SETTING"):
33
+ delattr(settings, "TEST_SETTING")
34
+
35
+ result = _clean_setting("TEST_SETTING", default_value=123, required_type=int)
36
+
37
+ self.assertEqual(result, 123)
38
+
39
+ def test_returns_setting_value_when_valid_and_defined(self):
40
+ """
41
+ Test returns setting value when valid and defined
42
+
43
+ :return:
44
+ :rtype:
45
+ """
46
+
47
+ with self.settings(TEST_SETTING=456):
48
+ result = _clean_setting(
49
+ "TEST_SETTING", default_value=123, required_type=int
50
+ )
51
+
52
+ self.assertEqual(result, 456)
53
+
54
+ def test_raises_value_error_when_default_is_below_minimum(self):
55
+ """
56
+ Test raises ValueError when default is below minimum
57
+
58
+ :return:
59
+ :rtype:
60
+ """
61
+
62
+ with self.assertRaises(ValueError):
63
+ _clean_setting(
64
+ "TEST_SETTING", default_value=5, min_value=10, required_type=int
65
+ )
66
+
67
+ def test_raises_value_error_when_default_exceeds_maximum(self):
68
+ """
69
+ Test raises ValueError when default exceeds maximum
70
+
71
+ :return:
72
+ :rtype:
73
+ """
74
+
75
+ with self.assertRaises(ValueError):
76
+ _clean_setting(
77
+ "TEST_SETTING", default_value=15, max_value=10, required_type=int
78
+ )
79
+
80
+ def test_uses_minimum_value_when_setting_is_below_minimum(self):
81
+ """
82
+ Test uses minimum value when setting is below minimum
83
+
84
+ :return:
85
+ :rtype:
86
+ """
87
+
88
+ with self.settings(TEST_SETTING=5):
89
+ result = _clean_setting(
90
+ "TEST_SETTING", default_value=123, min_value=10, required_type=int
91
+ )
92
+
93
+ self.assertEqual(result, 10)
94
+
95
+ def test_uses_maximum_value_when_setting_exceeds_maximum(self):
96
+ """
97
+ Test uses maximum value when setting exceeds maximum
98
+
99
+ :return:
100
+ :rtype:
101
+ """
102
+
103
+ with self.settings(TEST_SETTING=15):
104
+ result = _clean_setting(
105
+ "TEST_SETTING", default_value=3, max_value=10, required_type=int
106
+ )
107
+
108
+ self.assertEqual(result, 10)
109
+
110
+ def test_raises_type_error_when_required_type_is_invalid(self):
111
+ """
112
+ Test raises TypeError when required_type is invalid
113
+
114
+ :return:
115
+ :rtype:
116
+ """
117
+
118
+ with self.assertRaises(TypeError):
119
+ _clean_setting(
120
+ "TEST_SETTING", default_value=123, required_type="not_a_type"
121
+ )
122
+
123
+ def test_raises_value_error_when_required_type_is_missing_for_none_default(self):
124
+ """
125
+ Test raises ValueError when required_type is missing for None default
126
+
127
+ :return:
128
+ :rtype:
129
+ """
130
+
131
+ with self.assertRaises(ValueError):
132
+ _clean_setting("TEST_SETTING", default_value=None)
133
+
134
+ def test_uses_default_value_when_setting_is_not_in_choices(self):
135
+ """
136
+ Test uses default value when setting is not in choices
137
+
138
+ :return:
139
+ :rtype:
140
+ """
141
+
142
+ with self.settings(TEST_SETTING=999):
143
+ result = _clean_setting(
144
+ "TEST_SETTING", default_value=123, required_type=int, choices=[1, 2, 3]
145
+ )
146
+
147
+ self.assertEqual(result, 123)
148
+
149
+ def test_uses_setting_value_when_in_choices(self):
150
+ """
151
+ Test uses setting value when in choices
152
+
153
+ :return:
154
+ :rtype:
155
+ """
156
+
157
+ with self.settings(TEST_SETTING=2):
158
+ result = _clean_setting(
159
+ "TEST_SETTING", default_value=123, required_type=int, choices=[1, 2, 3]
160
+ )
161
+
162
+ self.assertEqual(result, 2)
163
+
164
+ def test_uses_type_of_default_value_when_required_type_is_not_provided(self):
165
+ """
166
+ Test uses type of default value when required_type is not provided
167
+
168
+ :return:
169
+ :rtype:
170
+ """
171
+
172
+ result = _clean_setting("TEST_SETTING", default_value=123)
173
+
174
+ self.assertEqual(result, 123)
175
+
176
+ def test_raises_type_error_when_default_value_is_none_and_required_type_is_not_provided(
177
+ self,
178
+ ):
179
+ """
180
+ Test raises TypeError when default_value is None and required_type is not provided
181
+
182
+ :return:
183
+ :rtype:
184
+ """
185
+
186
+ with self.assertRaises(ValueError):
187
+ _clean_setting("TEST_SETTING", default_value=None)
188
+
189
+ def test_does_not_raise_error_when_required_type_is_subclass_of_int(self):
190
+ """
191
+ Test does not raise error when required_type is subclass of int
192
+
193
+ :return:
194
+ :rtype:
195
+ """
196
+
197
+ result = _clean_setting("TEST_SETTING", default_value=123, required_type=int)
198
+
199
+ self.assertEqual(result, 123)
200
+
201
+ def test_skips_check_when_default_value_is_none_and_required_type_is_subclass_of_int(
202
+ self,
203
+ ):
204
+ """
205
+ Test skips check when default_value is None and required_type is subclass of int
206
+
207
+ :return:
208
+ :rtype:
209
+ """
210
+
211
+ result = _clean_setting("TEST_SETTING", default_value=None, required_type=int)
212
+
213
+ self.assertIsNone(result)
214
+
215
+
19
216
  class TestAppSettings(BaseTestCase):
20
217
  """
21
218
  Tests for App Settings
@@ -8,12 +8,9 @@ from http import HTTPStatus
8
8
  # Django
9
9
  from django.urls import reverse
10
10
 
11
- # Alliance Auth (External Libs)
12
- from app_utils.testing import create_fake_user
13
-
14
11
  # AA Intel Tool
15
12
  from aa_intel_tool.tests import BaseTestCase
16
- from aa_intel_tool.tests.utils import response_content_to_str
13
+ from aa_intel_tool.tests.utils import create_fake_user, response_content_to_str
17
14
 
18
15
 
19
16
  class TestHooks(BaseTestCase):
@@ -0,0 +1,70 @@
1
+ """
2
+ Unit tests for the helper.urls helper.
3
+ """
4
+
5
+ # Standard Library
6
+ from unittest.mock import patch
7
+
8
+ # AA Intel Tool
9
+ from aa_intel_tool.helper.urls import reverse_absolute
10
+ from aa_intel_tool.tests import BaseTestCase
11
+
12
+
13
+ class TestReverseAbsolute(BaseTestCase):
14
+ """
15
+ Test reverse_absolute helper
16
+ """
17
+
18
+ @patch("aa_intel_tool.helper.urls.reverse")
19
+ def test_returns_absolute_url_for_valid_viewname(self, mock_reverse):
20
+ """
21
+ Test returns absolute URL for valid viewname
22
+
23
+ :param mock_reverse:
24
+ :type mock_reverse:
25
+ :return:
26
+ :rtype:
27
+ """
28
+
29
+ mock_reverse.return_value = "/mocked-path/"
30
+
31
+ with self.settings(SITE_URL="https://example.com"):
32
+ result = reverse_absolute("mock_view")
33
+
34
+ self.assertEqual(result, "https://example.com/mocked-path/")
35
+
36
+ @patch("aa_intel_tool.helper.urls.reverse")
37
+ def test_handles_none_args_correctly(self, mock_reverse):
38
+ """
39
+ Test handles None args correctly
40
+
41
+ :param mock_reverse:
42
+ :type mock_reverse:
43
+ :return:
44
+ :rtype:
45
+ """
46
+
47
+ mock_reverse.return_value = "/mocked-path/"
48
+
49
+ with self.settings(SITE_URL="https://example.com"):
50
+ result = reverse_absolute("mock_view", args=None)
51
+
52
+ self.assertEqual(result, "https://example.com/mocked-path/")
53
+
54
+ @patch("aa_intel_tool.helper.urls.reverse")
55
+ def test_includes_args_in_generated_url(self, mock_reverse):
56
+ """
57
+ Test includes args in generated URL
58
+
59
+ :param mock_reverse:
60
+ :type mock_reverse:
61
+ :return:
62
+ :rtype:
63
+ """
64
+
65
+ mock_reverse.return_value = "/mocked-path/123/"
66
+
67
+ with self.settings(SITE_URL="https://example.com"):
68
+ result = reverse_absolute("mock_view", args=[123])
69
+
70
+ self.assertEqual(result, "https://example.com/mocked-path/123/")
@@ -0,0 +1,98 @@
1
+ """
2
+ Test for the providers module.
3
+ """
4
+
5
+ # Standard Library
6
+ import logging
7
+
8
+ # AA Intel Tool
9
+ from aa_intel_tool.providers import AppLogger
10
+ from aa_intel_tool.tests import BaseTestCase
11
+
12
+
13
+ class TestAppLogger(BaseTestCase):
14
+ """
15
+ Test the AppLogger provider.
16
+ """
17
+
18
+ def test_adds_prefix_to_log_message(self):
19
+ """
20
+ Tests that the AppLogger correctly adds a prefix to log messages.
21
+
22
+ :return:
23
+ :rtype:
24
+ """
25
+
26
+ logger = logging.getLogger("test_logger")
27
+ app_logger = AppLogger(logger, "PREFIX")
28
+
29
+ with self.assertLogs("test_logger", level="INFO") as log:
30
+ app_logger.info("This is a test message")
31
+
32
+ self.assertIn("[PREFIX] This is a test message", log.output[0])
33
+
34
+ def test_handles_empty_prefix(self):
35
+ """
36
+ Tests that the AppLogger handles an empty prefix correctly.
37
+
38
+ :return:
39
+ :rtype:
40
+ """
41
+
42
+ logger = logging.getLogger("test_logger")
43
+ app_logger = AppLogger(logger, "")
44
+
45
+ with self.assertLogs("test_logger", level="INFO") as log:
46
+ app_logger.info("Message without prefix")
47
+
48
+ self.assertIn("Message without prefix", log.output[0])
49
+
50
+ def test_handles_non_string_prefix(self):
51
+ """
52
+ Tests that the AppLogger handles a non-string prefix correctly.
53
+
54
+ :return:
55
+ :rtype:
56
+ """
57
+
58
+ logger = logging.getLogger("test_logger")
59
+ app_logger = AppLogger(logger, 123)
60
+
61
+ with self.assertLogs("test_logger", level="INFO") as log:
62
+ app_logger.info("Message with numeric prefix")
63
+
64
+ self.assertIn("[123] Message with numeric prefix", log.output[0])
65
+
66
+ def test_handles_special_characters_in_prefix(self):
67
+ """
68
+ Tests that the AppLogger handles special characters in the prefix correctly.
69
+
70
+ :return:
71
+ :rtype:
72
+ """
73
+
74
+ logger = logging.getLogger("test_logger")
75
+ app_logger = AppLogger(logger, "!@#$%^&*()")
76
+
77
+ with self.assertLogs("test_logger", level="INFO") as log:
78
+ app_logger.info("Message with special characters in prefix")
79
+
80
+ self.assertIn(
81
+ "[!@#$%^&*()] Message with special characters in prefix", log.output[0]
82
+ )
83
+
84
+ def test_handles_empty_message(self):
85
+ """
86
+ Tests that the AppLogger handles an empty log message correctly.
87
+
88
+ :return:
89
+ :rtype:
90
+ """
91
+
92
+ logger = logging.getLogger("test_logger")
93
+ app_logger = AppLogger(logger, "PREFIX")
94
+
95
+ with self.assertLogs("test_logger", level="INFO") as log:
96
+ app_logger.info("")
97
+
98
+ self.assertIn("[PREFIX] ", log.output[0])
@@ -3,12 +3,17 @@ Helper for our tests
3
3
  """
4
4
 
5
5
  # Standard Library
6
+ import re
6
7
  from pathlib import Path
7
8
 
8
9
  # Django
10
+ from django.contrib.auth.models import User
9
11
  from django.core.handlers.wsgi import WSGIRequest
10
12
  from django.template import Context, Template
11
13
 
14
+ # Alliance Auth
15
+ from allianceauth.tests.auth_utils import AuthUtils
16
+
12
17
 
13
18
  def render_template(string, context=None):
14
19
  """
@@ -79,3 +84,66 @@ def response_content_to_str(response: WSGIRequest) -> str:
79
84
  """
80
85
 
81
86
  return response.content.decode(response.charset)
87
+
88
+
89
+ def create_fake_user(
90
+ character_id: int,
91
+ character_name: str,
92
+ corporation_id: int = None,
93
+ corporation_name: str = None,
94
+ corporation_ticker: str = None,
95
+ permissions: list[str] = None,
96
+ **kwargs,
97
+ ) -> User:
98
+ """
99
+ Create a fake user with a given character name and id.
100
+
101
+ :param character_id:
102
+ :type character_id:
103
+ :param character_name:
104
+ :type character_name:
105
+ :param corporation_id:
106
+ :type corporation_id:
107
+ :param corporation_name:
108
+ :type corporation_name:
109
+ :param corporation_ticker:
110
+ :type corporation_ticker:
111
+ :param permissions:
112
+ :type permissions:
113
+ :param kwargs:
114
+ :type kwargs:
115
+ :return:
116
+ :rtype:
117
+ """
118
+
119
+ username = re.sub(pattern=r"[^\w\d@\.\+-]", repl="_", string=character_name)
120
+ user = AuthUtils.create_user(username=username)
121
+
122
+ if not corporation_id:
123
+ corporation_id = 2001
124
+ corporation_name = "Wayne Technologies Inc."
125
+ corporation_ticker = "WTE"
126
+
127
+ alliance_id = kwargs.get("alliance_id", 3001)
128
+ alliance_name = (
129
+ kwargs.get("alliance_name", "Wayne Enterprises")
130
+ if alliance_id is not None
131
+ else ""
132
+ )
133
+
134
+ AuthUtils.add_main_character_2(
135
+ user=user,
136
+ name=character_name,
137
+ character_id=character_id,
138
+ corp_id=corporation_id,
139
+ corp_name=corporation_name,
140
+ corp_ticker=corporation_ticker,
141
+ alliance_id=alliance_id,
142
+ alliance_name=alliance_name,
143
+ )
144
+
145
+ if permissions:
146
+ perm_objs = [AuthUtils.get_permission_by_name(perm) for perm in permissions]
147
+ user = AuthUtils.add_permissions_to_user(perms=perm_objs, user=user)
148
+
149
+ return user
@@ -12,9 +12,6 @@ from django.utils.translation import gettext_lazy as _
12
12
  # Alliance Auth
13
13
  from allianceauth.services.hooks import get_extension_logger
14
14
 
15
- # Alliance Auth (External Libs)
16
- from app_utils.logging import LoggerAddTag
17
-
18
15
  # AA Intel Tool
19
16
  from aa_intel_tool import __title__
20
17
  from aa_intel_tool.app_settings import AppSettings
@@ -23,8 +20,9 @@ from aa_intel_tool.exceptions import ParserError
23
20
  from aa_intel_tool.form import IntelForm
24
21
  from aa_intel_tool.models import Scan, ScanData
25
22
  from aa_intel_tool.parser.general import parse_intel
23
+ from aa_intel_tool.providers import AppLogger
26
24
 
27
- logger = LoggerAddTag(my_logger=get_extension_logger(name=__name__), prefix=__title__)
25
+ logger = AppLogger(my_logger=get_extension_logger(name=__name__), prefix=__title__)
28
26
 
29
27
 
30
28
  def index(request: WSGIRequest) -> HttpResponse:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aa-intel-tool
3
- Version: 2.11.2
3
+ Version: 2.12.1
4
4
  Summary: A simple parser for D-Scans and more for Alliance Auth
5
5
  Project-URL: Changelog, https://github.com/ppfeufer/aa-intel-tool/blob/master/CHANGELOG.md
6
6
  Project-URL: Codecov, https://codecov.io/gh/ppfeufer/aa-intel-tool
@@ -702,7 +702,6 @@ Classifier: Programming Language :: Python :: 3.13
702
702
  Classifier: Topic :: Internet :: WWW/HTTP
703
703
  Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
704
704
  Requires-Python: <3.14,>=3.10
705
- Requires-Dist: allianceauth-app-utils>=1.19.1
706
705
  Requires-Dist: allianceauth<5,>=4.10
707
706
  Requires-Dist: django-eveuniverse>=1.3
708
707
  Provides-Extra: tests-allianceauth-latest