compressedfhir 1.0.6__tar.gz → 1.0.8__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.

Potentially problematic release.


This version of compressedfhir might be problematic. Click here for more details.

Files changed (69) hide show
  1. {compressedfhir-1.0.6/compressedfhir.egg-info → compressedfhir-1.0.8}/PKG-INFO +1 -1
  2. compressedfhir-1.0.8/VERSION +1 -0
  3. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/compressed_dict/v1/compressed_dict.py +5 -1
  4. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/json_serializers/test/test_type_preservation_decoder.py +16 -1
  5. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/json_serializers/test/test_type_preservation_encoder.py +13 -1
  6. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/json_serializers/test/test_type_preservation_serializer.py +22 -1
  7. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/json_serializers/type_preservation_decoder.py +26 -1
  8. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/json_serializers/type_preservation_encoder.py +6 -1
  9. {compressedfhir-1.0.6 → compressedfhir-1.0.8/compressedfhir.egg-info}/PKG-INFO +1 -1
  10. compressedfhir-1.0.6/VERSION +0 -1
  11. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/LICENSE +0 -0
  12. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/MANIFEST.in +0 -0
  13. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/Makefile +0 -0
  14. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/README.md +0 -0
  15. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/__init__.py +0 -0
  16. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/fhir/__init__.py +0 -0
  17. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/fhir/base_resource_list.py +0 -0
  18. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/fhir/fhir_bundle.py +0 -0
  19. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/fhir/fhir_bundle_entry.py +0 -0
  20. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/fhir/fhir_bundle_entry_list.py +0 -0
  21. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/fhir/fhir_bundle_entry_request.py +0 -0
  22. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/fhir/fhir_bundle_entry_response.py +0 -0
  23. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/fhir/fhir_bundle_entry_search.py +0 -0
  24. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/fhir/fhir_identifier.py +0 -0
  25. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/fhir/fhir_link.py +0 -0
  26. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/fhir/fhir_meta.py +0 -0
  27. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/fhir/fhir_resource.py +0 -0
  28. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/fhir/fhir_resource_list.py +0 -0
  29. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/fhir/fhir_resource_map.py +0 -0
  30. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/fhir/test/__init__.py +0 -0
  31. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/fhir/test/test_bundle_entry.py +0 -0
  32. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/fhir/test/test_bundle_entry_list.py +0 -0
  33. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/fhir/test/test_bundle_entry_request.py +0 -0
  34. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/fhir/test/test_bundle_entry_response.py +0 -0
  35. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/fhir/test/test_fhir_bundle.py +0 -0
  36. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/fhir/test/test_fhir_resource.py +0 -0
  37. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/fhir/test/test_fhir_resource_list.py +0 -0
  38. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/fhir/test/test_fhir_resource_map.py +0 -0
  39. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/py.typed +0 -0
  40. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/__init__.py +0 -0
  41. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/compressed_dict/__init__.py +0 -0
  42. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/compressed_dict/v1/__init__.py +0 -0
  43. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/compressed_dict/v1/compressed_dict_access_error.py +0 -0
  44. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/compressed_dict/v1/compressed_dict_storage_mode.py +0 -0
  45. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/compressed_dict/v1/test/__init__.py +0 -0
  46. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/compressed_dict/v1/test/test_compressed_dict.py +0 -0
  47. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/fhir_json_encoder.py +0 -0
  48. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/json_helpers.py +0 -0
  49. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/json_serializers/__init__.py +0 -0
  50. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/json_serializers/test/__init__.py +0 -0
  51. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/json_serializers/type_preservation_serializer.py +0 -0
  52. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/ordered_dict_to_dict_converter/__init__.py +0 -0
  53. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/ordered_dict_to_dict_converter/ordered_dict_to_dict_converter.py +0 -0
  54. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/string_compressor/__init__.py +0 -0
  55. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/string_compressor/v1/__init__.py +0 -0
  56. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/string_compressor/v1/string_compressor.py +0 -0
  57. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/string_compressor/v1/test/__init__.py +0 -0
  58. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/string_compressor/v1/test/test_string_compressor.py +0 -0
  59. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/test/__init__.py +0 -0
  60. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/test/test_fhir_json_encoder.py +0 -0
  61. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir/utilities/test/test_json_helpers.py +0 -0
  62. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir.egg-info/SOURCES.txt +0 -0
  63. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir.egg-info/dependency_links.txt +0 -0
  64. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir.egg-info/not-zip-safe +0 -0
  65. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir.egg-info/requires.txt +0 -0
  66. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/compressedfhir.egg-info/top_level.txt +0 -0
  67. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/setup.cfg +0 -0
  68. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/setup.py +0 -0
  69. {compressedfhir-1.0.6 → compressedfhir-1.0.8}/tests/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: compressedfhir
