taranis-models 1.3.2.dev2__tar.gz → 1.3.2.dev3__tar.gz

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 (35) hide show
  1. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/PKG-INFO +2 -1
  2. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/models/assess.py +53 -8
  3. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/models/dashboard.py +2 -28
  4. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/pyproject.toml +1 -0
  5. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/taranis_models.egg-info/PKG-INFO +2 -1
  6. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/taranis_models.egg-info/requires.txt +1 -0
  7. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/uv.lock +31 -20
  8. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/.dockerignore +0 -0
  9. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/.gitignore +0 -0
  10. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/.python-version +0 -0
  11. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/LICENSE.md +0 -0
  12. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/README.md +0 -0
  13. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/models/__init__.py +0 -0
  14. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/models/admin.py +0 -0
  15. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/models/asset.py +0 -0
  16. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/models/base.py +0 -0
  17. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/models/product.py +0 -0
  18. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/models/py.typed +0 -0
  19. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/models/report.py +0 -0
  20. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/models/types.py +0 -0
  21. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/models/user.py +0 -0
  22. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/setup.cfg +0 -0
  23. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/taranis_models.egg-info/SOURCES.txt +0 -0
  24. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/taranis_models.egg-info/dependency_links.txt +0 -0
  25. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/taranis_models.egg-info/top_level.txt +0 -0
  26. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/typings/models/__init__.pyi +0 -0
  27. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/typings/models/admin.pyi +0 -0
  28. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/typings/models/assess.pyi +0 -0
  29. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/typings/models/asset.pyi +0 -0
  30. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/typings/models/base.pyi +0 -0
  31. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/typings/models/dashboard.pyi +0 -0
  32. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/typings/models/product.pyi +0 -0
  33. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/typings/models/report.pyi +0 -0
  34. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/typings/models/types.pyi +0 -0
  35. {taranis_models-1.3.2.dev2 → taranis_models-1.3.2.dev3}/typings/models/user.pyi +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: taranis-models
3
- Version: 1.3.2.dev2
3
+ Version: 1.3.2.dev3
4
4
  Summary: Taranis AI Models
5
5
  Maintainer-email: AIT <benjamin.akhras@ait.ac.at>
6
6
  License-Expression: EUPL-1.2
@@ -17,6 +17,7 @@ License-File: LICENSE.md
17
17
  Requires-Dist: pydantic
18
18
  Requires-Dist: pydantic-settings
19
19
  Requires-Dist: python-dotenv
20
+ Requires-Dist: langcodes
20
21
  Provides-Extra: dev
21
22
  Requires-Dist: ruff; extra == "dev"
22
23
  Requires-Dist: pytest; extra == "dev"
@@ -1,7 +1,10 @@
1
1
  from datetime import datetime
2
2
  from functools import cached_property
3
- from typing import Literal
3
+ from typing import Any, Literal
4
4
 
5
+ from langcodes import Language
6
+ from langcodes.tag_parser import LanguageTagError
7
+ from pydantic import ValidationInfo, field_validator, model_validator
5
8
 
6
9
  from models.base import TaranisBaseModel
7
10
 
@@ -10,18 +13,21 @@ class NewsItem(TaranisBaseModel):
10
13
  _core_endpoint = "/assess/news-items"
11
14
 
12
15
  osint_source_id: str
16
+ id: str | None = None
13
17
  hash: str | None = None
14
18
  title: str | None = None
15
19
  author: str | None = None
16
20
  review: str | None = None
17
21
  content: str | None = None
18
- web_url: str | None = None
22
+ link: str | None = None
19
23
  source: str | None = None
20
24
  published: datetime | None = None
21
25
  collected: datetime | None = None
22
- attributes: list[str | dict] | None = None
26
+ updated: datetime | None = None
27
+ attributes: list[str | dict[str, Any]] | None = None
23
28
  story_id: str | None = None
24
29
  language: str | None = None
30
+ last_change: str | None = None
25
31
 
26
32
 
27
33
  class StoryTag(TaranisBaseModel):
@@ -53,8 +59,8 @@ class Story(TaranisBaseModel):
53
59
  relevance: int | None = None
54
60
  comments: str | None = None
55
61
  in_reports_count: int | None = None
56
- tags: list[dict] | None = None
57
- attributes: list[dict] | None = None
62
+ tags: list[dict[str, Any]] | None = None
63
+ attributes: list[dict[str, Any]] | None = None
58
64
 
59
65
  @cached_property
60
66
  def search_field(self) -> str:
