canvas 0.3.0__py3-none-any.whl → 0.4.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.

Potentially problematic release.


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

Files changed (108) hide show
  1. {canvas-0.3.0.dist-info → canvas-0.4.0.dist-info}/METADATA +2 -1
  2. canvas-0.4.0.dist-info/RECORD +218 -0
  3. canvas_cli/apps/emit/__init__.py +3 -0
  4. canvas_cli/apps/emit/emit.py +67 -0
  5. canvas_cli/apps/emit/event_fixtures/ALLERGY_INTOLERANCE_CREATED.ndjson +1 -0
  6. canvas_cli/apps/emit/event_fixtures/ALLERGY_INTOLERANCE_UPDATED.ndjson +1 -0
  7. canvas_cli/apps/emit/event_fixtures/APPOINTMENT_CANCELED.ndjson +1 -0
  8. canvas_cli/apps/emit/event_fixtures/APPOINTMENT_CHECKED_IN.ndjson +1 -0
  9. canvas_cli/apps/emit/event_fixtures/APPOINTMENT_CREATED.ndjson +1 -0
  10. canvas_cli/apps/emit/event_fixtures/APPOINTMENT_NO_SHOWED.ndjson +1 -0
  11. canvas_cli/apps/emit/event_fixtures/APPOINTMENT_RESCHEDULED.ndjson +1 -0
  12. canvas_cli/apps/emit/event_fixtures/APPOINTMENT_RESTORED.ndjson +1 -0
  13. canvas_cli/apps/emit/event_fixtures/APPOINTMENT_UPDATED.ndjson +2 -0
  14. canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__CONDITION_SELECTED.ndjson +1 -0
  15. canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__POST_COMMIT.ndjson +3 -0
  16. canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__POST_ORIGINATE.ndjson +4 -0
  17. canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__POST_UPDATE.ndjson +5 -0
  18. canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__PRE_COMMIT.ndjson +3 -0
  19. canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__PRE_ORIGINATE.ndjson +4 -0
  20. canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__PRE_UPDATE.ndjson +5 -0
  21. canvas_cli/apps/emit/event_fixtures/BILLING_LINE_ITEM_CREATED.ndjson +3 -0
  22. canvas_cli/apps/emit/event_fixtures/BILLING_LINE_ITEM_UPDATED.ndjson +2 -0
  23. canvas_cli/apps/emit/event_fixtures/CONDITION_ASSESSED.ndjson +2 -0
  24. canvas_cli/apps/emit/event_fixtures/CONDITION_CREATED.ndjson +4 -0
  25. canvas_cli/apps/emit/event_fixtures/CONDITION_UPDATED.ndjson +5 -0
  26. canvas_cli/apps/emit/event_fixtures/CRON.ndjson +3 -0
  27. canvas_cli/apps/emit/event_fixtures/ENCOUNTER_CREATED.ndjson +3 -0
  28. canvas_cli/apps/emit/event_fixtures/ENCOUNTER_UPDATED.ndjson +2 -0
  29. canvas_cli/apps/emit/event_fixtures/IMMUNIZATION_CREATED.ndjson +1 -0
  30. canvas_cli/apps/emit/event_fixtures/IMMUNIZATION_STATEMENT_CREATED.ndjson +1 -0
  31. canvas_cli/apps/emit/event_fixtures/IMMUNIZATION_STATEMENT_UPDATED.ndjson +1 -0
  32. canvas_cli/apps/emit/event_fixtures/IMMUNIZATION_UPDATED.ndjson +1 -0
  33. canvas_cli/apps/emit/event_fixtures/INTERVIEW_CREATED.ndjson +1 -0
  34. canvas_cli/apps/emit/event_fixtures/INTERVIEW_UPDATED.ndjson +1 -0
  35. canvas_cli/apps/emit/event_fixtures/LAB_ORDER_CREATED.ndjson +1 -0
  36. canvas_cli/apps/emit/event_fixtures/LAB_ORDER_UPDATED.ndjson +1 -0
  37. canvas_cli/apps/emit/event_fixtures/MEDICATION_LIST_ITEM_CREATED.ndjson +1 -0
  38. canvas_cli/apps/emit/event_fixtures/MEDICATION_LIST_ITEM_UPDATED.ndjson +1 -0
  39. canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__POST_COMMIT.ndjson +1 -0
  40. canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__POST_ORIGINATE.ndjson +1 -0
  41. canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__POST_UPDATE.ndjson +2 -0
  42. canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__PRE_COMMIT.ndjson +1 -0
  43. canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__PRE_ORIGINATE.ndjson +1 -0
  44. canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__PRE_UPDATE.ndjson +2 -0
  45. canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT__MEDICATION__POST_SEARCH.ndjson +2 -0
  46. canvas_cli/apps/emit/event_fixtures/PATIENT_CREATED.ndjson +1 -0
  47. canvas_cli/apps/emit/event_fixtures/PATIENT_UPDATED.ndjson +1 -0
  48. canvas_cli/apps/emit/event_fixtures/PLAN_COMMAND__POST_ORIGINATE.ndjson +1 -0
  49. canvas_cli/apps/emit/event_fixtures/PLAN_COMMAND__PRE_ORIGINATE.ndjson +1 -0
  50. canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__POST_COMMIT.ndjson +1 -0
  51. canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__POST_ORIGINATE.ndjson +1 -0
  52. canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__POST_UPDATE.ndjson +2 -0
  53. canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__PRE_COMMIT.ndjson +1 -0
  54. canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__PRE_ORIGINATE.ndjson +1 -0
  55. canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__PRE_UPDATE.ndjson +2 -0
  56. canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE__QUESTIONNAIRE__POST_SEARCH.ndjson +4 -0
  57. canvas_cli/apps/emit/event_fixtures/TASK_COMMENT_CREATED.ndjson +1 -0
  58. canvas_cli/apps/emit/event_fixtures/TASK_CREATED.ndjson +1 -0
  59. canvas_cli/apps/emit/event_fixtures/TASK_UPDATED.ndjson +1 -0
  60. canvas_cli/apps/emit/event_fixtures/VITAL_SIGN_CREATED.ndjson +14 -0
  61. canvas_cli/apps/emit/event_fixtures/VITAL_SIGN_UPDATED.ndjson +364 -0
  62. canvas_cli/apps/logs/logs.py +6 -6
  63. canvas_cli/apps/plugin/plugin.py +11 -7
  64. canvas_cli/apps/run_plugins/__init__.py +3 -0
  65. canvas_cli/apps/run_plugins/run_plugins.py +16 -0
  66. canvas_cli/main.py +8 -38
  67. canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/README.md +0 -1
  68. canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/protocols/my_protocol.py +1 -1
  69. canvas_cli/tests.py +12 -5
  70. canvas_cli/utils/context/context.py +2 -2
  71. canvas_cli/utils/context/tests.py +5 -4
  72. canvas_cli/utils/print/print.py +1 -1
  73. canvas_cli/utils/print/tests.py +2 -3
  74. canvas_generated/messages/events_pb2.py +2 -2
  75. canvas_generated/messages/events_pb2.pyi +12 -0
  76. canvas_sdk/base.py +2 -1
  77. canvas_sdk/commands/base.py +25 -25
  78. canvas_sdk/commands/tests/protocol/tests.py +5 -3
  79. canvas_sdk/commands/tests/test_utils.py +8 -44
  80. canvas_sdk/commands/tests/unit/tests.py +3 -3
  81. canvas_sdk/data/client.py +1 -1
  82. canvas_sdk/effects/banner_alert/tests.py +12 -4
  83. canvas_sdk/effects/protocol_card/protocol_card.py +1 -1
  84. canvas_sdk/effects/protocol_card/tests.py +2 -2
  85. canvas_sdk/protocols/clinical_quality_measure.py +1 -0
  86. canvas_sdk/utils/http.py +2 -2
  87. canvas_sdk/v1/data/base.py +1 -1
  88. canvas_sdk/v1/data/command.py +27 -0
  89. canvas_sdk/v1/data/common.py +46 -0
  90. canvas_sdk/v1/data/device.py +44 -0
  91. canvas_sdk/v1/data/imaging.py +102 -0
  92. canvas_sdk/v1/data/lab.py +182 -10
  93. canvas_sdk/v1/data/observation.py +117 -0
  94. canvas_sdk/v1/data/patient.py +4 -1
  95. canvas_sdk/v1/data/questionnaire.py +4 -2
  96. canvas_sdk/value_set/tests/test_value_sets.py +9 -6
  97. canvas_sdk/value_set/v2022/intervention.py +0 -24
  98. canvas_sdk/value_set/value_set.py +24 -21
  99. plugin_runner/__init__.py +0 -0
  100. plugin_runner/authentication.py +48 -0
  101. plugin_runner/plugin_runner.py +389 -0
  102. plugin_runner/plugin_synchronizer.py +87 -0
  103. plugin_runner/sandbox.py +273 -0
  104. pubsub/__init__.py +0 -0
  105. pubsub/pubsub.py +38 -0
  106. canvas-0.3.0.dist-info/RECORD +0 -145
  107. {canvas-0.3.0.dist-info → canvas-0.4.0.dist-info}/WHEEL +0 -0
  108. {canvas-0.3.0.dist-info → canvas-0.4.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,117 @@
1
+ from django.db import models
2
+
3
+ from canvas_sdk.v1.data.base import CommittableModelManager, ValueSetLookupQuerySet
4
+ from canvas_sdk.v1.data.patient import Patient
5
+ from canvas_sdk.v1.data.user import CanvasUser
6
+
7
+
8
+ class ObservationQuerySet(ValueSetLookupQuerySet):
9
+ """ObservationQuerySet."""
10
+
11
+ pass
12
+
13
+
14
+ class Observation(models.Model):
15
+ """Observation."""
16
+
17
+ class Meta:
18
+ managed = False
19
+ app_label = "canvas_sdk"
20
+ db_table = "canvas_sdk_data_api_observation_001"
21
+
22
+ objects = CommittableModelManager.from_queryset(ObservationQuerySet)()
23
+
24
+ id = models.UUIDField()
25
+ dbid = models.BigIntegerField(primary_key=True)
26
+ created = models.DateTimeField()
27
+ modified = models.DateTimeField()
28
+ originator = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
29
+ committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
30
+ entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
31
+ deleted = models.BooleanField()
32
+ patient = models.ForeignKey(Patient, on_delete=models.DO_NOTHING, related_name="observations")
33
+ is_member_of = models.ForeignKey(
34
+ "self", on_delete=models.DO_NOTHING, null=True, related_name="members"
35
+ )
36
+ category = models.CharField()
37
+ units = models.TextField()
38
+ value = models.TextField()
39
+ note_id = models.BigIntegerField()
40
+ name = models.TextField()
41
+ effective_datetime = models.DateTimeField()
42
+
43
+
44
+ class ObservationCoding(models.Model):
45
+ """ObservationCoding."""
46
+
47
+ class Meta:
48
+ managed = False
49
+ app_label = "canvas_sdk"
50
+ db_table = "canvas_sdk_data_api_observationcoding_001"
51
+
52
+ dbid = models.BigIntegerField(primary_key=True)
53
+ system = models.CharField()
54
+ version = models.CharField()
55
+ code = models.CharField()
56
+ display = models.CharField()
57
+ user_selected = models.BooleanField()
58
+ observation = models.ForeignKey(
59
+ Observation, on_delete=models.DO_NOTHING, related_name="codings"
60
+ )
61
+
62
+
63
+ class ObservationComponent(models.Model):
64
+ """ObservationComponent."""
65
+
66
+ class Meta:
67
+ managed = False
68
+ app_label = "canvas_sdk"
69
+ db_table = "canvas_sdk_data_api_observationcomponent_001"
70
+
71
+ dbid = models.BigIntegerField(primary_key=True)
72
+ created = models.DateTimeField()
73
+ modified = models.DateTimeField()
74
+ observation = models.ForeignKey(
75
+ Observation, on_delete=models.DO_NOTHING, related_name="components"
76
+ )
77
+ value_quantity = models.TextField()
78
+ value_quantity_unit = models.TextField()
79
+ name = models.TextField()
80
+
81
+
82
+ class ObservationComponentCoding(models.Model):
83
+ """ObservationComponentCoding."""
84
+
85
+ class Meta:
86
+ managed = False
87
+ app_label = "canvas_sdk"
88
+ db_table = "canvas_sdk_data_api_observationcomponentcoding_001"
89
+
90
+ dbid = models.BigIntegerField(primary_key=True)
91
+ system = models.CharField()
92
+ version = models.CharField()
93
+ code = models.CharField()
94
+ display = models.CharField()
95
+ user_selected = models.BooleanField()
96
+ observation_component = models.ForeignKey(
97
+ ObservationComponent, on_delete=models.DO_NOTHING, related_name="codings"
98
+ )
99
+
100
+
101
+ class ObservationValueCoding(models.Model):
102
+ """ObservationValueCoding."""
103
+
104
+ class Meta:
105
+ managed = False
106
+ app_label = "canvas_sdk"
107
+ db_table = "canvas_sdk_data_api_observationvaluecoding_001"
108
+
109
+ dbid = models.BigIntegerField(primary_key=True)
110
+ system = models.CharField()
111
+ version = models.CharField()
112
+ code = models.CharField()
113
+ display = models.CharField()
114
+ user_selected = models.BooleanField()
115
+ observation = models.ForeignKey(
116
+ Observation, on_delete=models.DO_NOTHING, related_name="value_codings"
117
+ )
@@ -49,4 +49,7 @@ class Patient(models.Model):
49
49
  @classmethod
50
50
  def find(cls, id: str) -> Self:
51
51
  """Find a patient by id."""
52
- return cls.objects.get(id=id)
52
+ return cls._default_manager.get(id=id)
53
+
54
+ def __str__(self) -> str:
55
+ return f"{self.first_name} {self.last_name}"
@@ -109,7 +109,7 @@ class Questionnaire(models.Model):
109
109
  code_system = models.CharField()
110
110
  code = models.CharField()
111
111
  search_tags = models.CharField()
112
- questions = models.ManyToManyField(Question, through="QuestionnaireQuestionMap")
112
+ questions = models.ManyToManyField(Question, through="canvas_sdk.QuestionnaireQuestionMap") # type: ignore[misc, var-annotated]
113
113
  use_in_shx = models.BooleanField()
114
114
  carry_forward = models.TextField()
115
115
 
@@ -152,7 +152,9 @@ class Interview(models.Model):
152
152
  patient = models.ForeignKey(Patient, on_delete=models.DO_NOTHING, related_name="interviews")
153
153
  note_id = models.BigIntegerField()
154
154
  appointment_id = models.BigIntegerField()
155
- questionnaires = models.ManyToManyField(Questionnaire, through="InterviewQuestionnaireMap")
155
+ questionnaires = models.ManyToManyField( # type: ignore[var-annotated]
156
+ Questionnaire, through="canvas_sdk.InterviewQuestionnaireMap" # type: ignore[misc]
157
+ )
156
158
  progress_status = models.CharField()
157
159
  created = models.DateTimeField()
158
160
  modified = models.DateTimeField()
@@ -1,11 +1,10 @@
1
- import pytest
2
-
3
1
  from canvas_sdk.value_set.v2022.condition import (
4
2
  DisordersOfTheImmuneSystem,
5
3
  EncephalopathyDueToChildhoodVaccination,
6
4
  Rhabdomyolysis,
7
5
  StableAndUnstableAngina,
8
6
  )
7
+ from canvas_sdk.value_set.value_set import CombinedValueSet
9
8
 
10
9
 
11
10
  def test_value_set_class_values_property() -> None:
@@ -15,7 +14,9 @@ def test_value_set_class_values_property() -> None:
15
14
 
16
15
 
17
16
  def test_value_set_class_pipe_operator_with_two_value_sets() -> None:
18
- combined_value_set = DisordersOfTheImmuneSystem | EncephalopathyDueToChildhoodVaccination
17
+ combined_value_set: CombinedValueSet = (
18
+ DisordersOfTheImmuneSystem | EncephalopathyDueToChildhoodVaccination
19
+ )
19
20
 
20
21
  both_classes_icd_10_codes = DisordersOfTheImmuneSystem.ICD10CM.union(
21
22
  EncephalopathyDueToChildhoodVaccination.ICD10CM
@@ -29,7 +30,7 @@ def test_value_set_class_pipe_operator_with_two_value_sets() -> None:
29
30
 
30
31
 
31
32
  def test_value_set_class_pipe_operator_with_three_value_sets() -> None:
32
- combined_value_set = (
33
+ combined_value_set: CombinedValueSet = (
33
34
  DisordersOfTheImmuneSystem | EncephalopathyDueToChildhoodVaccination | Rhabdomyolysis
34
35
  )
35
36
 
@@ -45,8 +46,10 @@ def test_value_set_class_pipe_operator_with_three_value_sets() -> None:
45
46
 
46
47
 
47
48
  def test_value_set_class_pipe_operator_with_two_combined_value_sets() -> None:
48
- combined_value_set_1 = DisordersOfTheImmuneSystem | EncephalopathyDueToChildhoodVaccination
49
- combined_value_set_2 = Rhabdomyolysis | StableAndUnstableAngina
49
+ combined_value_set_1: CombinedValueSet = (
50
+ DisordersOfTheImmuneSystem | EncephalopathyDueToChildhoodVaccination
51
+ )
52
+ combined_value_set_2: CombinedValueSet = Rhabdomyolysis | StableAndUnstableAngina
50
53
 
51
54
  combined_value_set = combined_value_set_1 | combined_value_set_2
52
55
 
@@ -1,30 +1,6 @@
1
1
  from ..value_set import ValueSet
2
2
 
3
3
 
4
- class HospiceCareAmbulatory(ValueSet):
5
- """
6
- **Clinical Focus:** The purpose of this value set is to represent concepts of interventions to identify patients receiving hospice care outside of a hospital or long term care facility.
7
-
8
- **Data Element Scope:** This value set may use a model element related to Procedure or Intervention.
9
-
10
- **Inclusion Criteria:** Includes concepts that represent a procedure or intervention for hospice care.
11
-
12
- **Exclusion Criteria:** Excludes concepts that represent palliative care or comfort measures.
13
-
14
- ** Used in:** CMS90v11, CMS134v10, CMS165v10, CMS146v10, CMS124v10, CMS139v10, CMS154v10, CMS56v10, CMS74v11, CMS75v10, CMS137v10, CMS136v11, CMS128v10, CMS122v10, CMS153v10, CMS66v10, CMS130v10, CMS155v10, CMS127v10, CMS117v10, CMS131v10, CMS156v10, CMS125v10
15
- """
16
-
17
- VALUE_SET_NAME = "Hospice care ambulatory"
18
- OID = "2.16.840.1.113762.1.4.1108.15"
19
- DEFINITION_VERSION = "20170504"
20
- EXPANSION_VERSION = "eCQM Update 2021-05-06"
21
-
22
- SNOMEDCT = {
23
- "385763009", # Hospice care (regime/therapy)
24
- "385765002", # Hospice care management (procedure)
25
- }
26
-
27
-
28
4
  class PalliativeCareIntervention(ValueSet):
29
5
  """
30
6
  **Clinical Focus:** The purpose of this value set is to represent concepts for palliative care interventions.
@@ -1,5 +1,7 @@
1
1
  from collections import defaultdict
2
- from typing import Dict, Union, cast
2
+ from typing import Union, cast
3
+
4
+ from django.utils.functional import classproperty
3
5
 
4
6
 
5
7
  class CodeConstants:
@@ -33,7 +35,7 @@ class CodeConstants:
33
35
  URL_NDC = "http://hl7.org/fhir/sid/ndc"
34
36
 
35
37
 
36
- class CodeConstantsURLMapping:
38
+ class CodeConstantsURLMappingMixin:
37
39
  """A class that maps code systems to their URLs."""
38
40
 
39
41
  CODE_SYSTEM_MAPPING = {
@@ -53,21 +55,21 @@ class CodeConstantsURLMapping:
53
55
  }
54
56
 
55
57
 
56
- class CombinedValueSet(CodeConstantsURLMapping):
58
+ class CombinedValueSet(CodeConstantsURLMappingMixin):
57
59
  """A class representing a combination of two value sets."""
58
60
 
59
61
  def __init__(
60
62
  self,
61
- value_set_1: Union["ValueSet", "CombinedValueSet"],
62
- value_set_2: Union["ValueSet", "CombinedValueSet"],
63
+ value_set_1: Union[type["ValueSet"], "CombinedValueSet"],
64
+ value_set_2: Union[type["ValueSet"], "CombinedValueSet"],
63
65
  ) -> None:
64
66
  self.value_set_1 = value_set_1
65
67
  self.value_set_2 = value_set_2
66
68
 
67
69
  @property
68
- def values(self) -> Dict[str, set]:
70
+ def values(self) -> dict[str, set]:
69
71
  """A property that returns the combined values from both value sets."""
70
- values: Dict[str, set] = defaultdict(set)
72
+ values: dict[str, set] = defaultdict(set)
71
73
 
72
74
  for vs in [self.value_set_1, self.value_set_2]:
73
75
  sub_values = vs.values
@@ -77,7 +79,7 @@ class CombinedValueSet(CodeConstantsURLMapping):
77
79
 
78
80
  return values
79
81
 
80
- def __or__(self, value_set: Union["ValueSet", "CombinedValueSet"]) -> "CombinedValueSet":
82
+ def __or__(self, value_set: Union[type["ValueSet"], "CombinedValueSet"]) -> "CombinedValueSet":
81
83
  """Implements the `|` (or) operator to combine value sets."""
82
84
  return CombinedValueSet(self, value_set)
83
85
 
@@ -85,22 +87,23 @@ class CombinedValueSet(CodeConstantsURLMapping):
85
87
  class ValueSystems(type):
86
88
  """A metaclass for defining a ValueSet."""
87
89
 
88
- @property
89
- def values(cls) -> dict[str, set]:
90
- """A property that returns a dictionary of code systems and their associated values."""
91
- return {
92
- system: getattr(cls, system)
93
- for system in cast(ValueSet, cls).CODE_SYSTEM_MAPPING.keys()
94
- if hasattr(cls, system)
95
- }
90
+ def __or__(self, value_set: Union[type["ValueSet"], "CombinedValueSet"]) -> "CombinedValueSet": # type: ignore[override]
91
+ """Implements the `|` (or) operator."""
92
+ return CombinedValueSet(cast(type["ValueSet"], self), value_set)
96
93
 
97
- def __or__(self, value_set: Union["ValueSet", "CombinedValueSet"]) -> CombinedValueSet: # type: ignore[override]
94
+ def __ror__(self, value_set: Union[type["ValueSet"], "CombinedValueSet"]) -> "CombinedValueSet": # type: ignore[override]
98
95
  """Implements the `|` (or) operator."""
99
- return CombinedValueSet(cast(ValueSet, self), value_set)
96
+ return self.__or__(value_set)
100
97
 
101
98
 
102
- class ValueSet(CodeConstantsURLMapping, metaclass=ValueSystems):
99
+ class ValueSet(CodeConstantsURLMappingMixin, metaclass=ValueSystems):
103
100
  """The Base class for a ValueSet."""
104
101
 
105
- values: dict[str, set]
106
- pass
102
+ @classproperty
103
+ def values(cls) -> dict[str, set]:
104
+ """A property that returns a dictionary of code systems and their associated values."""
105
+ return {
106
+ system: getattr(cls, system)
107
+ for system in cls.CODE_SYSTEM_MAPPING.keys()
108
+ if hasattr(cls, system)
109
+ }
File without changes
@@ -0,0 +1,48 @@
1
+ import os
2
+ from typing import cast
3
+
4
+ import arrow
5
+ from jwt import encode
6
+
7
+ from logger import log
8
+
9
+ ONE_DAY_IN_MINUTES = 60 * 24
10
+
11
+ INSECURE_DEFAULT_SIGNING_KEY = "INSECURE_KEY"
12
+
13
+
14
+ def token_for_plugin(
15
+ plugin_name: str,
16
+ audience: str,
17
+ issuer: str = "plugin-runner",
18
+ jwt_signing_key: str = cast(
19
+ str, os.getenv("PLUGIN_RUNNER_SIGNING_KEY", INSECURE_DEFAULT_SIGNING_KEY)
20
+ ),
21
+ expiration_minutes: int = ONE_DAY_IN_MINUTES,
22
+ extra_kwargs: dict | None = None,
23
+ ) -> str:
24
+ """
25
+ Generate a JWT for the given plugin and audience.
26
+ """
27
+ if not extra_kwargs:
28
+ extra_kwargs = {}
29
+
30
+ if jwt_signing_key == INSECURE_DEFAULT_SIGNING_KEY:
31
+ log.warning(
32
+ "Using an insecure JWT signing key for GraphQL access. Set the PLUGIN_RUNNER_SIGNING_KEY environment variable to avoid this message."
33
+ )
34
+
35
+ token = encode(
36
+ {
37
+ "plugin_name": plugin_name,
38
+ "customer_identifier": os.getenv("CUSTOMER_IDENTIFIER"),
39
+ "exp": arrow.utcnow().shift(minutes=expiration_minutes).datetime,
40
+ "aud": audience,
41
+ "iss": issuer,
42
+ **extra_kwargs,
43
+ },
44
+ jwt_signing_key,
45
+ algorithm="HS256",
46
+ )
47
+
48
+ return token