3
- Version: 1.0.6
3
+ Version: 1.0.8
4
4
  Summary: Stores FHIR JSON resources in compressed form in memory
5
5
  Home-page: https://github.com/icanbwell/compressed-fhir
6
6
  Author: Imran Qureshi
@@ -0,0 +1 @@
1
+ 1.0.8
@@ -429,6 +429,7 @@ class CompressedDict[K, V](MutableMapping[K, V]):
429
429
  """
430
430
  Returns the raw dictionary. Deserializes if necessary.
431
431
  Note that this dictionary preserves the python types so it is not FHIR friendly.
432
+ For example, datetime will be represented as a datetime object instead of iso format string per FHIR.
432
433
  Use dict() if you want a FHIR friendly version.
433
434
 
434
435
  Returns:
@@ -437,12 +438,14 @@ class CompressedDict[K, V](MutableMapping[K, V]):
437
438
  if self._working_dict:
438
439
  return self._working_dict
439
440
  else:
440
- # if the working dict is not None, return it but don't store it in the self._working_dict to keep memory low
441
+ # if the working dict is None, create and return it but don't store it
442
+ # in the self._working_dict to keep memory low
441
443
  return self.create_working_dict()
442
444
 
443
445
  def dict(self) -> OrderedDict[K, V]:
444
446
  """
445
447
  Convert to a FHIR friendly dictionary where the python types like datetime are converted to string versions
448
+ For example, datetime will be represented as a iso format string per FHIR instead of a python datetime object.
446
449
 
447
450
  Returns:
448
451
  FHIR friendly dictionary
@@ -585,6 +588,7 @@ class CompressedDict[K, V](MutableMapping[K, V]):
585
588
  """
586
589
  # Create a new instance with the same storage mode
587
590
  new_instance = CompressedDict(
591
+ # we use raw_dict() instead of dict() so we can preserve python data types like datetime
588
592
  initial_dict=copy.deepcopy(self.raw_dict()),
589
593
  storage_mode=self._storage_mode,
590
594
  properties_to_cache=self._properties_to_cache,
@@ -1,4 +1,4 @@
1
- from datetime import datetime, date
1
+ from datetime import datetime, date, time
2
2
  from decimal import Decimal
3
3
  from typing import Type, Any, Dict, Optional
4
4
  import pytest
@@ -40,7 +40,22 @@ class TestCustomObject:
40
40
  {"__type__": "datetime", "iso": "2023-01-01T00:00:00+00:00"},
41
41
  datetime,
42
42
  ),
43
+ (
44
+ "datetime",
45
+ {
46
+ "__type__": "datetime",
47
+ "iso": "2023-01-01T00:00:00-08:00",
48
+ "tzinfo": "Pacific/Honolulu",
49
+ },
50
+ datetime,
51
+ ),
43
52
  ("date", {"__type__": "date", "iso": "2023-01-01"}, date),
53
+ ("time", {"__type__": "time", "iso": "14:30:15"}, time),
54
+ (
55
+ "time",
56
+ {"__type__": "time", "iso": "14:30:15", "tzinfo": "Pacific/Honolulu"},
57
+ time,
58
+ ),
44
59
  ("decimal", {"__type__": "decimal", "value": "3.14"}, Decimal),
45
60
  ("complex", {"__type__": "complex", "real": 3, "imag": 4}, complex),
46
61
  ("bytes", {"__type__": "bytes", "value": "test"}, bytes),
@@ -1,6 +1,9 @@
1
- from datetime import datetime, timezone, date
1
+ import logging
2
+ from datetime import datetime, timezone, date, time
2
3
  from decimal import Decimal
4
+ from logging import Logger
3
5
  from typing import Type, Any
6
+ from zoneinfo import ZoneInfo
4
7
 
5
8
  import pytest
6
9
 
@@ -24,7 +27,14 @@ class TestCustomObject:
24
27
  "input_type, input_value, expected_type",
25
28
  [
26
29
  (datetime, datetime(2023, 1, 1, tzinfo=timezone.utc), "datetime"),
30
+ (
31
+ datetime,
32
+ datetime(2023, 1, 1, tzinfo=ZoneInfo("Pacific/Honolulu")),
33
+ "datetime",
34
+ ),
27
35
  (date, date(2023, 1, 1), "date"),
36
+ (time, time(14, 30, 15), "time"),
37
+ (time, time(14, 30, 15, tzinfo=ZoneInfo("Pacific/Honolulu")), "time"),
28
38
  (Decimal, Decimal("3.14"), "decimal"),
29
39
  (complex, 3 + 4j, "complex"),
30
40
  (bytes, b"test", "bytes"),
@@ -37,9 +47,11 @@ def test_complex_type_serialization(
37
47
  """