@@ -81,7 +87,7 @@ class FilterLists(TaranisBaseModel):
81
87
 
82
88
  tags: list[str] = []
83
89
  sources: list[AssessSource] = []
84
- groups: list[dict] = []
90
+ groups: list[dict[str, Any]] = []
85
91
 
86
92
 
87
93
  class StoryUpdatePayload(TaranisBaseModel):
@@ -92,10 +98,49 @@ class StoryUpdatePayload(TaranisBaseModel):
92
98
  description: str | None = None
93
99
  comments: str | None = None
94
100
  summary: str | None = None
95
- tags: list[dict] | None = None
96
- attributes: list[dict] | None = None
101
+ tags: list[dict[str, Any]] | None = None
102
+ attributes: list[dict[str, Any]] | None = None
97
103
 
98
104
 
99
105
  class BulkAction(TaranisBaseModel):
100
106
  story_ids: list[str] = []
101
107
  payload: StoryUpdatePayload | None = None
108
+
109
+
110
+ class NewsItemCreate(TaranisBaseModel):
111
+ osint_source_id: str
112
+ title: str | None = None
113
+ author: str | None = None
114
+ review: str | None = None
115
+ content: str | None = None
116
+ link: str | None = None
117
+ source: str | None = None
118
+ published: datetime | None = None
119
+ collected: datetime | None = None
120
+ attributes: list[str | dict[str, Any]] | None = None
121
+ language: str | None = None
122
+
123
+ @field_validator("language", mode="before")
124
+ def normalize_language_code(self, v: str, info: ValidationInfo) -> str:
125
+ if v:
126
+ try:
127
+ return Language.get(v).language or ""
128
+ except (LanguageTagError, ValueError, TypeError):
129
+ return ""
130
+ return ""
131
+
132
+ @model_validator(mode="after")
133
+ def check_required_fields(self) -> "NewsItemCreate":
134
+ if not self.title and not self.content:
135
+ raise ValueError("Either title or content must be provided for NewsItemCreate.")
136
+ return self
137
+
138
+
139
+ class StoryCreate(TaranisBaseModel):
140
+ title: str | None = None
141
+ summary: str | None = None
142
+ description: str | None = None
143
+ news_items: list[NewsItemCreate] = []
144
+ tags: list[dict[str, Any]] | None = None
145
+ attributes: list[dict[str, Any]] | None = None
146
+ created: datetime | None = None
@@ -1,9 +1,8 @@
1
- from datetime import datetime
2
-
3
1
  from pydantic import Field
2
+ from datetime import datetime
4
3
 
5
- from models.assess import StoryTag
6
4
  from models.base import TaranisBaseModel
5
+ from models.assess import StoryTag
7
6
 
8
7
 
9
8
  class Dashboard(TaranisBaseModel):
@@ -39,28 +38,3 @@ class Cluster(TaranisBaseModel):
39
38
 
40
39
  name: str
41
40
  size: int | None = None
42
-
43
-
44
- class StoryConflict(TaranisBaseModel):
45
- _core_endpoint = "connectors/conflicts/story-conflicts"
46
- _cache_timeout = 5
47
- _model_name = "story_conflicts"
48
- _pretty_name = "Story Conflicts"
49
-
50
- story_id: str
51
- existing_story: str
52
- incoming_story: str
53
- has_proposals: str | None = None
54
-
55
-
56
- class NewsItemConflict(TaranisBaseModel):
57
- _core_endpoint = "/connectors/conflicts/news-items"
58
- _cache_timeout = 5
59
- _model_name = "news_item_conflict"
60
- _pretty_name = "News Item Conflicts"
61
-
62
- incoming_story_id: str
63
- news_item_id: str
64
- existing_story_id: str
65
- incoming_story: dict
66
- misp_address: str | None = None
@@ -18,6 +18,7 @@ dependencies = [
18
18
  "pydantic",
19
19
  "pydantic-settings",
20
20
  "python-dotenv",
21
+ "langcodes",
21
22
  ]
22
23
  dynamic = ["version"]
23
24
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: taranis-models
3
- Version: 1.3.2.dev2
3
+ Version: 1.3.2.dev3
4
4
  Summary: Taranis AI Models
5
5
  Maintainer-email: AIT <benjamin.akhras@ait.ac.at>
6
6
  License-Expression: EUPL-1.2
@@ -17,6 +17,7 @@ License-File: LICENSE.md
17
17
  Requires-Dist: pydantic
18
18
  Requires-Dist: pydantic-settings
