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.
- {canvas-0.3.0.dist-info → canvas-0.4.0.dist-info}/METADATA +2 -1
- canvas-0.4.0.dist-info/RECORD +218 -0
- canvas_cli/apps/emit/__init__.py +3 -0
- canvas_cli/apps/emit/emit.py +67 -0
- canvas_cli/apps/emit/event_fixtures/ALLERGY_INTOLERANCE_CREATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/ALLERGY_INTOLERANCE_UPDATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/APPOINTMENT_CANCELED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/APPOINTMENT_CHECKED_IN.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/APPOINTMENT_CREATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/APPOINTMENT_NO_SHOWED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/APPOINTMENT_RESCHEDULED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/APPOINTMENT_RESTORED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/APPOINTMENT_UPDATED.ndjson +2 -0
- canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__CONDITION_SELECTED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__POST_COMMIT.ndjson +3 -0
- canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__POST_ORIGINATE.ndjson +4 -0
- canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__POST_UPDATE.ndjson +5 -0
- canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__PRE_COMMIT.ndjson +3 -0
- canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__PRE_ORIGINATE.ndjson +4 -0
- canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__PRE_UPDATE.ndjson +5 -0
- canvas_cli/apps/emit/event_fixtures/BILLING_LINE_ITEM_CREATED.ndjson +3 -0
- canvas_cli/apps/emit/event_fixtures/BILLING_LINE_ITEM_UPDATED.ndjson +2 -0
- canvas_cli/apps/emit/event_fixtures/CONDITION_ASSESSED.ndjson +2 -0
- canvas_cli/apps/emit/event_fixtures/CONDITION_CREATED.ndjson +4 -0
- canvas_cli/apps/emit/event_fixtures/CONDITION_UPDATED.ndjson +5 -0
- canvas_cli/apps/emit/event_fixtures/CRON.ndjson +3 -0
- canvas_cli/apps/emit/event_fixtures/ENCOUNTER_CREATED.ndjson +3 -0
- canvas_cli/apps/emit/event_fixtures/ENCOUNTER_UPDATED.ndjson +2 -0
- canvas_cli/apps/emit/event_fixtures/IMMUNIZATION_CREATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/IMMUNIZATION_STATEMENT_CREATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/IMMUNIZATION_STATEMENT_UPDATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/IMMUNIZATION_UPDATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/INTERVIEW_CREATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/INTERVIEW_UPDATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/LAB_ORDER_CREATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/LAB_ORDER_UPDATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/MEDICATION_LIST_ITEM_CREATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/MEDICATION_LIST_ITEM_UPDATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__POST_COMMIT.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__POST_ORIGINATE.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__POST_UPDATE.ndjson +2 -0
- canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__PRE_COMMIT.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__PRE_ORIGINATE.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__PRE_UPDATE.ndjson +2 -0
- canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT__MEDICATION__POST_SEARCH.ndjson +2 -0
- canvas_cli/apps/emit/event_fixtures/PATIENT_CREATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/PATIENT_UPDATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/PLAN_COMMAND__POST_ORIGINATE.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/PLAN_COMMAND__PRE_ORIGINATE.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__POST_COMMIT.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__POST_ORIGINATE.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__POST_UPDATE.ndjson +2 -0
- canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__PRE_COMMIT.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__PRE_ORIGINATE.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__PRE_UPDATE.ndjson +2 -0
- canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE__QUESTIONNAIRE__POST_SEARCH.ndjson +4 -0
- canvas_cli/apps/emit/event_fixtures/TASK_COMMENT_CREATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/TASK_CREATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/TASK_UPDATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/VITAL_SIGN_CREATED.ndjson +14 -0
- canvas_cli/apps/emit/event_fixtures/VITAL_SIGN_UPDATED.ndjson +364 -0
- canvas_cli/apps/logs/logs.py +6 -6
- canvas_cli/apps/plugin/plugin.py +11 -7
- canvas_cli/apps/run_plugins/__init__.py +3 -0
- canvas_cli/apps/run_plugins/run_plugins.py +16 -0
- canvas_cli/main.py +8 -38
- canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/README.md +0 -1
- canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/protocols/my_protocol.py +1 -1
- canvas_cli/tests.py +12 -5
- canvas_cli/utils/context/context.py +2 -2
- canvas_cli/utils/context/tests.py +5 -4
- canvas_cli/utils/print/print.py +1 -1
- canvas_cli/utils/print/tests.py +2 -3
- canvas_generated/messages/events_pb2.py +2 -2
- canvas_generated/messages/events_pb2.pyi +12 -0
- canvas_sdk/base.py +2 -1
- canvas_sdk/commands/base.py +25 -25
- canvas_sdk/commands/tests/protocol/tests.py +5 -3
- canvas_sdk/commands/tests/test_utils.py +8 -44
- canvas_sdk/commands/tests/unit/tests.py +3 -3
- canvas_sdk/data/client.py +1 -1
- canvas_sdk/effects/banner_alert/tests.py +12 -4
- canvas_sdk/effects/protocol_card/protocol_card.py +1 -1
- canvas_sdk/effects/protocol_card/tests.py +2 -2
- canvas_sdk/protocols/clinical_quality_measure.py +1 -0
- canvas_sdk/utils/http.py +2 -2
- canvas_sdk/v1/data/base.py +1 -1
- canvas_sdk/v1/data/command.py +27 -0
- canvas_sdk/v1/data/common.py +46 -0
- canvas_sdk/v1/data/device.py +44 -0
- canvas_sdk/v1/data/imaging.py +102 -0
- canvas_sdk/v1/data/lab.py +182 -10
- canvas_sdk/v1/data/observation.py +117 -0
- canvas_sdk/v1/data/patient.py +4 -1
- canvas_sdk/v1/data/questionnaire.py +4 -2
- canvas_sdk/value_set/tests/test_value_sets.py +9 -6
- canvas_sdk/value_set/v2022/intervention.py +0 -24
- canvas_sdk/value_set/value_set.py +24 -21
- plugin_runner/__init__.py +0 -0
- plugin_runner/authentication.py +48 -0
- plugin_runner/plugin_runner.py +389 -0
- plugin_runner/plugin_synchronizer.py +87 -0
- plugin_runner/sandbox.py +273 -0
- pubsub/__init__.py +0 -0
- pubsub/pubsub.py +38 -0
- canvas-0.3.0.dist-info/RECORD +0 -145
- {canvas-0.3.0.dist-info → canvas-0.4.0.dist-info}/WHEEL +0 -0
- {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
|
+
)
|
canvas_sdk/v1/data/patient.py
CHANGED
|
@@ -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.
|
|
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(
|
|
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 =
|
|
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 =
|
|
49
|
-
|
|
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
|
|
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
|
|
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(
|
|
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) ->
|
|
70
|
+
def values(self) -> dict[str, set]:
|
|
69
71
|
"""A property that returns the combined values from both value sets."""
|
|
70
|
-
values:
|
|
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
|
-
|
|
89
|
-
|
|
90
|
-
""
|
|
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
|
|
94
|
+
def __ror__(self, value_set: Union[type["ValueSet"], "CombinedValueSet"]) -> "CombinedValueSet": # type: ignore[override]
|
|
98
95
|
"""Implements the `|` (or) operator."""
|
|
99
|
-
return
|
|
96
|
+
return self.__or__(value_set)
|
|
100
97
|
|
|
101
98
|
|
|
102
|
-
class ValueSet(
|
|
99
|
+
class ValueSet(CodeConstantsURLMappingMixin, metaclass=ValueSystems):
|
|
103
100
|
"""The Base class for a ValueSet."""
|
|
104
101
|
|
|
105
|
-
|
|
106
|
-
|
|
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
|