Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
giswqs
GitHub Repository: giswqs/geemap
Path: blob/master/tests/fake_map.py
2313 views
1
"""Fake map used for testing."""
2
3
# pylint: disable=too-few-public-methods
4
# pylint: disable=too-many-arguments
5
# pylint: disable=too-many-instance-attributes
6
# pylint: disable=too-many-positional-arguments
7
8
import unittest
9
10
import ee
11
import ipywidgets
12
import traitlets
13
14
from geemap import ee_tile_layers
15
16
17
class FakeMap:
18
"""A fake map used for initializing widgets."""
19
20
def __init__(self):
21
self.default_style = {}
22
self.interaction_handlers = set()
23
self.scale = 1024
24
self.zoom = 7
25
self.layers = []
26
self.ee_layers = {}
27
self.geojson_layers = []
28
self.controls = []
29
self.add = unittest.mock.MagicMock()
30
31
self._recognized_attrs = self.__dict__.keys()
32
33
def __setattr__(self, k, v):
34
if hasattr(self, "_recognized_attrs") and k not in self._recognized_attrs:
35
raise AttributeError(f"{k} is not a recognized attr")
36
super().__setattr__(k, v)
37
38
def on_interaction(self, func, remove=False):
39
if remove:
40
if func not in self.interaction_handlers:
41
raise ValueError("Removing an unknown on_interaction func.")
42
43
self.interaction_handlers.remove(func)
44
else:
45
if func in self.interaction_handlers:
46
raise ValueError("This on_interaction func already exists.")
47
48
self.interaction_handlers.add(func)
49
50
def click(self, coordinates, event_type):
51
for handler in self.interaction_handlers:
52
handler(coordinates=coordinates, type=event_type)
53
54
def get_scale(self):
55
return self.scale
56
57
@property
58
def bounds(self):
59
return ((1, 2), (3, 4))
60
61
def find_layer_index(self, name) -> int:
62
layers = self.layers
63
64
for index, layer in enumerate(layers):
65
if layer.name == name:
66
return index
67
68
return -1
69
70
def add_layer(
71
self,
72
ee_object,
73
vis_params=None,
74
name=None,
75
shown=True,
76
opacity=1.0,
77
):
78
layer = ee_object
79
if isinstance(
80
ee_object,
81
(
82
ee.FeatureCollection,
83
ee.Feature,
84
ee.Geometry,
85
ee.Image,
86
),
87
):
88
layer = ee_tile_layers.EELeafletTileLayer(
89
ee_object, vis_params, name, shown, opacity
90
)
91
self.ee_layers[name] = {
92
"ee_object": ee_object,
93
"ee_layer": layer,
94
"vis_params": vis_params,
95
}
96
self.layers.append(layer)
97
98
def remove_layer(self, layer):
99
if isinstance(layer, str):
100
layer = self.ee_layers[layer]["ee_layer"]
101
self.layers.remove(layer)
102
del self.ee_layers[layer.name]
103
104
def get_layer_names(self):
105
return [layer.name for layer in self.layers]
106
107
def zoom_to_bounds(self, _):
108
pass
109
110
def substitute(self, old_layer, new_layer):
111
i = self.find_layer_index(old_layer)
112
if i >= 0:
113
self.layers[i] = new_layer
114
115
def add_basemap(self, basemap="HYBRID", show=True, **kwargs):
116
del kwargs # Unused.
117
self.add_layer(FakeTileLayer(name=basemap, visible=show))
118
119
def _add_legend(
120
self,
121
title=None,
122
keys=None,
123
colors=None,
124
position=None,
125
builtin_legend=None,
126
layer_name=None,
127
add_header=None,
128
widget_args=None,
129
**kwargs,
130
):
131
del (
132
title,
133
keys,
134
colors,
135
position,
136
builtin_legend,
137
add_header,
138
widget_args,
139
kwargs,
140
)
141
if layer := self.ee_layers.get(layer_name):
142
layer["legend"] = {}
143
144
def _add_colorbar(
145
self,
146
vis_params=None,
147
cmap=None,
148
discrete=None,
149
label=None,
150
orientation=None,
151
position=None,
152
transparent_bg=None,
153
layer_name=None,
154
font_size=None,
155
axis_off=None,
156
max_width=None,
157
**kwargs,
158
):
159
del (
160
vis_params,
161
cmap,
162
discrete,
163
label,
164
orientation,
165
position,
166
transparent_bg,
167
font_size,
168
axis_off,
169
max_width,
170
kwargs,
171
)
172
if layer := self.ee_layers.get(layer_name):
173
layer["colorbar"] = {}
174
175
@property
176
def cursor_style(self):
177
return self.default_style.get("cursor")
178
179
180
class FakeEeTileLayer:
181
def __init__(self, name="test-layer", visible=True, opacity=1.0):
182
self.name = name
183
self.visible = visible
184
self.opacity = opacity
185
186
def observe(self, func, names):
187
pass
188
189
def calculate_vis_minmax(
190
self,
191
*,
192
bounds: ee.Geometry | ee.Feature | ee.FeatureCollection,
193
bands: list[str] | None = None,
194
percent: float | None = None,
195
sigma: float | None = None,
196
) -> tuple[float, float]:
197
del bounds, bands, percent, sigma # Unused.
198
return 21, 42
199
200
201
class FakeTileLayer(ipywidgets.Widget):
202
"""A fake tile layer."""
203
204
name = traitlets.Unicode("").tag(sync=True)
205
visible = traitlets.Bool(True).tag(sync=True)
206
opacity = traitlets.Float(1).tag(sync=True)
207
loading = traitlets.Bool(False).tag(sync=True)
208
209
def __init__(self, name="test-layer", visible=True, opacity=1.0):
210
super().__init__()
211
self.name = name
212
self.visible = visible
213
self.opacity = opacity
214
215
216
class FakeGeoJSONLayer:
217
def __init__(self, name="test-layer", visible=True, style=None):
218
self.name = name
219
self.visible = visible
220
self.style = style or {}
221
222
def observe(self, func, names):
223
pass
224
225