38
48
  Test serialization of various complex types
39
49
  """
50
+ logger: Logger = logging.getLogger(__name__)
40
51
  encoder = TypePreservationEncoder()
41
52
  serialized = encoder.default(input_value)
42
53
 
54
+ logger.info(serialized)
43
55
  assert isinstance(serialized, dict)
44
56
  assert serialized.get("__type__") == expected_type
45
57
 
@@ -1,9 +1,10 @@
1
1
  import logging
2
2
  from collections import OrderedDict
3
- from datetime import datetime, timezone, date
3
+ from datetime import datetime, timezone, date, time
4
4
  from decimal import Decimal
5
5
  from logging import Logger
6
6
  from typing import Any
7
+ from zoneinfo import ZoneInfo
7
8
 
8
9
  from compressedfhir.utilities.json_serializers.type_preservation_serializer import (
9
10
  TypePreservationSerializer,
@@ -26,8 +27,12 @@ def test_complex_data_serialization() -> None:
26
27
  Test serialization and deserialization of complex data
27
28
  """
28
29
  complex_data = {
30
+ "timestamp_no_tz": datetime.now(),
29
31
  "timestamp": datetime.now(timezone.utc),
32
+ "timestamp_pst": datetime.now(ZoneInfo("Pacific/Honolulu")),
30
33
  "today": date.today(),
34
+ "my_time": time(14, 30, 15),
35
+ "my_time_pst": time(14, 30, 15, tzinfo=ZoneInfo("Pacific/Honolulu")),
31
36
  "precise_value": Decimal("3.14159"),
32
37
  "complex_number": 3 + 4j,
33
38
  "byte_data": b"Hello",
@@ -42,13 +47,29 @@ def test_complex_data_serialization() -> None:
42
47
  deserialized = TypePreservationSerializer.deserialize(serialized)
43
48
 
44
49
  # Verify types
50
+ assert isinstance(deserialized, OrderedDict)
51
+ assert isinstance(deserialized["timestamp_no_tz"], datetime)
52
+ assert deserialized["timestamp_no_tz"] == complex_data["timestamp_no_tz"]
45
53
  assert isinstance(deserialized["timestamp"], datetime)
54
+ assert deserialized["timestamp"] == complex_data["timestamp"]
55
+ assert isinstance(deserialized["timestamp_pst"], datetime)
56
+ assert deserialized["timestamp_pst"] == complex_data["timestamp_pst"]
46
57
  assert isinstance(deserialized["today"], date)
58
+ assert deserialized["today"] == complex_data["today"]
59
+ assert isinstance(deserialized["my_time"], time)
60
+ assert deserialized["my_time"] == complex_data["my_time"]
61
+ assert isinstance(deserialized["my_time_pst"], time)
62
+ assert deserialized["my_time_pst"] == complex_data["my_time_pst"]
47
63
  assert isinstance(deserialized["precise_value"], Decimal)
64
+ assert deserialized["precise_value"] == complex_data["precise_value"]
48
65
  assert isinstance(deserialized["complex_number"], complex)
66
+ assert deserialized["complex_number"] == complex_data["complex_number"]
49
67
  assert isinstance(deserialized["byte_data"], bytes)
68
+ assert deserialized["byte_data"] == complex_data["byte_data"]
50
69
  assert isinstance(deserialized["unique_items"], set)
70
+ assert deserialized["unique_items"] == complex_data["unique_items"]
51
71
  assert isinstance(deserialized["custom_obj"], TestCustomObject)
72
+ assert deserialized["custom_obj"] == complex_data["custom_obj"]
52
73
 
53
74
 
54
75
  def test_nested_complex_data() -> None:
@@ -1,9 +1,10 @@
1
1
  import logging
2
2
  from collections import OrderedDict
3
- from datetime import datetime, date
3
+ from datetime import datetime, date, time
4
4
  from decimal import Decimal
5
5
  from logging import Logger
6
6
  from typing import Any, Dict, Callable, Optional, Union, cast, List
7
+ from zoneinfo import ZoneInfo
7
8
 
8
9
 
9
10
  class TypePreservationDecoder:
@@ -46,9 +47,33 @@ class TypePreservationDecoder:
46
47
  return date.fromisoformat(d["iso"])
47
48
  return cast(date, d)
48
49
 
50
+ def time_decoder(d: Union[str, Dict[str, Any]]) -> time:
51
+ if isinstance(d, str):
52
+ return time.fromisoformat(d)
53
+ elif isinstance(d, dict) and "iso" in d:
54
+ # Extract ISO time string
55
+ iso_time: str = d["iso"]
56
+
57
+ # Parse time from ISO format
58
+ parsed_time = time.fromisoformat(iso_time)
59
+
60
+ # Add timezone if specified
61
+ tz_info = d.get("tzinfo")
62
+ if tz_info:
63
+ try:
64
+ tz_aware_time = parsed_time.replace(tzinfo=ZoneInfo(tz_info))
65
+ return tz_aware_time
66
+ except Exception as e:
67
+ raise ValueError(f"Invalid timezone: {tz_info}") from e
68
+ else:
69
+ # If no timezone info, return naive time
70
+ return parsed_time
71
+ return cast(time, d)
72
+
49
73
  default_decoders: Dict[str, Callable[[Any], Any]] = {
50
74
  "datetime": datetime_decoder,
51
75
  "date": date_decoder,
76
+ "time": time_decoder,
52
77
  "decimal": lambda d: Decimal(d["value"] if isinstance(d, dict) else d),
53
78
  "complex": lambda d: complex(d["real"], d["imag"])
54
79
  if isinstance(d, dict)
@@ -1,6 +1,6 @@
1
1
  import json
2
2
  from collections.abc import Callable
3
- from datetime import datetime, date
3
+ from datetime import datetime, date, time
4
4
  from decimal import Decimal
5
5
  from typing import Any, Dict, Type
6
6
 
@@ -17,6 +17,11 @@ class TypePreservationEncoder(json.JSONEncoder):
17
17
  "tzinfo": str(dt.tzinfo) if dt.tzinfo else None,
18
18
  },
19
19
  date: lambda d: {"__type__": "date", "iso": d.isoformat()},
20
+ time: lambda t: {
21
+ "__type__": "time",
22
+ "iso": t.isoformat(),
23
+ "tzinfo": str(t.tzinfo) if t.tzinfo else None,
24
+ },
20
25
  Decimal: lambda d: {"__type__": "decimal", "value": str(d)},
21
26
  complex: lambda c: {"__type__": "complex", "real": c.real, "imag": c.imag},
22
27
  bytes: lambda b: {"__type__": "bytes", "value": b.decode("latin-1")},
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: compressedfhir
3
- Version: 1.0.6
3
+ Version: 1.0.8
4
4
  Summary: Stores FHIR JSON resources in compressed form in memory
5
5
  Home-page: https://github.com/icanbwell/compressed-fhir
6
6
  Author: Imran Qureshi
@@ -1 +0,0 @@
1
- 1.0.6
File without changes
File without changes
File without changes
File without changes
File without changes