terra_ui_components 0.0.131__py3-none-any.whl → 0.0.135__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.
- terra_ui_components/__init__.py +2 -1
- terra_ui_components/base.py +2 -2
- terra_ui_components/earthdata_login/__init__.py +3 -0
- terra_ui_components/earthdata_login/earthdata_login.py +177 -0
- {terra_ui_components-0.0.131.dist-info → terra_ui_components-0.0.135.dist-info}/METADATA +2 -1
- {terra_ui_components-0.0.131.dist-info → terra_ui_components-0.0.135.dist-info}/RECORD +8 -6
- {terra_ui_components-0.0.131.dist-info → terra_ui_components-0.0.135.dist-info}/WHEEL +0 -0
- {terra_ui_components-0.0.131.dist-info → terra_ui_components-0.0.135.dist-info}/licenses/LICENSE.md +0 -0
terra_ui_components/__init__.py
CHANGED
|
@@ -13,4 +13,5 @@ from .plot_toolbar import TerraPlotToolbar
|
|
|
13
13
|
from .data_access import TerraDataAccess
|
|
14
14
|
from .slider import TerraSlider
|
|
15
15
|
from .input import TerraInput
|
|
16
|
-
|
|
16
|
+
from .earthdata_login import TerraEarthdataLogin
|
|
17
|
+
__all__ = ["TerraBaseWidget", "TerraDateRangeSlider", "TerraTimeSeries", "TerraLogin", "TerraDialog", "TerraDatePicker", "TerraDataRods", "TerraAccordion", "TerraDataSubsetter", "TerraDataSubsetterHistory", "TerraTimeAverageMap", "TerraPlotToolbar", "TerraDataAccess", "TerraSlider", "TerraInput", "TerraEarthdataLogin"]
|
terra_ui_components/base.py
CHANGED
|
@@ -16,12 +16,12 @@ class TerraBaseWidget(anywidget.AnyWidget):
|
|
|
16
16
|
return f"""
|
|
17
17
|
const terraStyles = document.createElement('link')
|
|
18
18
|
terraStyles.rel = 'stylesheet'
|
|
19
|
-
terraStyles.href = 'https://cdn.jsdelivr.net/npm/@nasa-terra/components@0.0.
|
|
19
|
+
terraStyles.href = 'https://cdn.jsdelivr.net/npm/@nasa-terra/components@0.0.135/cdn/themes/horizon.css'
|
|
20
20
|
//terraStyles.href = "http://localhost:4000/dist/themes/horizon.css"
|
|
21
21
|
document.head.appendChild(terraStyles)
|
|
22
22
|
|
|
23
23
|
const terraAutoloader = document.createElement('script')
|
|
24
|
-
terraAutoloader.src = "https://cdn.jsdelivr.net/npm/@nasa-terra/components@0.0.
|
|
24
|
+
terraAutoloader.src = "https://cdn.jsdelivr.net/npm/@nasa-terra/components@0.0.135/cdn/terra-ui-components-autoloader.js"
|
|
25
25
|
//terraAutoloader.src = "http://localhost:4000/dist/terra-ui-components-autoloader.js"
|
|
26
26
|
terraAutoloader.type = 'module'
|
|
27
27
|
document.head.appendChild(terraAutoloader)
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import importlib.metadata
|
|
2
|
+
import traitlets
|
|
3
|
+
from ..base import TerraBaseWidget
|
|
4
|
+
import earthaccess
|
|
5
|
+
from earthaccess.auth import netrc_path
|
|
6
|
+
from earthaccess.exceptions import LoginStrategyUnavailable
|
|
7
|
+
import os
|
|
8
|
+
from tinynetrc import Netrc
|
|
9
|
+
|
|
10
|
+
try:
|
|
11
|
+
__version__ = importlib.metadata.version("terra_earthdata_login")
|
|
12
|
+
except importlib.metadata.PackageNotFoundError:
|
|
13
|
+
__version__ = "unknown"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class TerraEarthdataLogin(TerraBaseWidget):
|
|
17
|
+
_esm = TerraBaseWidget.get_autoloader() + """
|
|
18
|
+
function render({ model, el }) {
|
|
19
|
+
const cell = el.closest('.lm-Widget');
|
|
20
|
+
if (cell && cell.classList.contains('jp-mod-outputsScrolled')) {
|
|
21
|
+
cell.classList.remove('jp-mod-outputsScrolled');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// create an instance of the component
|
|
25
|
+
let component = document.createElement('terra-earthdata-login')
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Set initial property values
|
|
29
|
+
* NOTE: In reality, we won't need to have the ability to set EVERY property in a Jupyter Notebook, feel free to remove the ones that don't make sense
|
|
30
|
+
*
|
|
31
|
+
* model.get() pulls from the Jupyter notebooks state. We'll use the state to set the initial value for each property
|
|
32
|
+
*/
|
|
33
|
+
component.loggedInMessage = model.get('loggedInMessage')
|
|
34
|
+
component.loggedOutMessage = model.get('loggedOutMessage')
|
|
35
|
+
component.loadingMessage = model.get('loadingMessage')
|
|
36
|
+
component.username = model.get('username')
|
|
37
|
+
component.password = model.get('password')
|
|
38
|
+
component.autoLogin = model.get('autoLogin')
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* add the component to the cell
|
|
42
|
+
* it should now be visible in the notebook!
|
|
43
|
+
*/
|
|
44
|
+
el.appendChild(component)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Set up property change handlers
|
|
49
|
+
* This way if someone in the Jupyter Notebook changes the property externally, we reflect the change
|
|
50
|
+
* back to the component.
|
|
51
|
+
*
|
|
52
|
+
* If this isn't here, the component can't be changed after it's initial render
|
|
53
|
+
*/
|
|
54
|
+
model.on('change:loggedInMessage', () => {
|
|
55
|
+
component.loggedInMessage = model.get('loggedInMessage')
|
|
56
|
+
})
|
|
57
|
+
model.on('change:loggedOutMessage', () => {
|
|
58
|
+
component.loggedOutMessage = model.get('loggedOutMessage')
|
|
59
|
+
})
|
|
60
|
+
model.on('change:loadingMessage', () => {
|
|
61
|
+
component.loadingMessage = model.get('loadingMessage')
|
|
62
|
+
})
|
|
63
|
+
model.on('change:username', () => {
|
|
64
|
+
component.username = model.get('username')
|
|
65
|
+
})
|
|
66
|
+
model.on('change:password', () => {
|
|
67
|
+
component.password = model.get('password')
|
|
68
|
+
})
|
|
69
|
+
model.on('change:autoLogin', () => {
|
|
70
|
+
component.autoLogin = model.get('autoLogin')
|
|
71
|
+
})
|
|
72
|
+
model.on('change:credentialsError', () => {
|
|
73
|
+
console.log('credentialsError: ', model.get('credentialsError'))
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
// listen for terra-login event and update the bearer token in the model
|
|
77
|
+
component.addEventListener('terra-login', (e) => {
|
|
78
|
+
model.set('bearerToken', e.detail.token)
|
|
79
|
+
model.save_changes()
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export default { render };
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
# Component properties
|
|
87
|
+
# While we have properties in the component, we also need to tell Python about them as well.
|
|
88
|
+
# Again, you don't technically need all these. If Jupyter Notebooks don't need access to them, you can remove them from here
|
|
89
|
+
loggedInMessage = traitlets.Unicode('').tag(sync=True)
|
|
90
|
+
loggedOutMessage = traitlets.Unicode('').tag(sync=True)
|
|
91
|
+
loadingMessage = traitlets.Unicode('').tag(sync=True)
|
|
92
|
+
bearerToken = traitlets.Unicode('').tag(sync=True)
|
|
93
|
+
username = traitlets.Unicode().tag(sync=True)
|
|
94
|
+
password = traitlets.Unicode().tag(sync=True)
|
|
95
|
+
credentialsError = traitlets.Unicode('').tag(sync=True)
|
|
96
|
+
autoLogin = traitlets.Bool(True).tag(sync=True)
|
|
97
|
+
|
|
98
|
+
@traitlets.default('username')
|
|
99
|
+
def _default_username(self):
|
|
100
|
+
"""
|
|
101
|
+
Get the default username from the .netrc file or environment variable
|
|
102
|
+
"""
|
|
103
|
+
username, password = self._get_default_credentials()
|
|
104
|
+
if username is not None:
|
|
105
|
+
return username
|
|
106
|
+
return ''
|
|
107
|
+
|
|
108
|
+
@traitlets.default('password')
|
|
109
|
+
def _default_password(self):
|
|
110
|
+
"""
|
|
111
|
+
Get the default password from the .netrc file or environment variable
|
|
112
|
+
"""
|
|
113
|
+
username, password = self._get_default_credentials()
|
|
114
|
+
if password is not None:
|
|
115
|
+
return password
|
|
116
|
+
return ''
|
|
117
|
+
|
|
118
|
+
@traitlets.observe("bearerToken")
|
|
119
|
+
def _observe_bearer_token(self, change):
|
|
120
|
+
"""
|
|
121
|
+
Whenever the bearer token changes, we want to login to earthaccess with the new token
|
|
122
|
+
"""
|
|
123
|
+
if change["new"]:
|
|
124
|
+
os.environ["EARTHDATA_TOKEN"] = change["new"]
|
|
125
|
+
earthaccess.login(strategy='environment')
|
|
126
|
+
|
|
127
|
+
def _get_default_credentials(self):
|
|
128
|
+
"""
|
|
129
|
+
Get the default credentials from the .netrc file
|
|
130
|
+
"""
|
|
131
|
+
try:
|
|
132
|
+
return self._get_default_credentials_from_netrc()
|
|
133
|
+
except Exception as e:
|
|
134
|
+
self.credentialsError = str(e)
|
|
135
|
+
return self._get_default_credentials_from_environment()
|
|
136
|
+
|
|
137
|
+
def _get_default_credentials_from_netrc(self):
|
|
138
|
+
"""
|
|
139
|
+
Get the default credentials from the .netrc file
|
|
140
|
+
"""
|
|
141
|
+
netrc_loc = netrc_path()
|
|
142
|
+
|
|
143
|
+
try:
|
|
144
|
+
my_netrc = Netrc(str(netrc_loc))
|
|
145
|
+
except FileNotFoundError as err:
|
|
146
|
+
raise LoginStrategyUnavailable(
|
|
147
|
+
f"No .netrc found at {netrc_loc}") from err
|
|
148
|
+
except NetrcParseError as err:
|
|
149
|
+
raise LoginStrategyUnavailable(
|
|
150
|
+
f"Unable to parse .netrc file {netrc_loc}"
|
|
151
|
+
) from err
|
|
152
|
+
|
|
153
|
+
creds = my_netrc['urs.earthdata.nasa.gov']
|
|
154
|
+
if creds is None:
|
|
155
|
+
raise LoginStrategyUnavailable(
|
|
156
|
+
f"Earthdata Login hostname urs.earthdata.nasa.gov not found in .netrc file {netrc_loc}"
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
username = creds["login"]
|
|
160
|
+
password = creds["password"]
|
|
161
|
+
|
|
162
|
+
if username is None:
|
|
163
|
+
raise LoginStrategyUnavailable(
|
|
164
|
+
f"Username not found in .netrc file {netrc_loc}"
|
|
165
|
+
)
|
|
166
|
+
if password is None:
|
|
167
|
+
raise LoginStrategyUnavailable(
|
|
168
|
+
f"Password not found in .netrc file {netrc_loc}"
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
return username, password
|
|
172
|
+
|
|
173
|
+
def _get_default_credentials_from_environment(self):
|
|
174
|
+
"""
|
|
175
|
+
Get the default credentials from the environment variable
|
|
176
|
+
"""
|
|
177
|
+
return os.environ.get('EARTHDATA_USERNAME', ''), os.environ.get('EARTHDATA_PASSWORD', '')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: terra_ui_components
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.135
|
|
4
4
|
Summary: NASA Terra UI Components Library
|
|
5
5
|
License-File: LICENSE.md
|
|
6
6
|
Requires-Python: >=3.8
|
|
@@ -61,6 +61,7 @@ Then run the following:
|
|
|
61
61
|
- `uv venv` - create a virtual environment (only have to do this the first time)
|
|
62
62
|
- `source .venv/bin/activate` - activate it
|
|
63
63
|
- `uv pip install -e ".[dev]"` - install dependencies (see pyproject.toml)
|
|
64
|
+
- open base.py and point dependencies to localhost (do not commit these changes) TODO: fix this so we auto-detect local development
|
|
64
65
|
- `npm run start:python` - spins up Jupyter lab and should open the browser for you
|
|
65
66
|
|
|
66
67
|
For an example of how to use the components in a Jupyter Notebook, open the `/notebooks/playground.ipynb` notebook in Jupyter Lab.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
terra_ui_components/README.md,sha256=lBRXP8aio8W0AqDiXL9hkgGlPKfPTELiXZflujVT6BY,198
|
|
2
|
-
terra_ui_components/__init__.py,sha256=
|
|
3
|
-
terra_ui_components/base.py,sha256=
|
|
2
|
+
terra_ui_components/__init__.py,sha256=2048zaqJKHd_FSTxfZAvGdR_sZSgo15mog3ko6pFw10,980
|
|
3
|
+
terra_ui_components/base.py,sha256=7eIWyBZe8_RGqm8NH2auca12--TFlbw3b-9Vw6IgTeE,1224
|
|
4
4
|
terra_ui_components/accordion/__init__.py,sha256=xruOtrVmmzFKacs2B_lKpEnDh2PbBq-HUKCdceRNboU,67
|
|
5
5
|
terra_ui_components/accordion/accordion.py,sha256=3duUmiJ5DTMYfzMJmra8pt0CXXcOkcbY-aAb7-PVCIs,1789
|
|
6
6
|
terra_ui_components/browse_variables/__init__.py,sha256=JfrTDLSbAecttohBx_OuEC1qT-LoqGO4egStvlJY1Os,86
|
|
@@ -19,6 +19,8 @@ terra_ui_components/date_range_slider/__init__.py,sha256=8rFfB6ilThf7fvuGsFZ8w4n
|
|
|
19
19
|
terra_ui_components/date_range_slider/date_range_slider.py,sha256=kE3vMFV-CZ45n8F48qE0Vrs3taPClxSrZRy8ffOEbp0,3511
|
|
20
20
|
terra_ui_components/dialog/__init__.py,sha256=6H2fOO3FawjPtowliaCxyneITsS4MXZy1YJYWgVKFCY,58
|
|
21
21
|
terra_ui_components/dialog/dialog.py,sha256=GRKktKwUpkSAE7gl8-ivZ5O18iK9oHEb2m7vKjxJIR0,1780
|
|
22
|
+
terra_ui_components/earthdata_login/__init__.py,sha256=GvxmPtvxZZfx34Z-y89x6hmx-n2wbrsAK_9lk0l8QV0,83
|
|
23
|
+
terra_ui_components/earthdata_login/earthdata_login.py,sha256=O5NssydZKYRR90M3GsQj11lWpoEIUb2DiPpuRqkSpjw,6597
|
|
22
24
|
terra_ui_components/input/__init__.py,sha256=UIEQqNyGMwv-BkeGqVjD_A_nXhiS5Tpv6WxBD7aZibk,55
|
|
23
25
|
terra_ui_components/input/input.py,sha256=JTsFjXMO9jifhisaQ2fLz7OFsTxrv_4U4AIMIXbxewU,1777
|
|
24
26
|
terra_ui_components/login/__init__.py,sha256=R9Rn-D770XK5bIsVdQ4EwiafuISYUxYpq15zxJeyk-A,55
|
|
@@ -33,7 +35,7 @@ terra_ui_components/time_series/__init__.py,sha256=uXQun39vOajxJjfOIPC4W-909Sb8Q
|
|
|
33
35
|
terra_ui_components/time_series/time_series.py,sha256=M29nbYf-wmsxyu7WgeQu-pejF598zXuBd9MwAEIW704,3833
|
|
34
36
|
terra_ui_components/variable_keyword_search/__init__.py,sha256=yjNToGluREKDD4UbkIOROSdlCC4jO6sgHA741OEwVdk,107
|
|
35
37
|
terra_ui_components/variable_keyword_search/variable_keyword_search.py,sha256=D_jT-FAu0fubKsC0ttK_XF80ExehLnwLyvSLpVVik_o,3677
|
|
36
|
-
terra_ui_components-0.0.
|
|
37
|
-
terra_ui_components-0.0.
|
|
38
|
-
terra_ui_components-0.0.
|
|
39
|
-
terra_ui_components-0.0.
|
|
38
|
+
terra_ui_components-0.0.135.dist-info/METADATA,sha256=__dC3QOl2y-jWbeakju2-wULbVGj_EllY5id8i7QkKs,3225
|
|
39
|
+
terra_ui_components-0.0.135.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
40
|
+
terra_ui_components-0.0.135.dist-info/licenses/LICENSE.md,sha256=rJ_6y_yHe29CU6SBs8DtutDAGaw1BqO1FBWzNvSgwFQ,1065
|
|
41
|
+
terra_ui_components-0.0.135.dist-info/RECORD,,
|
|
File without changes
|
{terra_ui_components-0.0.131.dist-info → terra_ui_components-0.0.135.dist-info}/licenses/LICENSE.md
RENAMED
|
File without changes
|