jsonstat-validator 0.1.6__tar.gz → 0.2.0__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 (19) hide show
  1. {jsonstat_validator-0.1.6/jsonstat_validator.egg-info → jsonstat_validator-0.2.0}/PKG-INFO +3 -3
  2. {jsonstat_validator-0.1.6 → jsonstat_validator-0.2.0}/jsonstat_validator/__init__.py +3 -16
  3. jsonstat_validator-0.1.6/jsonstat_validator/validator.py → jsonstat_validator-0.2.0/jsonstat_validator/models.py +33 -27
  4. jsonstat_validator-0.2.0/jsonstat_validator/validator.py +70 -0
  5. {jsonstat_validator-0.1.6 → jsonstat_validator-0.2.0/jsonstat_validator.egg-info}/PKG-INFO +3 -3
  6. {jsonstat_validator-0.1.6 → jsonstat_validator-0.2.0}/jsonstat_validator.egg-info/SOURCES.txt +1 -0
  7. {jsonstat_validator-0.1.6 → jsonstat_validator-0.2.0}/jsonstat_validator.egg-info/requires.txt +1 -1
  8. {jsonstat_validator-0.1.6 → jsonstat_validator-0.2.0}/pyproject.toml +4 -4
  9. jsonstat_validator-0.2.0/requirements.txt +1 -0
  10. jsonstat_validator-0.1.6/requirements.txt +0 -1
  11. {jsonstat_validator-0.1.6 → jsonstat_validator-0.2.0}/LICENSE +0 -0
  12. {jsonstat_validator-0.1.6 → jsonstat_validator-0.2.0}/MANIFEST.in +0 -0
  13. {jsonstat_validator-0.1.6 → jsonstat_validator-0.2.0}/README.md +0 -0
  14. {jsonstat_validator-0.1.6 → jsonstat_validator-0.2.0}/jsonstat_validator.egg-info/dependency_links.txt +0 -0
  15. {jsonstat_validator-0.1.6 → jsonstat_validator-0.2.0}/jsonstat_validator.egg-info/top_level.txt +0 -0
  16. {jsonstat_validator-0.1.6 → jsonstat_validator-0.2.0}/setup.cfg +0 -0
  17. {jsonstat_validator-0.1.6 → jsonstat_validator-0.2.0}/setup.py +0 -0
  18. {jsonstat_validator-0.1.6 → jsonstat_validator-0.2.0}/tests/test_custom.py +0 -0
  19. {jsonstat_validator-0.1.6 → jsonstat_validator-0.2.0}/tests/test_official_samples.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jsonstat-validator
3
- Version: 0.1.6
3
+ Version: 0.2.0
4
4
  Summary: A Python validator for the JSON-stat 2.0 standard format, based on Pydantic.
5
5
  Author-email: Ahmed Hassan <ahmedhassan.ahmed@fao.org>
6
6
  License: # MIT License
@@ -30,11 +30,11 @@ Project-URL: Bug Tracker, https://github.com/ahmed-hassan19/jsonstat-validator/i
30
30
  Project-URL: Documentation, https://github.com/ahmed-hassan19/jsonstat-validator#readme
31
31
  Keywords: json-stat,validator,json,data-engineering,pydantic,python,fao
32
32
  Classifier: Programming Language :: Python :: 3
33
- Classifier: Programming Language :: Python :: 3.8
34
33
  Classifier: Programming Language :: Python :: 3.9
35
34
  Classifier: Programming Language :: Python :: 3.10
36
35
  Classifier: Programming Language :: Python :: 3.11
37
36
  Classifier: Programming Language :: Python :: 3.12
37
+ Classifier: Programming Language :: Python :: 3.13
38
38
  Classifier: License :: OSI Approved :: MIT License
39
39
  Classifier: Operating System :: OS Independent
40
40
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
@@ -42,7 +42,7 @@ Classifier: Topic :: Software Development :: Quality Assurance
42
42
  Requires-Python: >=3.8
43
43
  Description-Content-Type: text/markdown
44
44
  License-File: LICENSE
45
- Requires-Dist: pydantic<3.0.0,>=2.0.0
45
+ Requires-Dist: pydantic==2.11.2
46
46
  Provides-Extra: dev
