clear-skies 1.18.3__py3-none-any.whl → 1.18.5__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 clear-skies might be problematic. Click here for more details.
- {clear_skies-1.18.3.dist-info → clear_skies-1.18.5.dist-info}/METADATA +1 -1
- {clear_skies-1.18.3.dist-info → clear_skies-1.18.5.dist-info}/RECORD +13 -13
- clearskies/authentication/__init__.py +4 -0
- clearskies/authentication/auth0_jwks.py +0 -1
- clearskies/column_types/column.py +6 -0
- clearskies/column_types/datetime.py +41 -0
- clearskies/columns.py +16 -11
- clearskies/handlers/create.py +1 -1
- clearskies/handlers/input_processing.py +4 -2
- clearskies/handlers/update.py +1 -1
- clearskies/model.py +16 -5
- {clear_skies-1.18.3.dist-info → clear_skies-1.18.5.dist-info}/LICENSE +0 -0
- {clear_skies-1.18.3.dist-info → clear_skies-1.18.5.dist-info}/WHEEL +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
clearskies/__init__.py,sha256=Iz_VxSgiqM6VtGXoUsB_yVKFy_uWvcf071w803wJ8EE,832
|
|
2
2
|
clearskies/application.py,sha256=_gYGIUGdVE5fAS9dwxRZ1gDpDjqGo7-twVt_VxI6XVE,966
|
|
3
|
-
clearskies/authentication/__init__.py,sha256=
|
|
4
|
-
clearskies/authentication/auth0_jwks.py,sha256=
|
|
3
|
+
clearskies/authentication/__init__.py,sha256=sAU6m9c8cJECfLa-hY-BxsSk5FVLb5Dvphb5u6AmULA,710
|
|
4
|
+
clearskies/authentication/auth0_jwks.py,sha256=bzqNaEoG_iPndwttRXuaKpgkDtgOCLAooyifl0I0ACI,4447
|
|
5
5
|
clearskies/authentication/auth_exception.py,sha256=8Tay3Sim2K8vAZ6ldisSJyRyN0cwX7iyGHwfglSKW_A,41
|
|
6
6
|
clearskies/authentication/authorization.py,sha256=eLzBrXMNr1gYoIBZTd8I6uH3R0CfMMjhvimkJt4Amrs,601
|
|
7
7
|
clearskies/authentication/jwks.py,sha256=JsBG4U7eGoKO75CV6J39d91lrVWtjVn6n8fN9RpCYEc,2811
|
|
@@ -59,12 +59,12 @@ clearskies/column_types/audit.py,sha256=meDFV0s4u9i6UojN5f6EQk_kh-nGP8xPscCRa2Nd
|
|
|
59
59
|
clearskies/column_types/belongs_to.py,sha256=dWY5AYgvn4ZDgsKVnILbQKCiYrJNOb-FBuzl--DkZas,10827
|
|
60
60
|
clearskies/column_types/boolean.py,sha256=1yyM1CUfgD84pPE65c1OP1Qjf_J0Z45hjPrDR51AUkQ,1878
|
|
61
61
|
clearskies/column_types/category_tree.py,sha256=PgNmzZPyqYS5NADH_QTCxLvDXZFxzv5ESKTkvPrrLXo,9140
|
|
62
|
-
clearskies/column_types/column.py,sha256=
|
|
62
|
+
clearskies/column_types/column.py,sha256=TCGqtsCEYJr6BHs-PS1yFoUHGIwcx5oTujytNkTAcrk,13243
|
|
63
63
|
clearskies/column_types/created.py,sha256=R8P3egUb7JEHoU_NtbmN9OIwBUHQ0XFi1GoAb5RpSkI,339
|
|
64
64
|
clearskies/column_types/created_by_authorization_data.py,sha256=TBcALV3uchur2Aq9JCRCAihjZrZKc95VZJSIYgY3Ve0,557
|
|
65
65
|
clearskies/column_types/created_by_ip.py,sha256=wwCUoEwHEVGN89x4xP7NJ6QR85Aum6v3JmxofoQrqtg,395
|
|
66
66
|
clearskies/column_types/created_by_user_agent.py,sha256=sSYDRrqSjsCwcYlhF_s9NO-iDww3PaH6aO2ATp_SKGQ,419
|
|
67
|
-
clearskies/column_types/datetime.py,sha256=
|
|
67
|
+
clearskies/column_types/datetime.py,sha256=MuVaeI6FMgevTdgv6djZjlHogs72TC1HTuYdw_6MF2M,3824
|
|
68
68
|
clearskies/column_types/email.py,sha256=KjnncTdacaFWFSNItNRhUm9euyWhKck0Y6rHT5NqPIM,408
|
|
69
69
|
clearskies/column_types/float.py,sha256=j8jJeBueSOusPtAFCWgLHYBncfLnqT1U7bh1zcAkYiA,1332
|
|
70
70
|
clearskies/column_types/has_many.py,sha256=Z4oM1g2dQx6H9171c52FLC41nLryCOKmh51I75mYmmY,5895
|
|
@@ -76,7 +76,7 @@ clearskies/column_types/select.py,sha256=1oBslTJ_7QCjlFeEcwJVRL-ED4sXwCESVFRAOon
|
|
|
76
76
|
clearskies/column_types/string.py,sha256=XbHC31TmlW0k86cvdVJBDyowU8Xis6Te6R0rPLXgLpI,863
|
|
77
77
|
clearskies/column_types/updated.py,sha256=ZAHTHZtKbZQE_JwZ2wMwAUSr4PUYNscy8SwzZGko8hU,290
|
|
78
78
|
clearskies/column_types/uuid.py,sha256=pA6Cd-1QSRuUpz0PxWAGRdG01hW7bpIicOhhJvAvDkQ,711
|
|
79
|
-
clearskies/columns.py,sha256=
|
|
79
|
+
clearskies/columns.py,sha256=3PgLopL1l20vVWaUqOJkwXMr06a-gFHEsbExfOWVB4I,5925
|
|
80
80
|
clearskies/condition_parser.py,sha256=ZMXWbHH5jnPo1-mRIo_uU4IzYNllXiOu9rsD7Ab2A-A,6452
|
|
81
81
|
clearskies/contexts/__init__.py,sha256=wKNK-SKuAEf7aJ3qX6UUzIbUfJIBSIHCI7cLXZTGGC0,179
|
|
82
82
|
clearskies/contexts/bash.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -122,7 +122,7 @@ clearskies/handlers/__init__.py,sha256=YIQeKkkFhXwn7Rcc7Qllh2RGkKB0nDjt1nwowqEuJ
|
|
|
122
122
|
clearskies/handlers/advanced_search.py,sha256=aB6DaMIsms6luVPQLhPwV9sBTOyh4ip_gi-0l_52YLE,12934
|
|
123
123
|
clearskies/handlers/base.py,sha256=K_6-HupAAjmVb9pusjit0aRM3VtF63YCLMT4a_ZKM2Q,22888
|
|
124
124
|
clearskies/handlers/callable.py,sha256=RxDPBuk1socPQvPhuKhCiidhAnXXLdSdG0sVtNAmi8c,8001
|
|
125
|
-
clearskies/handlers/create.py,sha256=
|
|
125
|
+
clearskies/handlers/create.py,sha256=xj_hVYma2sKDK5Vq_R9wo8f0ZXfGlXTkYU71AMyKF2U,1232
|
|
126
126
|
clearskies/handlers/crud_by_method.py,sha256=BOkPX-LUvQrbRLSbyTfRh4c8nPF51dZEXSKOl7m9ZYA,435
|
|
127
127
|
clearskies/handlers/database_connector.py,sha256=XLF_Y3aYnjDtOVP_MOtT5mbI3lHR8S-viOxPiqEAamE,1050
|
|
128
128
|
clearskies/handlers/delete.py,sha256=nXzEuOPI6GEvuiqA5baO2iNEjETsGqNXfRDRj-C1nhc,2247
|
|
@@ -134,7 +134,7 @@ clearskies/handlers/exceptions/input_error.py,sha256=kmEVv9LNIalLKD9GF-olsD39Z94
|
|
|
134
134
|
clearskies/handlers/exceptions/not_found.py,sha256=xThOXiMfyYBaI2bhfOhpVoZ_vdw1hU8A_HxHenPqHzo,96
|
|
135
135
|
clearskies/handlers/get.py,sha256=GHXlhXiuewu9E54RsCo7BPyFXQ7m5tCyiAPHIgb8Qok,6820
|
|
136
136
|
clearskies/handlers/health_check.py,sha256=m6H3psUql-I7hZao3fsxjrZnCjFJZ1ROTF-41g8Syww,2078
|
|
137
|
-
clearskies/handlers/input_processing.py,sha256=
|
|
137
|
+
clearskies/handlers/input_processing.py,sha256=edtG6NQJZCte0Nq-j7SUMzp6vxgIIbLxeUGscWOALAs,3814
|
|
138
138
|
clearskies/handlers/list.py,sha256=f17wbS1gVopTTzV9rwmEb7KjHnoiwercENZbXJDwChI,23133
|
|
139
139
|
clearskies/handlers/mygrations.py,sha256=4iKpJKooqgNtAURwMl_FgsXUt8OYOaG_TY1OV1llQxY,2759
|
|
140
140
|
clearskies/handlers/request_method_routing.py,sha256=DgPEz3tgbaUkXHsOriPbIctfSf4Gm4NxfRdVulH91Kg,1636
|
|
@@ -144,7 +144,7 @@ clearskies/handlers/schema_helper.py,sha256=62644USvFlZu_6tT7rb-k6t_5J3Q0uZsJwP5
|
|
|
144
144
|
clearskies/handlers/simple_routing.py,sha256=8T4eKLIurZO3ZdIPgi-0pypQp_X4BKkbet_Ymba5br4,9332
|
|
145
145
|
clearskies/handlers/simple_routing_route.py,sha256=C-dDLubkUnAazxAcXoyGxMX4g24Iwz7wX5rf5T8T8kU,7376
|
|
146
146
|
clearskies/handlers/simple_search.py,sha256=hZ0rMfhS-BB6LTpdl0I53pEUBgbgIwtXvcW_8ZEOZOs,6003
|
|
147
|
-
clearskies/handlers/update.py,sha256=
|
|
147
|
+
clearskies/handlers/update.py,sha256=GAtkZpim6YI-XvtJ4qm-fwlz7gHYbUMCfvsfdD0_RSo,3799
|
|
148
148
|
clearskies/handlers/write.py,sha256=VduGtjnFMQOvo3l0t-tUP4PExPJ9JEpuziHsquF08rE,9344
|
|
149
149
|
clearskies/input_outputs/__init__.py,sha256=mQWL-u41FRTrPGuHe8FhLmcHjAEaUxjFwUf7RgDcbAs,182
|
|
150
150
|
clearskies/input_outputs/cli.py,sha256=snIfLFakIqDXm-AXVN6qes0tZsg2IM7T1riFzDdHlMM,6254
|
|
@@ -162,7 +162,7 @@ clearskies/input_requirements/unique.py,sha256=gpbm9uoXcy8WCHsuWqAotwockbjDfJOWi
|
|
|
162
162
|
clearskies/mocks/__init__.py,sha256=T68OUB9gGCX0WoisGzsY3Bt2cCFX7ILHKPqi6XKTJM0,113
|
|
163
163
|
clearskies/mocks/input_output.py,sha256=2wD5GbUyVSkXcBg1GTZ-Oz9VzcYxNHfTlmZAODW-7CI,3898
|
|
164
164
|
clearskies/mocks/models.py,sha256=DCzsnMddBvPoBA8JwwbSOhzY7enQWrosgeYD4gx2deI,5124
|
|
165
|
-
clearskies/model.py,sha256=
|
|
165
|
+
clearskies/model.py,sha256=vUZ5lCDmZqvt11YC-ii15MdbftBM1Koz_JJ-KonjCdA,12691
|
|
166
166
|
clearskies/models.py,sha256=Oh1dDPg-IDIEt54oXVvKBBmksBYtStyw6Uu5fOfCs6E,12232
|
|
167
167
|
clearskies/secrets/__init__.py,sha256=ctTmA_etV9G_5U21APWENI1HvThrBS4DidGWRtEDHQs,1053
|
|
168
168
|
clearskies/secrets/additional_configs/__init__.py,sha256=cFCrbtKF5nuR061S2y1iKZp349x-y8Srdwe3VZbfSFU,1119
|
|
@@ -186,7 +186,7 @@ clearskies/tests/simple_api/models/__init__.py,sha256=nUA0W6fgXw_Bxa9CudkaDkC80t
|
|
|
186
186
|
clearskies/tests/simple_api/models/status.py,sha256=PEhPbaQh5qdUNHp8O0gz91LOLENAEBtqSaHxUPXchaM,699
|
|
187
187
|
clearskies/tests/simple_api/models/user.py,sha256=5_P4Tp1tTdX7PkMJ__epPM5MA7JAeVYGas69vcWloLc,819
|
|
188
188
|
clearskies/tests/simple_api/users_api.py,sha256=KYXCgEofDxHeRdQK67txN5oYUPvxxmB8JTku7L-apk4,2344
|
|
189
|
-
clear_skies-1.18.
|
|
190
|
-
clear_skies-1.18.
|
|
191
|
-
clear_skies-1.18.
|
|
192
|
-
clear_skies-1.18.
|
|
189
|
+
clear_skies-1.18.5.dist-info/LICENSE,sha256=3Ehd0g3YOpCj8sqj0Xjq5qbOtjjgk9qzhhD9YjRQgOA,1053
|
|
190
|
+
clear_skies-1.18.5.dist-info/METADATA,sha256=L1nHAatrWlhUOyMtNjmOI9TzuYBN3T6RHtRhDEdRItg,1366
|
|
191
|
+
clear_skies-1.18.5.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
|
|
192
|
+
clear_skies-1.18.5.dist-info/RECORD,,
|
|
@@ -214,6 +214,12 @@ class Column(ABC):
|
|
|
214
214
|
if on_change_actions and model.was_changed(self.name):
|
|
215
215
|
self.execute_actions(on_change_actions, model)
|
|
216
216
|
|
|
217
|
+
def values_match(self, value_1, value_2):
|
|
218
|
+
"""
|
|
219
|
+
Compares two values to see if they are the same
|
|
220
|
+
"""
|
|
221
|
+
return value_1 == value_2
|
|
222
|
+
|
|
217
223
|
def pre_delete(self, model):
|
|
218
224
|
"""
|
|
219
225
|
Make any changes needed to the data before starting the delete process
|
|
@@ -49,3 +49,44 @@ class DateTime(Column):
|
|
|
49
49
|
if not value.tzinfo:
|
|
50
50
|
return "date is missing timezone information"
|
|
51
51
|
return ""
|
|
52
|
+
|
|
53
|
+
def values_match(self, value_1, value_2):
|
|
54
|
+
"""
|
|
55
|
+
Compares two values to see if they are the same
|
|
56
|
+
"""
|
|
57
|
+
# in this function we deal with data directly out of the backend, so our date is likely
|
|
58
|
+
# to be string-ified and we want to look for default (e.g. null) values in string form.
|
|
59
|
+
if type(value_1) == str and "0000-00-00" in value_1:
|
|
60
|
+
value_1 = None
|
|
61
|
+
if type(value_2) == str and "0000-00-00" in value_2:
|
|
62
|
+
value_2 = None
|
|
63
|
+
number_values = 0
|
|
64
|
+
if value_1:
|
|
65
|
+
number_values += 1
|
|
66
|
+
if value_2:
|
|
67
|
+
number_values += 1
|
|
68
|
+
if number_values == 0:
|
|
69
|
+
return True
|
|
70
|
+
if number_values == 1:
|
|
71
|
+
return False
|
|
72
|
+
|
|
73
|
+
if type(value_1) == str:
|
|
74
|
+
value_1 = dateparser.parse(value_1)
|
|
75
|
+
if type(value_2) == str:
|
|
76
|
+
value_2 = dateparser.parse(value_2)
|
|
77
|
+
|
|
78
|
+
# we need to make sure we're comparing in the same timezones. For our purposes, a difference in timezone
|
|
79
|
+
# is fine as long as they represent the same time (e.g. 16:00EST == 20:00UTC). For python, same time in different
|
|
80
|
+
# timezones is treated as different datetime objects.
|
|
81
|
+
if value_1.tzinfo is not None and value_2.tzinfo is not None:
|
|
82
|
+
value_1 = value_1.astimezone(value_2.tzinfo)
|
|
83
|
+
|
|
84
|
+
# two times can be the same but if one is datetime-aware and one is not, python will treat them as not equal.
|
|
85
|
+
# we want to treat such times as being the same. Therefore, check for equality but ignore the timezone.
|
|
86
|
+
for to_check in ["year", "month", "day", "hour", "minute", "second", "microsecond"]:
|
|
87
|
+
if getattr(value_1, to_check) != getattr(value_2, to_check):
|
|
88
|
+
return False
|
|
89
|
+
|
|
90
|
+
# and since we already converted the timezones to match (or one has a timezone and one doesn't), we're good to go.
|
|
91
|
+
# if we passed the above loop then the times are the same.
|
|
92
|
+
return True
|
clearskies/columns.py
CHANGED
|
@@ -17,18 +17,23 @@ class Columns:
|
|
|
17
17
|
if name in columns:
|
|
18
18
|
raise ValueError(f"Duplicate column '{name}' found for model '{model_class.__name__}'")
|
|
19
19
|
column_overrides = overrides[name] if (overrides is not None and name in overrides) else {}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
# if the overrides changes the class then we need to completely replace the column definition
|
|
21
|
+
# with what is in the overrides.
|
|
22
|
+
if "class" in column_overrides and id(column_overrides["class"]) != id(configuration["class"]):
|
|
23
|
+
configuration = column_overrides
|
|
24
|
+
else:
|
|
25
|
+
configuration = {
|
|
26
|
+
**configuration,
|
|
27
|
+
**column_overrides,
|
|
28
|
+
"input_requirements": self._resolve_input_requirements(
|
|
29
|
+
self._merge_input_requirements(
|
|
30
|
+
configuration.get("input_requirements"),
|
|
31
|
+
column_overrides.get("input_requirements"),
|
|
32
|
+
),
|
|
33
|
+
name,
|
|
34
|
+
model_class.__name__,
|
|
27
35
|
),
|
|
28
|
-
|
|
29
|
-
model_class.__name__,
|
|
30
|
-
),
|
|
31
|
-
}
|
|
36
|
+
}
|
|
32
37
|
columns[name] = self.build_column(name, configuration, model_class)
|
|
33
38
|
|
|
34
39
|
# overrides can add columns too - need to handle those separately
|
clearskies/handlers/create.py
CHANGED
|
@@ -23,7 +23,7 @@ class Create(Write):
|
|
|
23
23
|
if input_errors:
|
|
24
24
|
self._logging.debug("Request rejected due to input errors: " + json.dumps(input_errors))
|
|
25
25
|
raise InputError(input_errors)
|
|
26
|
-
model.save(input_data)
|
|
26
|
+
model.save(input_data, columns=self._columns)
|
|
27
27
|
|
|
28
28
|
return self.success(input_output, self._model_as_json(model, input_output))
|
|
29
29
|
|
|
@@ -9,11 +9,13 @@ class InputProcessing:
|
|
|
9
9
|
def _get_writeable_columns(self):
|
|
10
10
|
if self._writeable_columns is None:
|
|
11
11
|
self._writeable_columns = self._get_rw_columns("writeable")
|
|
12
|
+
additional_columns = OrderedDict()
|
|
12
13
|
for column in self._writeable_columns.values():
|
|
13
14
|
more_columns = column.additional_write_columns(is_create=self._is_create)
|
|
14
|
-
# do it one-at-a-time so we don't lose our OrderedDict
|
|
15
15
|
for additional_column_name, additional_column in more_columns.items():
|
|
16
|
-
|
|
16
|
+
additional_columns[additional_column_name] = additional_column
|
|
17
|
+
for additional_column_name, additional_column in additional_columns.items():
|
|
18
|
+
self._writeable_columns[additional_column_name] = additional_column
|
|
17
19
|
return self._writeable_columns
|
|
18
20
|
|
|
19
21
|
def _extra_column_errors(self, input_data):
|
clearskies/handlers/update.py
CHANGED
clearskies/model.py
CHANGED
|
@@ -10,6 +10,7 @@ class Model(Models):
|
|
|
10
10
|
_configured_columns = None
|
|
11
11
|
_data = None
|
|
12
12
|
_previous_data = None
|
|
13
|
+
_touched_columns = None
|
|
13
14
|
_transformed = None
|
|
14
15
|
id_column_name = "id"
|
|
15
16
|
|
|
@@ -18,6 +19,7 @@ class Model(Models):
|
|
|
18
19
|
self._transformed = {}
|
|
19
20
|
self._data = {}
|
|
20
21
|
self._previous_data = None
|
|
22
|
+
self._touched_columns = None
|
|
21
23
|
|
|
22
24
|
def model_class(self):
|
|
23
25
|
"""
|
|
@@ -120,7 +122,7 @@ class Model(Models):
|
|
|
120
122
|
def data(self, data):
|
|
121
123
|
self._data = {} if data is None else data
|
|
122
124
|
|
|
123
|
-
def save(self, data):
|
|
125
|
+
def save(self, data, columns=None):
|
|
124
126
|
"""
|
|
125
127
|
Save data to the database and update the model!
|
|
126
128
|
|
|
@@ -128,7 +130,8 @@ class Model(Models):
|
|
|
128
130
|
"""
|
|
129
131
|
if not len(data):
|
|
130
132
|
raise ValueError("You have to pass in something to save!")
|
|
131
|
-
columns
|
|
133
|
+
if columns is None:
|
|
134
|
+
columns = self.columns()
|
|
132
135
|
|
|
133
136
|
old_data = self.data
|
|
134
137
|
data = self.columns_pre_save(data, columns)
|
|
@@ -150,6 +153,7 @@ class Model(Models):
|
|
|
150
153
|
self.data = new_data
|
|
151
154
|
self._transformed = {}
|
|
152
155
|
self._previous_data = old_data
|
|
156
|
+
self._touched_columns = list(data.keys())
|
|
153
157
|
|
|
154
158
|
self.columns_save_finished(columns)
|
|
155
159
|
self.save_finished()
|
|
@@ -190,9 +194,11 @@ class Model(Models):
|
|
|
190
194
|
"""Returns True/False to denote if a column was changed in the last save"""
|
|
191
195
|
if self._previous_data is None:
|
|
192
196
|
raise ValueError("was_changed was called before a save was finished - you must save something first")
|
|
197
|
+
if key not in self._touched_columns:
|
|
198
|
+
return False
|
|
193
199
|
|
|
194
|
-
has_old_value =
|
|
195
|
-
has_new_value =
|
|
200
|
+
has_old_value = bool(self._previous_data.get(key))
|
|
201
|
+
has_new_value = bool(self._data.get(key))
|
|
196
202
|
|
|
197
203
|
if has_new_value != has_old_value:
|
|
198
204
|
return True
|
|
@@ -200,7 +206,12 @@ class Model(Models):
|
|
|
200
206
|
if not has_old_value:
|
|
201
207
|
return False
|
|
202
208
|
|
|
203
|
-
|
|
209
|
+
columns = self.columns()
|
|
210
|
+
new_value = self.__getattr__(key)
|
|
211
|
+
old_value = self._previous_data[key]
|
|
212
|
+
if key not in columns:
|
|
213
|
+
return old_value != new_value
|
|
214
|
+
return not columns[key].values_match(old_value, new_value)
|
|
204
215
|
|
|
205
216
|
def previous_value(self, key):
|
|
206
217
|
return self.get_transformed_from_data(key, self._previous_data, cache=False, check_providers=False, silent=True)
|
|
File without changes
|
|
File without changes
|