Skip to content

Commit d18aab0

Browse files
authored
feat: add lifecycle hooks
1 parent f10852b commit d18aab0

File tree

2 files changed

+264
-0
lines changed

2 files changed

+264
-0
lines changed

nitric/lifecycle/__init__.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#
2+
# Copyright (c) 2021 Nitric Technologies Pty Ltd.
3+
#
4+
# This file is part of Nitric Python 3 SDK.
5+
# See https://github.com/nitrictech/python-sdk for further info.
6+
#
7+
# Licensed under the Apache License, Version 2.0 (the "License");
8+
# you may not use this file except in compliance with the License.
9+
# You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
#
19+
"""
20+
Lifecycle utilities for Nitric applications.
21+
22+
This module provides utilities for detecting the current lifecycle stage and
23+
conditionally executing code based on the current stage.
24+
"""
25+
26+
from nitric.lifecycle.lifecycle import (
27+
Lifecycle,
28+
LifecycleStage,
29+
get_current_lifecycle,
30+
is_collecting,
31+
is_in_lifecycle,
32+
is_running,
33+
when_collecting,
34+
when_in_lifecycles,
35+
when_running,
36+
)
37+
38+
__all__ = [
39+
"Lifecycle",
40+
"LifecycleStage",
41+
"get_current_lifecycle",
42+
"is_collecting",
43+
"is_in_lifecycle",
44+
"is_running",
45+
"when_collecting",
46+
"when_in_lifecycles",
47+
"when_running",
48+
]

