strapi-kit 0.0.5__py3-none-any.whl → 0.1.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.
- strapi_kit/_version.py +2 -2
- strapi_kit/cache/schema_cache.py +91 -3
- strapi_kit/client/async_client.py +83 -47
- strapi_kit/client/base.py +70 -3
- strapi_kit/client/sync_client.py +23 -12
- strapi_kit/export/__init__.py +3 -1
- strapi_kit/export/exporter.py +160 -4
- strapi_kit/export/importer.py +519 -66
- strapi_kit/export/jsonl_reader.py +195 -0
- strapi_kit/export/jsonl_writer.py +134 -0
- strapi_kit/export/relation_resolver.py +230 -1
- strapi_kit/models/__init__.py +8 -1
- strapi_kit/models/config.py +5 -1
- strapi_kit/models/enums.py +4 -4
- strapi_kit/models/export_format.py +13 -0
- strapi_kit/models/import_options.py +12 -2
- strapi_kit/models/schema.py +9 -4
- strapi_kit/utils/__init__.py +3 -0
- strapi_kit/utils/schema.py +35 -0
- {strapi_kit-0.0.5.dist-info → strapi_kit-0.1.0.dist-info}/METADATA +2 -3
- {strapi_kit-0.0.5.dist-info → strapi_kit-0.1.0.dist-info}/RECORD +23 -20
- {strapi_kit-0.0.5.dist-info → strapi_kit-0.1.0.dist-info}/WHEEL +0 -0
- {strapi_kit-0.0.5.dist-info → strapi_kit-0.1.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -4,12 +4,12 @@ Defines how imported data should be processed and validated.
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
from collections.abc import Callable
|
|
7
|
-
from enum import
|
|
7
|
+
from enum import StrEnum
|
|
8
8
|
|
|
9
9
|
from pydantic import BaseModel, Field
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class ConflictResolution(
|
|
12
|
+
class ConflictResolution(StrEnum):
|
|
13
13
|
"""Strategy for handling conflicts during import.
|
|
14
14
|
|
|
15
15
|
Attributes:
|
|
@@ -90,6 +90,7 @@ class ImportResult(BaseModel):
|
|
|
90
90
|
entities_skipped: Number of entities skipped
|
|
91
91
|
entities_updated: Number of entities updated
|
|
92
92
|
entities_failed: Number of entities that failed
|
|
93
|
+
relations_imported: Number of relation updates performed
|
|
93
94
|
media_imported: Number of media files imported
|
|
94
95
|
media_skipped: Number of media files skipped
|
|
95
96
|
errors: List of error messages
|
|
@@ -103,6 +104,7 @@ class ImportResult(BaseModel):
|
|
|
103
104
|
entities_skipped: int = Field(default=0, description="Entities skipped")
|
|
104
105
|
entities_updated: int = Field(default=0, description="Entities updated")
|
|
105
106
|
entities_failed: int = Field(default=0, description="Entities failed")
|
|
107
|
+
relations_imported: int = Field(default=0, description="Relation updates performed")
|
|
106
108
|
media_imported: int = Field(default=0, description="Media files imported")
|
|
107
109
|
media_skipped: int = Field(default=0, description="Media files skipped")
|
|
108
110
|
errors: list[str] = Field(default_factory=list, description="Error messages")
|
|
@@ -111,6 +113,14 @@ class ImportResult(BaseModel):
|
|
|
111
113
|
default_factory=dict,
|
|
112
114
|
description="Mapping of old IDs to new IDs per content type",
|
|
113
115
|
)
|
|
116
|
+
doc_id_mapping: dict[str, dict[int, str]] = Field(
|
|
117
|
+
default_factory=dict,
|
|
118
|
+
description="Mapping of old IDs to document_ids per content type (for v5 endpoints)",
|
|
119
|
+
)
|
|
120
|
+
doc_id_to_new_id: dict[str, dict[str, int]] = Field(
|
|
121
|
+
default_factory=dict,
|
|
122
|
+
description="Mapping of old document_ids to new IDs (for v5 string relation resolution)",
|
|
123
|
+
)
|
|
114
124
|
|
|
115
125
|
def add_error(self, error: str) -> None:
|
|
116
126
|
"""Add an error message.
|
strapi_kit/models/schema.py
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
"""Content type schema models."""
|
|
2
2
|
|
|
3
|
-
from enum import
|
|
3
|
+
from enum import StrEnum
|
|
4
4
|
|
|
5
5
|
from pydantic import BaseModel, Field
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
class FieldType(
|
|
8
|
+
class FieldType(StrEnum):
|
|
9
9
|
"""Field types in Strapi."""
|
|
10
10
|
|
|
11
11
|
STRING = "string"
|
|
12
12
|
TEXT = "text"
|
|
13
13
|
RICH_TEXT = "richtext"
|
|
14
14
|
EMAIL = "email"
|
|
15
|
-
PASSWORD = "password" #
|
|
15
|
+
PASSWORD = "password" # noqa: S105 - Field type enum, not a hardcoded password
|
|
16
16
|
INTEGER = "integer"
|
|
17
17
|
BIG_INTEGER = "biginteger"
|
|
18
18
|
FLOAT = "float"
|
|
@@ -31,7 +31,7 @@ class FieldType(str, Enum):
|
|
|
31
31
|
UID = "uid"
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
class RelationType(
|
|
34
|
+
class RelationType(StrEnum):
|
|
35
35
|
"""Relation types in Strapi."""
|
|
36
36
|
|
|
37
37
|
ONE_TO_ONE = "oneToOne"
|
|
@@ -53,6 +53,11 @@ class FieldSchema(BaseModel):
|
|
|
53
53
|
mapped_by: str | None = None
|
|
54
54
|
inversed_by: str | None = None
|
|
55
55
|
|
|
56
|
+
# Component-specific
|
|
57
|
+
component: str | None = None # Component UID for COMPONENT type
|
|
58
|
+
components: list[str] | None = None # Allowed UIDs for DYNAMIC_ZONE
|
|
59
|
+
repeatable: bool = False # True for repeatable components
|
|
60
|
+
|
|
56
61
|
|
|
57
62
|
class ContentTypeSchema(BaseModel):
|
|
58
63
|
"""Complete schema for a content type."""
|
strapi_kit/utils/__init__.py
CHANGED
|
@@ -7,6 +7,7 @@ This package contains helper utilities including:
|
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
from strapi_kit.utils.rate_limiter import AsyncTokenBucketRateLimiter, TokenBucketRateLimiter
|
|
10
|
+
from strapi_kit.utils.schema import extract_info_from_schema
|
|
10
11
|
from strapi_kit.utils.seo import SEOConfiguration, detect_seo_configuration
|
|
11
12
|
from strapi_kit.utils.uid import (
|
|
12
13
|
api_id_to_singular,
|
|
@@ -31,4 +32,6 @@ __all__ = [
|
|
|
31
32
|
# SEO utilities
|
|
32
33
|
"detect_seo_configuration",
|
|
33
34
|
"SEOConfiguration",
|
|
35
|
+
# Schema utilities
|
|
36
|
+
"extract_info_from_schema",
|
|
34
37
|
]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Schema utility functions.
|
|
2
|
+
|
|
3
|
+
This module provides shared utility functions for handling Strapi schema data,
|
|
4
|
+
particularly for extracting info from various schema formats.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def extract_info_from_schema(schema: dict[str, Any]) -> dict[str, Any]:
|
|
11
|
+
"""Extract info dict from schema, handling both v5 formats.
|
|
12
|
+
|
|
13
|
+
Strapi v5 may return info in two formats:
|
|
14
|
+
1. Nested: schema.info.displayName (alternative format)
|
|
15
|
+
2. Flat: schema.displayName (actual v5 API format from Issue #28)
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
schema: Schema dict from API response
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
Info dict with displayName, singularName, pluralName, description
|
|
22
|
+
"""
|
|
23
|
+
# Check for nested info object first
|
|
24
|
+
nested_info_raw = schema.get("info")
|
|
25
|
+
nested_info: dict[str, Any] = nested_info_raw if isinstance(nested_info_raw, dict) else {}
|
|
26
|
+
if nested_info.get("displayName"):
|
|
27
|
+
return nested_info
|
|
28
|
+
|
|
29
|
+
# Extract from top-level schema properties (actual v5 format)
|
|
30
|
+
return {
|
|
31
|
+
"displayName": schema.get("displayName", ""),
|
|
32
|
+
"singularName": schema.get("singularName"),
|
|
33
|
+
"pluralName": schema.get("pluralName"),
|
|
34
|
+
"description": schema.get("description"),
|
|
35
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: strapi-kit
|
|
3
|
-
Version: 0.0
|
|
3
|
+
Version: 0.1.0
|
|
4
4
|
Summary: A modern Python client for Strapi CMS with import/export capabilities
|
|
5
5
|
Project-URL: Homepage, https://github.com/mehdizare/strapi-kit
|
|
6
6
|
Project-URL: Documentation, https://mehdizare.github.io/strapi-kit/
|
|
@@ -27,7 +27,6 @@ Requires-Dist: python-dateutil>=2.9.0
|
|
|
27
27
|
Requires-Dist: tenacity>=9.0.0
|
|
28
28
|
Requires-Dist: typing-extensions>=4.15.0
|
|
29
29
|
Provides-Extra: dev
|
|
30
|
-
Requires-Dist: bandit[toml]>=1.9.3; extra == 'dev'
|
|
31
30
|
Requires-Dist: detect-secrets>=1.5.0; extra == 'dev'
|
|
32
31
|
Requires-Dist: mypy>=1.19.1; extra == 'dev'
|
|
33
32
|
Requires-Dist: pre-commit>=4.5.0; extra == 'dev'
|
|
@@ -1175,7 +1174,7 @@ pre-commit autoupdate
|
|
|
1175
1174
|
- ✅ Code formatting (ruff format)
|
|
1176
1175
|
- ✅ Linting (ruff check)
|
|
1177
1176
|
- ✅ Type checking (mypy strict mode)
|
|
1178
|
-
- ✅ Security issues (
|
|
1177
|
+
- ✅ Security issues (ruff S rules)
|
|
1179
1178
|
- ✅ Secrets detection (detect-secrets)
|
|
1180
1179
|
- ✅ File consistency (trailing whitespace, EOF, etc.)
|
|
1181
1180
|
|
|
@@ -1,31 +1,33 @@
|
|
|
1
1
|
strapi_kit/__init__.py,sha256=z4BR2eysdjTvsFaTqyUX0aPnSODMC2MyhdpvtCgWHVY,2177
|
|
2
2
|
strapi_kit/__version__.py,sha256=oLc_AUMPwiL7J2vgrvXdzVqbSQl2hqkPZ6dNfUx1lTU,478
|
|
3
|
-
strapi_kit/_version.py,sha256=
|
|
3
|
+
strapi_kit/_version.py,sha256=5jwwVncvCiTnhOedfkzzxmxsggwmTBORdFL_4wq0ZeY,704
|
|
4
4
|
strapi_kit/config_provider.py,sha256=Eky8mH6XgvgrwzsQuAc4gPpbPby_miycxqQH175rlU4,11864
|
|
5
5
|
strapi_kit/protocols.py,sha256=wMeGSFCSxeamv2YDzWWWSVJtiGrm__1Xg00QighEbQ4,10971
|
|
6
6
|
strapi_kit/auth/__init__.py,sha256=VhjbOiyBVSafz3lf2a43bnbSm0J8PG-lguIKHlRplx8,117
|
|
7
7
|
strapi_kit/auth/api_token.py,sha256=FntOxnf18ZdF0YwGjt0J6DM9tlxmIGZGIplqkLvstl0,1419
|
|
8
8
|
strapi_kit/cache/__init__.py,sha256=MpqVNsjbE6_QGEwyxZ80h-PFkB8NzDv7xGxJK1g5agQ,126
|
|
9
|
-
strapi_kit/cache/schema_cache.py,sha256=
|
|
9
|
+
strapi_kit/cache/schema_cache.py,sha256=n7-puYmJ41dwS08CWjXAQQduUyVNHRSxtwujk-Ub6Sk,9516
|
|
10
10
|
strapi_kit/client/__init__.py,sha256=R9Ux5bCret4mnXItnFh5MxYlMOjoS4bepPX1KpNSs5w,216
|
|
11
|
-
strapi_kit/client/async_client.py,sha256=
|
|
12
|
-
strapi_kit/client/base.py,sha256=
|
|
13
|
-
strapi_kit/client/sync_client.py,sha256=
|
|
11
|
+
strapi_kit/client/async_client.py,sha256=3RBDOzBliKwPDThB-Br7udsHYq_V8C-QCNryZKol4f8,41142
|
|
12
|
+
strapi_kit/client/base.py,sha256=jqWKFynPaigTgSL97AIGzjDfR2Qyw3dxkIrdksytg2Q,22831
|
|
13
|
+
strapi_kit/client/sync_client.py,sha256=pwZjdoPqDNg4R3JzwEEmqszKaC1aAgyHn3cVxalxqpE,36845
|
|
14
14
|
strapi_kit/exceptions/__init__.py,sha256=lGjEMAbbKO4MXIodY6jxF5x0WerbSZEnYL_r990tzXM,748
|
|
15
15
|
strapi_kit/exceptions/errors.py,sha256=Yc051k-3tCmT7ybJjQXs9V_i6bh0pY4xW6zmTT7i4PQ,5328
|
|
16
|
-
strapi_kit/export/__init__.py,sha256=
|
|
17
|
-
strapi_kit/export/exporter.py,sha256
|
|
18
|
-
strapi_kit/export/importer.py,sha256=
|
|
16
|
+
strapi_kit/export/__init__.py,sha256=5vaQ9cNdNTxM7jfRqk4J8whEnuvWcid55Z_8Kp8nDVI,504
|
|
17
|
+
strapi_kit/export/exporter.py,sha256=-adEuIOloRs2IDAdLiZffZUqZ7eX4EldxORMobZqO2E,20812
|
|
18
|
+
strapi_kit/export/importer.py,sha256=AptEN3k3eW-bhNAobySVfs0znpOe5P27KOp3XEufzww,45888
|
|
19
|
+
strapi_kit/export/jsonl_reader.py,sha256=hOU56iliXaV6fXQ5lUNTISZyL1uwCvhAfpZnri_qmCE,6069
|
|
20
|
+
strapi_kit/export/jsonl_writer.py,sha256=xrgiN6Gv25EGIEYGHJWeXuHb0NzSRrIHKHk905BxGpc,4094
|
|
19
21
|
strapi_kit/export/media_handler.py,sha256=xmx06M4ehtpNpVDwwuppwGpLwRd9s2M-NNnQ7I1T5Pk,11014
|
|
20
|
-
strapi_kit/export/relation_resolver.py,sha256=
|
|
21
|
-
strapi_kit/models/__init__.py,sha256=
|
|
22
|
+
strapi_kit/export/relation_resolver.py,sha256=d27z389DvDIOQXkUvufB_UmPbTp6SlRy4wlFtNPrmU8,15125
|
|
23
|
+
strapi_kit/models/__init__.py,sha256=Ad02Jl4hdPLqfDkBR4vHrVT_G0ZVrM5SprPaqbwYtgQ,3500
|
|
22
24
|
strapi_kit/models/bulk.py,sha256=g1swXgk8nWE_C-u6LIwKJzk2E5xmqMxDMQgY6SzxY7Q,2100
|
|
23
|
-
strapi_kit/models/config.py,sha256=
|
|
25
|
+
strapi_kit/models/config.py,sha256=xuYEH0EgJzUiE8T5Nxuln01FQdNgzHJdsVNuLbYcoIE,4606
|
|
24
26
|
strapi_kit/models/content_type.py,sha256=AIONiPq6-ZyNdoAygiR1_ynh-s2d5ti2GvtmnaktzMs,4150
|
|
25
|
-
strapi_kit/models/enums.py,sha256=
|
|
26
|
-
strapi_kit/models/export_format.py,sha256=
|
|
27
|
-
strapi_kit/models/import_options.py,sha256=
|
|
28
|
-
strapi_kit/models/schema.py,sha256=
|
|
27
|
+
strapi_kit/models/enums.py,sha256=y8cNZ_2fktdrI8ggJkd-DHfuKUepN-ZZC_PE0mgg2nE,2936
|
|
28
|
+
strapi_kit/models/export_format.py,sha256=Nt6QXn4QmSgWsZNWbdXQuBnXe45RdJL09KrbXQb_duI,5664
|
|
29
|
+
strapi_kit/models/import_options.py,sha256=8goA5A0RRqDhogBtfyTxu6o1ej7rT7jwSLyBN_nuwbs,5326
|
|
30
|
+
strapi_kit/models/schema.py,sha256=UuOsfqS2IpZ_glCgFbBXDIgfC_260JyVhU9pX17XAqk,2709
|
|
29
31
|
strapi_kit/models/request/__init__.py,sha256=RvuVgPvc2tAx9A_Esh04SZZ5Oi1GFiYpxdg90TLsd6A,54
|
|
30
32
|
strapi_kit/models/request/fields.py,sha256=VrPyf0Pg_EQ3z2IyzBhaw_4fr7N5VWJRcN2Li7ZyZ2w,1828
|
|
31
33
|
strapi_kit/models/request/filters.py,sha256=3qMzI8cTMfYCFWRAGMbw6DmEBtD2yUWB4UswABQavR4,19274
|
|
@@ -47,11 +49,12 @@ strapi_kit/operations/media.py,sha256=26eUo-o6UDtHOKNuVc8bvoXht037-bH114glLvk-RQ
|
|
|
47
49
|
strapi_kit/operations/streaming.py,sha256=A6Czlq_c2yIc7vQMx4OwLURBgdTPnnOfa80z-Mw5pMQ,4796
|
|
48
50
|
strapi_kit/parsers/__init__.py,sha256=-4WSHKbFhnbOB4j7MF2qyktgkb6t8RY3slTYKV4vhvg,142
|
|
49
51
|
strapi_kit/parsers/version_detecting.py,sha256=i6Wh7NSQYPWSv0GR63ZJLuPF6BqFwQ_Y7J3q7l7h1JQ,6421
|
|
50
|
-
strapi_kit/utils/__init__.py,sha256=
|
|
52
|
+
strapi_kit/utils/__init__.py,sha256=FXyI9rQ6aJRSKW6--4pBauHREYMHz2dxSfXr8rG-zSA,939
|
|
51
53
|
strapi_kit/utils/rate_limiter.py,sha256=c-oAgCILG-6nrjhxIXEx3sKqRgkxOHcNJE496ix7aVA,6367
|
|
54
|
+
strapi_kit/utils/schema.py,sha256=tmcMiNgr7foCeuk6G_IPTnaR3RBOsG-T6TM1TsmnCm8,1200
|
|
52
55
|
strapi_kit/utils/seo.py,sha256=p1CR3NGPJfarLosqRa3PAgigS9l9IB_LXUMjaZBXDeM,9317
|
|
53
56
|
strapi_kit/utils/uid.py,sha256=IcGlFKxtyIIWm9TKVMDX4WseSCMS5FLLDNJItSZgIoA,6797
|
|
54
|
-
strapi_kit-0.0.
|
|
55
|
-
strapi_kit-0.0.
|
|
56
|
-
strapi_kit-0.0.
|
|
57
|
-
strapi_kit-0.0.
|
|
57
|
+
strapi_kit-0.1.0.dist-info/METADATA,sha256=W1YaiKxve9OO4rMVZlGdJbyqCtJcg1s_yciyQ_7jaow,38024
|
|
58
|
+
strapi_kit-0.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
59
|
+
strapi_kit-0.1.0.dist-info/licenses/LICENSE,sha256=lN0YUtXlAFBt9MNYr2F0GJEYdprxDOTIqcVhKxMsaTI,1067
|
|
60
|
+
strapi_kit-0.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|