19
19
  Requires-Dist: python-dotenv
20
+ Requires-Dist: langcodes
20
21
  Provides-Extra: dev
21
22
  Requires-Dist: ruff; extra == "dev"
22
23
  Requires-Dist: pytest; extra == "dev"
@@ -1,6 +1,7 @@
1
1
  pydantic
2
2
  pydantic-settings
3
3
  python-dotenv
4
+ langcodes
4
5
 
5
6
  [dev]
6
7
  ruff
@@ -35,6 +35,15 @@ wheels = [
35
35
  { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
36
36
  ]
37
37
 
38
+ [[package]]
39
+ name = "langcodes"
40
+ version = "3.5.1"
41
+ source = { registry = "https://pypi.org/simple" }
42
+ sdist = { url = "https://files.pythonhosted.org/packages/a9/75/f9edc5d72945019312f359e69ded9f82392a81d49c5051ed3209b100c0d2/langcodes-3.5.1.tar.gz", hash = "sha256:40bff315e01b01d11c2ae3928dd4f5cbd74dd38f9bd912c12b9a3606c143f731", size = 191084, upload-time = "2025-12-02T16:22:01.627Z" }
43
+ wheels = [
44
+ { url = "https://files.pythonhosted.org/packages/dd/c1/d10b371bcba7abce05e2b33910e39c33cfa496a53f13640b7b8e10bb4d2b/langcodes-3.5.1-py3-none-any.whl", hash = "sha256:b6a9c25c603804e2d169165091d0cdb23934610524a21d226e4f463e8e958a72", size = 183050, upload-time = "2025-12-02T16:21:59.954Z" },
45
+ ]
46
+
38
47
  [[package]]
39
48
  name = "nodeenv"
40
49
  version = "1.9.1"
@@ -183,34 +192,35 @@ wheels = [
183
192
 
184
193
  [[package]]
185
194
  name = "ruff"
186
- version = "0.14.8"
195
+ version = "0.14.9"
187
196
  source = { registry = "https://pypi.org/simple" }
188
- sdist = { url = "https://files.pythonhosted.org/packages/ed/d9/f7a0c4b3a2bf2556cd5d99b05372c29980249ef71e8e32669ba77428c82c/ruff-0.14.8.tar.gz", hash = "sha256:774ed0dd87d6ce925e3b8496feb3a00ac564bea52b9feb551ecd17e0a23d1eed", size = 5765385, upload-time = "2025-12-04T15:06:17.669Z" }
197
+ sdist = { url = "https://files.pythonhosted.org/packages/f6/1b/ab712a9d5044435be8e9a2beb17cbfa4c241aa9b5e4413febac2a8b79ef2/ruff-0.14.9.tar.gz", hash = "sha256:35f85b25dd586381c0cc053f48826109384c81c00ad7ef1bd977bfcc28119d5b", size = 5809165, upload-time = "2025-12-11T21:39:47.381Z" }
189
198
  wheels = [
190
- { url = "https://files.pythonhosted.org/packages/48/b8/9537b52010134b1d2b72870cc3f92d5fb759394094741b09ceccae183fbe/ruff-0.14.8-py3-none-linux_armv6l.whl", hash = "sha256:ec071e9c82eca417f6111fd39f7043acb53cd3fde9b1f95bbed745962e345afb", size = 13441540, upload-time = "2025-12-04T15:06:14.896Z" },
191
- { url = "https://files.pythonhosted.org/packages/24/00/99031684efb025829713682012b6dd37279b1f695ed1b01725f85fd94b38/ruff-0.14.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:8cdb162a7159f4ca36ce980a18c43d8f036966e7f73f866ac8f493b75e0c27e9", size = 13669384, upload-time = "2025-12-04T15:06:51.809Z" },
192
- { url = "https://files.pythonhosted.org/packages/72/64/3eb5949169fc19c50c04f28ece2c189d3b6edd57e5b533649dae6ca484fe/ruff-0.14.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2e2fcbefe91f9fad0916850edf0854530c15bd1926b6b779de47e9ab619ea38f", size = 12806917, upload-time = "2025-12-04T15:06:08.925Z" },
193
- { url = "https://files.pythonhosted.org/packages/c4/08/5250babb0b1b11910f470370ec0cbc67470231f7cdc033cee57d4976f941/ruff-0.14.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9d70721066a296f45786ec31916dc287b44040f553da21564de0ab4d45a869b", size = 13256112, upload-time = "2025-12-04T15:06:23.498Z" },
194
- { url = "https://files.pythonhosted.org/packages/78/4c/6c588e97a8e8c2d4b522c31a579e1df2b4d003eddfbe23d1f262b1a431ff/ruff-0.14.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c87e09b3cd9d126fc67a9ecd3b5b1d3ded2b9c7fce3f16e315346b9d05cfb52", size = 13227559, upload-time = "2025-12-04T15:06:33.432Z" },
195
- { url = "https://files.pythonhosted.org/packages/23/ce/5f78cea13eda8eceac71b5f6fa6e9223df9b87bb2c1891c166d1f0dce9f1/ruff-0.14.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d62cb310c4fbcb9ee4ac023fe17f984ae1e12b8a4a02e3d21489f9a2a5f730c", size = 13896379, upload-time = "2025-12-04T15:06:02.687Z" },
196
- { url = "https://files.pythonhosted.org/packages/cf/79/13de4517c4dadce9218a20035b21212a4c180e009507731f0d3b3f5df85a/ruff-0.14.8-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:1af35c2d62633d4da0521178e8a2641c636d2a7153da0bac1b30cfd4ccd91344", size = 15372786, upload-time = "2025-12-04T15:06:29.828Z" },
197
- { url = "https://files.pythonhosted.org/packages/00/06/33df72b3bb42be8a1c3815fd4fae83fa2945fc725a25d87ba3e42d1cc108/ruff-0.14.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:25add4575ffecc53d60eed3f24b1e934493631b48ebbc6ebaf9d8517924aca4b", size = 14990029, upload-time = "2025-12-04T15:06:36.812Z" },
198
- { url = "https://files.pythonhosted.org/packages/64/61/0f34927bd90925880394de0e081ce1afab66d7b3525336f5771dcf0cb46c/ruff-0.14.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4c943d847b7f02f7db4201a0600ea7d244d8a404fbb639b439e987edcf2baf9a", size = 14407037, upload-time = "2025-12-04T15:06:39.979Z" },
199
- { url = "https://files.pythonhosted.org/packages/96/bc/058fe0aefc0fbf0d19614cb6d1a3e2c048f7dc77ca64957f33b12cfdc5ef/ruff-0.14.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb6e8bf7b4f627548daa1b69283dac5a296bfe9ce856703b03130732e20ddfe2", size = 14102390, upload-time = "2025-12-04T15:06:46.372Z" },
200
- { url = "https://files.pythonhosted.org/packages/af/a4/e4f77b02b804546f4c17e8b37a524c27012dd6ff05855d2243b49a7d3cb9/ruff-0.14.8-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:7aaf2974f378e6b01d1e257c6948207aec6a9b5ba53fab23d0182efb887a0e4a", size = 14230793, upload-time = "2025-12-04T15:06:20.497Z" },
201
- { url = "https://files.pythonhosted.org/packages/3f/52/bb8c02373f79552e8d087cedaffad76b8892033d2876c2498a2582f09dcf/ruff-0.14.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e5758ca513c43ad8a4ef13f0f081f80f08008f410790f3611a21a92421ab045b", size = 13160039, upload-time = "2025-12-04T15:06:49.06Z" },
202
- { url = "https://files.pythonhosted.org/packages/1f/ad/b69d6962e477842e25c0b11622548df746290cc6d76f9e0f4ed7456c2c31/ruff-0.14.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:f74f7ba163b6e85a8d81a590363bf71618847e5078d90827749bfda1d88c9cdf", size = 13205158, upload-time = "2025-12-04T15:06:54.574Z" },
203
- { url = "https://files.pythonhosted.org/packages/06/63/54f23da1315c0b3dfc1bc03fbc34e10378918a20c0b0f086418734e57e74/ruff-0.14.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:eed28f6fafcc9591994c42254f5a5c5ca40e69a30721d2ab18bb0bb3baac3ab6", size = 13469550, upload-time = "2025-12-04T15:05:59.209Z" },
204
- { url = "https://files.pythonhosted.org/packages/70/7d/a4d7b1961e4903bc37fffb7ddcfaa7beb250f67d97cfd1ee1d5cddb1ec90/ruff-0.14.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:21d48fa744c9d1cb8d71eb0a740c4dd02751a5de9db9a730a8ef75ca34cf138e", size = 14211332, upload-time = "2025-12-04T15:06:06.027Z" },
205
- { url = "https://files.pythonhosted.org/packages/5d/93/2a5063341fa17054e5c86582136e9895db773e3c2ffb770dde50a09f35f0/ruff-0.14.8-py3-none-win32.whl", hash = "sha256:15f04cb45c051159baebb0f0037f404f1dc2f15a927418f29730f411a79bc4e7", size = 13151890, upload-time = "2025-12-04T15:06:11.668Z" },
206
- { url = "https://files.pythonhosted.org/packages/02/1c/65c61a0859c0add13a3e1cbb6024b42de587456a43006ca2d4fd3d1618fe/ruff-0.14.8-py3-none-win_amd64.whl", hash = "sha256:9eeb0b24242b5bbff3011409a739929f497f3fb5fe3b5698aba5e77e8c833097", size = 14537826, upload-time = "2025-12-04T15:06:26.409Z" },
207
- { url = "https://files.pythonhosted.org/packages/6d/63/8b41cea3afd7f58eb64ac9251668ee0073789a3bc9ac6f816c8c6fef986d/ruff-0.14.8-py3-none-win_arm64.whl", hash = "sha256:965a582c93c63fe715fd3e3f8aa37c4b776777203d8e1d8aa3cc0c14424a4b99", size = 13634522, upload-time = "2025-12-04T15:06:43.212Z" },
199
+ { url = "https://files.pythonhosted.org/packages/b8/1c/d1b1bba22cffec02351c78ab9ed4f7d7391876e12720298448b29b7229c1/ruff-0.14.9-py3-none-linux_armv6l.whl", hash = "sha256:f1ec5de1ce150ca6e43691f4a9ef5c04574ad9ca35c8b3b0e18877314aba7e75", size = 13576541, upload-time = "2025-12-11T21:39:14.806Z" },
200
+ { url = "https://files.pythonhosted.org/packages/94/ab/ffe580e6ea1fca67f6337b0af59fc7e683344a43642d2d55d251ff83ceae/ruff-0.14.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ed9d7417a299fc6030b4f26333bf1117ed82a61ea91238558c0268c14e00d0c2", size = 13779363, upload-time = "2025-12-11T21:39:20.29Z" },
201
+ { url = "https://files.pythonhosted.org/packages/7d/f8/2be49047f929d6965401855461e697ab185e1a6a683d914c5c19c7962d9e/ruff-0.14.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d5dc3473c3f0e4a1008d0ef1d75cee24a48e254c8bed3a7afdd2b4392657ed2c", size = 12925292, upload-time = "2025-12-11T21:39:38.757Z" },
202
+ { url = "https://files.pythonhosted.org/packages/9e/e9/08840ff5127916bb989c86f18924fd568938b06f58b60e206176f327c0fe/ruff-0.14.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84bf7c698fc8f3cb8278830fb6b5a47f9bcc1ed8cb4f689b9dd02698fa840697", size = 13362894, upload-time = "2025-12-11T21:39:02.524Z" },
203
+ { url = "https://files.pythonhosted.org/packages/31/1c/5b4e8e7750613ef43390bb58658eaf1d862c0cc3352d139cd718a2cea164/ruff-0.14.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aa733093d1f9d88a5d98988d8834ef5d6f9828d03743bf5e338bf980a19fce27", size = 13311482, upload-time = "2025-12-11T21:39:17.51Z" },
204
+ { url = "https://files.pythonhosted.org/packages/5b/3a/459dce7a8cb35ba1ea3e9c88f19077667a7977234f3b5ab197fad240b404/ruff-0.14.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a1cfb04eda979b20c8c19550c8b5f498df64ff8da151283311ce3199e8b3648", size = 14016100, upload-time = "2025-12-11T21:39:41.948Z" },
205
+ { url = "https://files.pythonhosted.org/packages/a6/31/f064f4ec32524f9956a0890fc6a944e5cf06c63c554e39957d208c0ffc45/ruff-0.14.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:1e5cb521e5ccf0008bd74d5595a4580313844a42b9103b7388eca5a12c970743", size = 15477729, upload-time = "2025-12-11T21:39:23.279Z" },
206
+ { url = "https://files.pythonhosted.org/packages/7a/6d/f364252aad36ccd443494bc5f02e41bf677f964b58902a17c0b16c53d890/ruff-0.14.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd429a8926be6bba4befa8cdcf3f4dd2591c413ea5066b1e99155ed245ae42bb", size = 15122386, upload-time = "2025-12-11T21:39:33.125Z" },
207
+ { url = "https://files.pythonhosted.org/packages/20/02/e848787912d16209aba2799a4d5a1775660b6a3d0ab3944a4ccc13e64a02/ruff-0.14.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab208c1b7a492e37caeaf290b1378148f75e13c2225af5d44628b95fd7834273", size = 14497124, upload-time = "2025-12-11T21:38:59.33Z" },
208
+ { url = "https://files.pythonhosted.org/packages/f3/51/0489a6a5595b7760b5dbac0dd82852b510326e7d88d51dbffcd2e07e3ff3/ruff-0.14.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72034534e5b11e8a593f517b2f2f2b273eb68a30978c6a2d40473ad0aaa4cb4a", size = 14195343, upload-time = "2025-12-11T21:39:44.866Z" },
209
+ { url = "https://files.pythonhosted.org/packages/f6/53/3bb8d2fa73e4c2f80acc65213ee0830fa0c49c6479313f7a68a00f39e208/ruff-0.14.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:712ff04f44663f1b90a1195f51525836e3413c8a773574a7b7775554269c30ed", size = 14346425, upload-time = "2025-12-11T21:39:05.927Z" },
210
+ { url = "https://files.pythonhosted.org/packages/ad/04/bdb1d0ab876372da3e983896481760867fc84f969c5c09d428e8f01b557f/ruff-0.14.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a111fee1db6f1d5d5810245295527cda1d367c5aa8f42e0fca9a78ede9b4498b", size = 13258768, upload-time = "2025-12-11T21:39:08.691Z" },
211
+ { url = "https://files.pythonhosted.org/packages/40/d9/8bf8e1e41a311afd2abc8ad12be1b6c6c8b925506d9069b67bb5e9a04af3/ruff-0.14.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8769efc71558fecc25eb295ddec7d1030d41a51e9dcf127cbd63ec517f22d567", size = 13326939, upload-time = "2025-12-11T21:39:53.842Z" },
212
+ { url = "https://files.pythonhosted.org/packages/f4/56/a213fa9edb6dd849f1cfbc236206ead10913693c72a67fb7ddc1833bf95d/ruff-0.14.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:347e3bf16197e8a2de17940cd75fd6491e25c0aa7edf7d61aa03f146a1aa885a", size = 13578888, upload-time = "2025-12-11T21:39:35.988Z" },
213
+ { url = "https://files.pythonhosted.org/packages/33/09/6a4a67ffa4abae6bf44c972a4521337ffce9cbc7808faadede754ef7a79c/ruff-0.14.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:7715d14e5bccf5b660f54516558aa94781d3eb0838f8e706fb60e3ff6eff03a8", size = 14314473, upload-time = "2025-12-11T21:39:50.78Z" },
214
+ { url = "https://files.pythonhosted.org/packages/12/0d/15cc82da5d83f27a3c6b04f3a232d61bc8c50d38a6cd8da79228e5f8b8d6/ruff-0.14.9-py3-none-win32.whl", hash = "sha256:df0937f30aaabe83da172adaf8937003ff28172f59ca9f17883b4213783df197", size = 13202651, upload-time = "2025-12-11T21:39:26.628Z" },
215
+ { url = "https://files.pythonhosted.org/packages/32/f7/c78b060388eefe0304d9d42e68fab8cffd049128ec466456cef9b8d4f06f/ruff-0.14.9-py3-none-win_amd64.whl", hash = "sha256:c0b53a10e61df15a42ed711ec0bda0c582039cf6c754c49c020084c55b5b0bc2", size = 14702079, upload-time = "2025-12-11T21:39:11.954Z" },
216
+ { url = "https://files.pythonhosted.org/packages/26/09/7a9520315decd2334afa65ed258fed438f070e31f05a2e43dd480a5e5911/ruff-0.14.9-py3-none-win_arm64.whl", hash = "sha256:8e821c366517a074046d92f0e9213ed1c13dbc5b37a7fc20b07f79b64d62cc84", size = 13744730, upload-time = "2025-12-11T21:39:29.659Z" },
208
217
  ]
209
218
 
210
219
  [[package]]
211
220
  name = "taranis-models"
212
221
  source = { editable = "." }
213
222
  dependencies = [
223
+ { name = "langcodes" },
214
224
  { name = "pydantic" },
215
225
  { name = "pydantic-settings" },
216
226
  { name = "python-dotenv" },
@@ -226,6 +236,7 @@ dev = [
226
236
 
227
237
  [package.metadata]
228
238
  requires-dist = [
239
+ { name = "langcodes" },
229
240
  { name = "pydantic" },
230
241
  { name = "pydantic-settings" },
231
242
  { name = "pyright", marker = "extra == 'dev'" },