nitric/lifecycle/lifecycle.py

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
#
2+
# Copyright (c) 2021 Nitric Technologies Pty Ltd.
3+
#
4+
# This file is part of Nitric Python 3 SDK.
5+
# See https://github.com/nitrictech/python-sdk for further info.
6+
#
7+
# Licensed under the Apache License, Version 2.0 (the "License");
8+
# you may not use this file except in compliance with the License.
9+
# You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
19+
import os
20+
from enum import Enum
21+
from typing import Callable, List, TypeVar, Optional
22+
23+
# The environment variable key that will be used to determine the current Nitric lifecycle/executing environment
24+
NITRIC_ENVIRONMENT = 'NITRIC_ENVIRONMENT'
25+
26+
27+
# Possible nitric execution environments
28+
class LifecycleStage(Enum):
29+
"""Represents the different stages of the Nitric application lifecycle."""
30+
31+
# Local development run (using nitric run/start)
32+
LOCAL_RUN = 'run'
33+
34+
# Local development requirements building/collection (using nitric up)
35+
BUILD = 'build'
36+
37+
# When the code is running in a deployed environment
38+
CLOUD = 'cloud'
39+
40+
41+
def get_current_lifecycle() -> LifecycleStage:
42+
"""
43+
Get the current lifecycle stage from the environment variable.
44+
45+
Returns:
46+
The current lifecycle stage.
47+
48+
Raises:
49+
ValueError: If the NITRIC_ENVIRONMENT environment variable is not set or is invalid.
50+
"""
51+
lifecycle = os.environ.get(NITRIC_ENVIRONMENT)
52+
53+
if not lifecycle or lifecycle not in [stage.value for stage in LifecycleStage]:
54+
raise ValueError(
55+
f"Unable to determine the current Nitric lifecycle, please ensure the {NITRIC_ENVIRONMENT} "
56+
"environment variable is set"
57+
)
58+
59+
return LifecycleStage(lifecycle)
60+
61+
62+
def is_in_lifecycle(stages: List[LifecycleStage]) -> bool:
63+
"""
64+
Check if the current environment is one of the provided stages.
65+
66+
Args:
67+
stages: The stages to check against.
68+
69+
Returns:
70+
True if the current stage is in the provided stages, False otherwise.
71+
"""
72+
current_stage = get_current_lifecycle()
73+
return current_stage in stages
74+
75+
76+
T = TypeVar('T')
77+
78+
79+
def when_in_lifecycles(stages: List[LifecycleStage], callback: Callable[[], T]) -> Optional[T]:
80+
"""
81+
If the current environment is one of the provided stages, execute the provided callback.
82+
83+
Args:
84+
stages: The stages to check against.
85+
callback: The callback to execute if the current stage is in the provided stages.
86+
87+
Returns:
88+
The result of the callback if executed, None otherwise.
89+
"""
90+
if is_in_lifecycle(stages):
91+
return callback()
92+
return None
93+
94+
95+
def when_running(callback: Callable[[], T]) -> Optional[T]:
96+
"""
97+
If the current environment is running (local or cloud), execute the provided callback.
98+
99+
Args:
100+
callback: The callback to execute if the current stage is running.
101+
102+
Returns:
103+
The result of the callback if executed, None otherwise.
104+
"""
105+
return when_in_lifecycles([LifecycleStage.LOCAL_RUN, LifecycleStage.CLOUD], callback)
106+
107+
108+
def when_collecting(callback: Callable[[], T]) -> Optional[T]:
109+
"""
110+
If the current environment is collecting requirements, execute the provided callback.
111+
112+
Args:
113+
callback: The callback to execute if the current stage is collecting.
114+
115+
Returns:
116+
The result of the callback if executed, None otherwise.
117+
"""
118+
return when_in_lifecycles([LifecycleStage.BUILD], callback)
119+
120+
121+
def is_running() -> bool:
122+
"""
123+
Check if the current lifecycle is running the app.
124+
125+
Returns:
126+
True if the current stage is running, False otherwise.
127+
"""
128+
return is_in_lifecycle([LifecycleStage.LOCAL_RUN, LifecycleStage.CLOUD])
129+
130+
131+
def is_collecting() -> bool:
132+
"""
133+
Check if the current lifecycle is collecting application requirements.
134+
135+
Returns:
136+
True if the current stage is collecting, False otherwise.
137+
"""
138+
return is_in_lifecycle([LifecycleStage.BUILD])
139+
140+
141+
# Create a class to match the Node SDK's export style
142+
class Lifecycle:
143+
"""Lifecycle utilities for Nitric applications."""
144+
145+
@staticmethod
146+
def lifecycle_is(stages: List[LifecycleStage]) -> bool:
147+
"""
148+
Check if the current environment is one of the provided stages.
149+
150+
Args:
151+
stages: The stages to check against.
152+
153+
Returns:
154+
True if the current stage is in the provided stages, False otherwise.
155+
"""
156+
return is_in_lifecycle(stages)
157+
158+
@staticmethod
159+
def is_collecting() -> bool:
160+
"""
161+
Check if the current lifecycle is collecting application requirements.
162+
163+
Returns:
164+
True if the current stage is collecting, False otherwise.
165+
"""
166+
return is_collecting()
167+
168+
@staticmethod
169+
def is_running() -> bool:
170+
"""
171+
Check if the current lifecycle is running the app.
172+
173+
Returns:
174+
True if the current stage is running, False otherwise.
175+
"""
176+
return is_running()
177+
178+
@staticmethod
179+
def when(stages: List[LifecycleStage], callback: Callable[[], T]) -> Optional[T]:
180+
"""
181+
If the current environment is one of the provided stages, execute the provided callback.
182+
183+
Args:
184+
stages: The stages to check against.
185+
callback: The callback to execute if the current stage is in the provided stages.
186+
187+
Returns:
188+
The result of the callback if executed, None otherwise.
189+
"""
190+
return when_in_lifecycles(stages, callback)
191+
192+
@staticmethod
193+
def when_collecting(callback: Callable[[], T]) -> Optional[T]:
194+
"""
195+
If the current environment is collecting requirements, execute the provided callback.
196+
197+
Args:
198+
callback: The callback to execute if the current stage is collecting.
199+
200+
Returns:
201+
The result of the callback if executed, None otherwise.
202+
"""
203+
return when_collecting(callback)
204+
205+
@staticmethod
206+
def when_running(callback: Callable[[], T]) -> Optional[T]:
207+
"""
208+
If the current environment is running (local or cloud), execute the provided callback.
209+
210+
Args:
211+
callback: The callback to execute if the current stage is running.
212+
213+
Returns:
214+
The result of the callback if executed, None otherwise.
215+
"""
216+
return when_running(callback)

0 commit comments

Comments
 (0)