47
47
  Requires-Dist: pytest>=8.1.1; extra == "dev"
48
48
  Requires-Dist: build>=1.0.0; extra == "dev"
@@ -10,27 +10,14 @@ dimensions are organized in categories.
10
10
  For more information on JSON-stat, see: https://json-stat.org/
11
11
  """
12
12
 
13
- from jsonstat_validator.validator import (
14
- Category,
15
- Collection,
16
- Dataset,
17
- DatasetRole,
18
- Dimension,
19
- JSONStatSchema,
20
- Link,
21
- Unit,
22
- validate_jsonstat,
23
- )
13
+ from jsonstat_validator.models import Collection, Dataset, Dimension, JSONStatSchema
14
+ from jsonstat_validator.validator import validate_jsonstat
24
15
 
25
- __version__ = "0.1.6"
16
+ __version__ = "0.2.0"
26
17
  __all__ = [
27
18
  "Dataset",
28
19
  "Dimension",
29
20
  "Collection",
30
- "Link",
31
- "Unit",
32
- "Category",
33
- "DatasetRole",
34
21
  "JSONStatSchema",
35
22
  "validate_jsonstat",
36
23
  ]
@@ -14,9 +14,9 @@ from typing import Any, Dict, List, Literal, Optional, Union
14
14
  from pydantic import (
15
15
  AnyUrl,
16
16
  BaseModel,
17
+ ConfigDict,
17
18
  Field,
18
19
  RootModel,
19
- ValidationError,
20
20
  field_serializer,
21
21
  field_validator,
22
22
  model_validator,
@@ -46,6 +46,8 @@ class JSONStatBaseModel(BaseModel):
46
46
  """Convert AnyUrl to string, if it exists."""
47
47
  return str(href) if href else None
48
48
 
49
+ model_config = ConfigDict(extra="forbid", serialize_by_alias=True)
50
+
49
51
 
50
52
  class Unit(JSONStatBaseModel):
51
53
  """Unit of measurement of a dimension.
@@ -169,6 +171,14 @@ class Category(JSONStatBaseModel):
169
171
  "of a dimension with a metric role."
170
172
  ),
171
173
  )
174
+ note: Optional[Dict[str, List[str]]] = Field(
175
+ default=None,
176
+ description=(
177
+ "note allows to assign annotations to datasets (array), dimensions "
178
+ "(array) and categories (object). To assign annotations to individual "
179
+ "data, use status: https://json-stat.org/full/#status."
180
+ ),
181
+ )
172
182
 
173
183
  @model_validator(mode="after")
174
184
  def validate_category(self):
@@ -320,8 +330,9 @@ class Dimension(JSONStatBaseModel):
320
330
  note: Optional[List[str]] = Field(
321
331
  default=None,
322
332
  description=(
323
- "Note allows to assign annotations to datasets (array), dimensions (array) "
324
- "and categories (object)."
333
+ "note allows to assign annotations to datasets (array), dimensions "
334
+ "(array) and categories (object). To assign annotations to individual "
335
+ "data, use status: https://json-stat.org/full/#status."
325
336
  ),
326
337
  )
327
338
  updated: Optional[str] = Field(
@@ -417,8 +428,9 @@ class DatasetDimension(JSONStatBaseModel):
417
428
  note: Optional[List[str]] = Field(
418
429
  default=None,
419
430
  description=(
420
- "Note allows to assign annotations to datasets (array), dimensions (array) "
421
- "and categories (object)."
431
+ "note allows to assign annotations to datasets (array), dimensions "
432
+ "(array) and categories (object). To assign annotations to individual "
433
+ "data, use status: https://json-stat.org/full/#status."
422
434
  ),
423
435
  )
424
436
  updated: Optional[str] = Field(
@@ -597,8 +609,9 @@ class Dataset(JSONStatBaseModel):
597
609
  note: Optional[List[str]] = Field(
598
610
  default=None,
599
611
  description=(
600
- "Note allows to assign annotations to datasets (array), dimensions (array) "
601
- "and categories (object)."
612
+ "note allows to assign annotations to datasets (array), dimensions "
613
+ "(array) and categories (object). To assign annotations to individual "
614
+ "data, use status: https://json-stat.org/full/#status."
602
615
  ),
603
616
  )
604
617
  extension: Optional[Dict[str, Any]] = Field(
@@ -707,6 +720,19 @@ class Collection(JSONStatBaseModel):
707
720
  "(datasets, dimensions, collections)."
708
721
  ),
709
722
  )
723
+ source: Optional[str] = Field(
724
+ default=None,
725
+ description="It contains a language-dependent short text describing the source "
726
+ "of the collection.",
727
+ )
728
+ note: Optional[List[str]] = Field(
729
+ default=None,
730
+ description=(
731
+ "note allows to assign annotations to datasets (array), dimensions "
732
+ "(array) and categories (object). To assign annotations to individual "
733
+ "data, use status: https://json-stat.org/full/#status."
734
+ ),
735
+ )
710
736
  extension: Optional[Dict[str, Any]] = Field(
711
737
  default=None,
712
738
  description="Extension allows JSON-stat to be extended for particular needs. "
@@ -747,23 +773,3 @@ class JSONStatSchema(RootModel):
747
773
  def serialize_any_url(self, href: Optional[AnyUrl]) -> Optional[str]:
748
774
  """Convert AnyUrl to string, if it exists."""
749
775
  return str(href) if href else None
750
-
751
-
752
- def validate_jsonstat(data: Dict[str, Any]) -> bool:
753
- """
754
- Validate a JSON-stat 2.0 object against the specification.
755
-
756
- Args:
757
- data: A dictionary containing JSON-stat data
758
-
759
- Returns:
760
- bool: True if valid, raises ValueError otherwise
761
-
762
- Raises:
763
- ValueError: If the data does not conform to the JSON-stat specification
764
- """
765
- try:
766
- JSONStatSchema(**data)
767
- return True
768
- except ValidationError as e:
769
- raise ValueError(e) from e
@@ -0,0 +1,70 @@
1
+ from typing import Any, Dict
2
+
3
+ from pydantic import ValidationError
4
+
5
+ from jsonstat_validator.models import JSONStatSchema
6
+
7
+
8
+ def format_error_location(loc: tuple) -> str:
9
+ """
10
+ Format error location to be more human-readable.
11
+
12
+ Args:
13
+ loc: Location tuple from ValidationError
14
+
15
+ Returns:
16
+ str: Formatted location string
17
+ """
18
+ parts = []
19
+ for item in loc:
20
+ if isinstance(item, int):
21
+ parts.append(f"[{item}]")
22
+ elif parts:
23
+ parts.append(f".{item}")
24
+ else:
25
+ parts.append(item)
26
+ return "".join(parts)
27
+
28
+
29
+ def format_validation_errors(e: ValidationError) -> str:
30
+ """
31
+ Format ValidationError to be more human-readable.
32
+
33
+ Args:
34
+ e: ValidationError instance
35
+
36
+ Returns:
37
+ str: Formatted error message
38
+ """
39
+ errors = []
40
+ for error in e.errors():
41
+ # Create a simplified error object without input and url fields
42
+ loc = format_error_location(error["loc"])
43
+ msg = error["msg"]
44
+ type_str = error["type"]
45
+
46
+ errors.append(f"Error at '{loc}': {msg} (type={type_str})")
47
+
48
+ return "\n".join(errors)
49
+
50
+
51
+ def validate_jsonstat(data: Dict[str, Any]) -> bool:
52
+ """
53
+ Validate a JSON-stat 2.0 object against the specification.
54
+
55
+ Args:
56
+ data: A dictionary containing JSON-stat data
57
+
58
+ Returns:
59
+ bool: True if valid, raises ValueError otherwise
60
+
61
+ Raises:
62
+ ValueError: If the data does not conform to the JSON-stat specification
63
+ with a user-friendly error message
64
+ """
65
+ try:
66
+ JSONStatSchema.model_validate(data)
67
+ return True
68
+ except ValidationError as e:
69
+ error_message = format_validation_errors(e)
70
+ raise ValueError(f"JSON-stat validation failed:\n{error_message}") from None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jsonstat-validator
3
- Version: 0.1.6
3
+ Version: 0.2.0
4
4
  Summary: A Python validator for the JSON-stat 2.0 standard format, based on Pydantic.
5
5
  Author-email: Ahmed Hassan <ahmedhassan.ahmed@fao.org>
6
6
  License: # MIT License
@@ -30,11 +30,11 @@ Project-URL: Bug Tracker, https://github.com/ahmed-hassan19/jsonstat-validator/i
30
30
  Project-URL: Documentation, https://github.com/ahmed-hassan19/jsonstat-validator#readme
31
31
  Keywords: json-stat,validator,json,data-engineering,pydantic,python,fao
32
32
  Classifier: Programming Language :: Python :: 3
33
- Classifier: Programming Language :: Python :: 3.8
34
33
  Classifier: Programming Language :: Python :: 3.9
35
34
  Classifier: Programming Language :: Python :: 3.10
36
35
  Classifier: Programming Language :: Python :: 3.11
37
36
  Classifier: Programming Language :: Python :: 3.12
37
+ Classifier: Programming Language :: Python :: 3.13
38
38
  Classifier: License :: OSI Approved :: MIT License
39
39
  Classifier: Operating System :: OS Independent
40
40
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
@@ -42,7 +42,7 @@ Classifier: Topic :: Software Development :: Quality Assurance
42
42
  Requires-Python: >=3.8
43
43
  Description-Content-Type: text/markdown
44
44
  License-File: LICENSE
45
- Requires-Dist: pydantic<3.0.0,>=2.0.0
45
+ Requires-Dist: pydantic==2.11.2
46
46
  Provides-Extra: dev
47
47
  Requires-Dist: pytest>=8.1.1; extra == "dev"
48
48
  Requires-Dist: build>=1.0.0; extra == "dev"
@@ -5,6 +5,7 @@ pyproject.toml
5
5
  requirements.txt
6
6
  setup.py
7
7
  jsonstat_validator/__init__.py
8
+ jsonstat_validator/models.py
8
9
  jsonstat_validator/validator.py
9
10
  jsonstat_validator.egg-info/PKG-INFO
10
11
  jsonstat_validator.egg-info/SOURCES.txt
@@ -1,4 +1,4 @@
1
- pydantic<3.0.0,>=2.0.0
1
+ pydantic==2.11.2
2
2
 
3
3
  [dev]
4
4
  pytest>=8.1.1
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "jsonstat-validator"
7
- version = "0.1.6"
7
+ version = "0.2.0"
8
8
  description = "A Python validator for the JSON-stat 2.0 standard format, based on Pydantic."
9
9
  readme = "README.md"
10
10
  authors = [
@@ -13,11 +13,11 @@ authors = [
13
13
  license = {file = "LICENSE"}
14
14
  classifiers = [
15
15
  "Programming Language :: Python :: 3",
16
- "Programming Language :: Python :: 3.8",
17
16
  "Programming Language :: Python :: 3.9",
18
17
  "Programming Language :: Python :: 3.10",
19
18
  "Programming Language :: Python :: 3.11",
20
19
  "Programming Language :: Python :: 3.12",
20
+ "Programming Language :: Python :: 3.13",
21
21
  "License :: OSI Approved :: MIT License",
22
22
  "Operating System :: OS Independent",
23
23
  "Topic :: Software Development :: Libraries :: Python Modules",
@@ -26,7 +26,7 @@ classifiers = [
26
26
  keywords = ["json-stat", "validator", "json", "data-engineering", "pydantic", "python", "fao"]
27
27
  requires-python = ">=3.8"
28
28
  dependencies = [
29
- "pydantic>=2.0.0,<3.0.0",
29
+ "pydantic==2.11.2",
30
30
  ]
31
31
 
32
32
  [project.optional-dependencies]
@@ -55,7 +55,7 @@ testpaths = ["tests"]
55
55
 
56
56
  [tool.black]
57
57
  line-length = 90
58
- target-version = ["py38", "py39", "py310", "py311", "py312"]
58
+ target-version = ["py39", "py310", "py311", "py312", "py313"]
59
59
  include = '\.pyi?$'
60
60
 
61
61
  [tool.isort]
@@ -0,0 +1 @@
1
+ pydantic==2.11.2
@@ -1 +0,0 @@
1
- pydantic==2.*