geo-adjacency 1.1.1__py3-none-any.whl → 1.1.2__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.
@@ -1,20 +1,21 @@
1
1
  """
2
2
  The `adjacency` module implements the AdjacencyEngine class,
3
- which allows us to determine adjacency relationships. Adjacency relationships are between a set of source geometries,
4
- or between source geometries and a second set of target geometries. Obstacle geometries can be passed in to
5
- stand between sources or sources and targets, but they are not included in the output.
3
+ which allows us to calculate adjacency relationships. Adjacency relationships are between a set of source geometries,
4
+ or between source geometries and a second set of target geometries. Obstacle geometries can be passed in to
5
+ stand between sources or sources and targets, but they are not included in the output.
6
6
 
7
- For example, if we wanted to know what trees in a forest are adjacent to the shore of a lake, we could
8
- pass in a set of Point geometries to the trees, a Polygon to represent the lake, and a LineString to represent
9
- a road passing between some of the trees and the shore.
7
+ For example, if we wanted to know what trees in a forest are adjacent to the shore of a lake, we could
8
+ pass in a set of Point geometries to the trees, a Polygon to represent the lake, and a LineString to represent
9
+ a road passing between some of the trees and the shore.
10
10
 
11
- `AdjacencyEngine` utilizes a Voronoi of all the vertices in all the geometries combined to determine
12
- which geomtries are adjacent to each other. See
11
+ `AdjacencyEngine` utilizes a Voronoi diagram of all the vertices in all the geometries combined to determine
12
+ which geometries are adjacent to each other. See
13
13
  """
14
14
 
15
15
  import math
16
16
  from collections import defaultdict
17
- from typing import List, Union, Dict, Tuple
17
+ from typing import List, Union, Dict, Tuple, Generator
18
+
18
19
  try:
19
20
  from typing_extensions import Self # Python < 3.11
20
21
  except ImportError:
@@ -39,34 +40,47 @@ from geo_adjacency.utils import (
39
40
  )
40
41
 
41
42
  # ToDo: Support geometries with Z-coordinates
42
-
43
43
  # Create a custom logger
44
- logger = logging.getLogger(__name__)
44
+ log: logging.Logger = logging.getLogger(__name__)
45
45
 
46
46
  # Create handlers
47
- c_handler = logging.StreamHandler()
47
+ c_handler: logging.StreamHandler = logging.StreamHandler()
48
48
  c_handler.setLevel(logging.WARNING)
49
49
 
50
50
  # Create formatters and add it to handlers
51
- c_format = logging.Formatter("%(name)s - %(levelname)s - %(message)s")
52
- f_format = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
51
+ c_format: logging.Formatter = logging.Formatter("%(name)s - %(levelname)s - %(message)s")
52
+ f_format: logging.Formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
53
53
  c_handler.setFormatter(c_format)
54
54
 
55
55
  # Add handlers to the logger
56
- logger.addHandler(c_handler)
56
+ log.addHandler(c_handler)
57
57
 
58
58
 
59
59
  class _Feature:
60
+ """
61
+ A _Feature is a wrapper around a Shapely geometry that allows us to easily determine if two
62
+ geometries are adjacent.
63
+ """
60
64
  __slots__ = ("_geometry", "_coords", "voronoi_points")
61
65
 
62
66
  def __init__(self, geometry: BaseGeometry):
67
+ """
68
+ Create a _Feature from a Shapely geometry.
69
+
70
+ Args:
71
+ geometry (BaseGeometry): A valid Shapely Geometry, either a Point, LineString, Polygon, or
72
+ MultiPolygon.
73
+ """
74
+
63
75
  if not isinstance(geometry, (Point, Polygon, MultiPolygon, LineString)):
64
76
  raise TypeError(
65
- "Cannot create _Feature for geometry type '%s'." % type(self.geometry)
77
+ "Cannot create _Feature for geometry type '%s'." % type(geometry)
66
78
  )
67
79
 
80
+ assert geometry.is_valid, "Could not process invalid geometry: %s" % geometry.wkt
81
+
68
82
  self._geometry: BaseGeometry = geometry
69
- self._coords = None
83
+ self._coords: Union[List[Tuple[float, float]], None] = None
70
84
  self.voronoi_points: set = set()
71
85
 
72
86
  def __str__(self):
@@ -75,32 +89,30 @@ class _Feature:
75
89
  def __repr__(self):
76
90
  return f"<_Feature: {str(self.geometry)}>"
77
91
 
78
- def __eq__(self, other: Self):
79
- if not isinstance(other, type(self)):
80
- return False
81
- return self.geometry.equals_exact(other.geometry, 1e-8)
82
-
83
- def __ne__(self, other: Self):
84
- return not self.__eq__(other)
85
-
86
- def is_adjacent(
92
+ def _is_adjacent(
87
93
  self, other: Self, min_overlapping_voronoi_vertices: int = 2
88
94
  ) -> bool:
89
95
  """
90
96
  Determine if two features are adjacent based on how many Voronoi vertices they share. Note:
91
97
  the Voronoi analysis must have been run, or this will always return False.
92
- :param min_overlapping_voronoi_vertices:
93
- :param other:
94
- :return:
98
+ Args:
99
+ other (_Feature): Another _Feature to compare to.
100
+ min_overlapping_voronoi_vertices (int): The minimum number of Voronoi vertices that
101
+ must be shared to be considered adjacent.
102
+
103
+ Returns:
104
+ bool: True if the two features are adjacent.
105
+
95
106
  """
96
107
  assert isinstance(other, type(self)), "Cannot compare '%s' with '%s'." % (
97
108
  type(self),
98
109
  type(other),
99
110
  )
100
111
  if len(self.voronoi_points) == 0 and len(other.voronoi_points) == 0:
101
- logger.warning(
112
+ log.warning(
102
113
  "No Voronoi vertices found for either feature. Did you run the analysis yet?"
103
114
  )
115
+ return False
104
116
  return (
105
117
  len(self.voronoi_points & other.voronoi_points)
106
118
  >= min_overlapping_voronoi_vertices
@@ -110,7 +122,10 @@ class _Feature:
110
122
  def geometry(self):
111
123
  """
112
124
  Access the Shapely geometry of the feature.
113
- :return: BaseGeometry
125
+
126
+ Returns:
127
+ BaseGeometry: The Shapely geometry of the feature.
128
+
114
129
  """
115
130
  return self._geometry
116
131
 
@@ -124,7 +139,9 @@ class _Feature:
124
139
  """
125
140
  Convenience property for accessing the coordinates of the geometry as a list of 2-tuples.
126
141
 
127
- :return: List[Tuple[float, float]]: A list of coordinate tuples.
142
+ Returns:
143
+ List[Tuple[float, float]]: A list of coordinate tuples.
144
+
128
145
  """
129
146
 
130
147
  if not self._coords:
@@ -140,6 +157,10 @@ class _Feature:
140
157
  raise TypeError(f"Unknown geometry type '{type(self.geometry)}'")
141
158
  return self._coords
142
159
 
160
+ @coords.setter
161
+ def coords(self, coords):
162
+ raise ImmutablePropertyError("Property coords is immutable.")
163
+
143
164
 
144
165
  class AdjacencyEngine:
145
166
  """
@@ -149,9 +170,6 @@ class AdjacencyEngine:
149
170
  First, the Voronoi diagram is generated for each geometry and obstacle. Then, we check which
150
171
  voronoi shapes intersect one another. If they do, then the two underlying geometries are
151
172
  adjacent.
152
-
153
- :ivar all_features: List of all features in order of source, target, and obstacle.
154
- :ivar all_coordinates: List of all coordinates in the same order as all_features.
155
173
  """
156
174
 
157
175
  __slots__ = (
@@ -161,7 +179,7 @@ class AdjacencyEngine:
161
179
  "_adjacency_dict",
162
180
  "_feature_indices",
163
181
  "_vor",
164
- "all_features",
182
+ "_all_features",
165
183
  "_all_coordinates",
166
184
  )
167
185
 
@@ -174,24 +192,23 @@ class AdjacencyEngine:
174
192
  max_segment_length: Union[float, None] = None,
175
193
  ):
176
194
  """
177
- Note: only Multipolygons, Polygons, LineStrings and Points are supported. It is assumed all
195
+ Note: only Multipolygons, Polygons, LineStrings and Points are supported. It is assumed all
178
196
  features are in the same projection.
179
197
 
180
- :param source_geoms: List of Shapely geometries. We will which ones are adjacent to
181
- which others.
182
- :param target_geoms: Optional list of Shapley geometries. if not None, We will
198
+ Args:
199
+ source_geoms (List[BaseGeometry]): List of Shapely geometries. We will which ones are adjacent to
200
+ which others, unless target_geoms is specified.
201
+ target_geoms (Union[List[BaseGeometry], None]), optional): list of Shapley geometries. if not None, We will
183
202
  test if these features are adjacent to the source features.
184
- :param obstacle_geoms: List
203
+ obstacle_geoms (Union[List[BaseGeometry], None]), optional): List
185
204
  of Shapely geometries. These features will not be tested for adjacency, but they can
186
205
  prevent a source and target feature from being adjacent.
187
- :param densify_features: If
206
+ densify_features (bool, optional): If
188
207
  True, we will add additional points to the features to improve accuracy of the voronoi
189
- diagram.
190
- :param max_segment_length: The maximum distance between vertices that we want.
191
- In projection units. densify_features must be True, or an error will be thrown. If
192
- densify_features is True and max_segment_length is false, then the max_segment_length
208
+ diagram. If densify_features is True and max_segment_length is false, then the max_segment_length
193
209
  will be calculated based on the average segment length of all features, divided by 5.
194
- This often works well.
210
+ max_segment_length (Union[float, None], optional): The maximum distance between vertices that we want.
211
+ In projection units. densify_features must be True, or an error will be thrown.
195
212
  """
196
213
 
197
214
  if max_segment_length and not densify_features:
@@ -212,21 +229,21 @@ class AdjacencyEngine:
212
229
  if obstacle_geoms
213
230
  else tuple()
214
231
  )
215
- self._adjacency_dict = None
216
- self._feature_indices = None
232
+ self._adjacency_dict: Union[Dict[int, List[int]], None] = None
233
+ self._feature_indices: Union[Dict[int, int], None] = None
217
234
  self._vor = None
218
235
  self._all_coordinates = None
219
236
 
220
237
  """All source, target, and obstacle features in a single list. The order of this list must
221
238
  not be changed."""
222
- self.all_features: Tuple[_Feature, ...] = tuple(
239
+ self._all_features: Tuple[_Feature, ...] = tuple(
223
240
  [*self.source_features, *self.target_features, *self.obstacle_features]
224
241
  )
225
242
 
226
243
  if densify_features:
227
244
  if max_segment_length is None:
228
- max_segment_length = self.calc_segmentation_dist()
229
- logger.info("Calculated max_segment_length of %s" % max_segment_length)
245
+ max_segment_length = self._calc_segmentation_dist()
246
+ log.info("Calculated max_segment_length of %s" % max_segment_length)
230
247
 
231
248
  for feature in self.all_features:
232
249
  if not isinstance(feature.geometry, Point):
@@ -234,8 +251,32 @@ class AdjacencyEngine:
234
251
  # Reset all coordinates
235
252
  self._all_coordinates = None
236
253
 
254
+ @property
255
+ def all_features(self):
256
+ """
257
+ All source, target, and obstacle features in a single list. The order of this list must
258
+ not be changed. This property cannot be set manually.
259
+
260
+ Returns:
261
+ List[_Feature]: A list of _Features.
262
+
263
+ """
264
+ return self._all_features
265
+
266
+ @all_features.setter
267
+ def all_features(self, value):
268
+ raise ImmutablePropertyError("Property all_features is immutable.")
269
+
237
270
  @property
238
271
  def all_coordinates(self):
272
+ """
273
+ All source, target, and obstacle coordinates in a single list. The order of this list must
274
+ not be changed. This property cannot be set manually.
275
+
276
+ Returns:
277
+ List[tuple[float, float]]: A list of coordinate tuples.
278
+ """
279
+
239
280
  if not self._all_coordinates:
240
281
  self._all_coordinates = []
241
282
  for feature in self.all_features:
@@ -248,7 +289,7 @@ class AdjacencyEngine:
248
289
  def all_coordinates(self, value):
249
290
  raise ImmutablePropertyError("Property all_coordinates is immutable.")
250
291
 
251
- def calc_segmentation_dist(self, divisor=5):
292
+ def _calc_segmentation_dist(self, divisor=5):
252
293
  """
253
294
  Try to create a well-fitting maximum length for all line segments in all features. Take
254
295
  the average distance between all coordinate pairs and divide by 5. This means that the
@@ -258,10 +299,12 @@ class AdjacencyEngine:
258
299
  average segment lengths. In that case, it is advisable to prepare the data appropriately
259
300
  beforehand.
260
301
 
261
- :param divisor: Divide the average segment length by this number to get the new desired
302
+ Args:
303
+ divisor (int, optional): Divide the average segment length by this number to get the new desired
262
304
  segment length.
263
305
 
264
- :return: Average segment length divided by divisor
306
+ Returns:
307
+ float: Average segment length divided by divisor.
265
308
  """
266
309
 
267
310
  return float(
@@ -276,7 +319,10 @@ class AdjacencyEngine:
276
319
  def source_features(self) -> Tuple[_Feature]:
277
320
  """
278
321
  Features which will be the keys in the adjacency_dict.
279
- :return: List of source features.
322
+
323
+ Returns:
324
+ List[_Feature]: A list of _Features.
325
+
280
326
  """
281
327
  return self._source_features
282
328
 
@@ -288,7 +334,8 @@ class AdjacencyEngine:
288
334
  def target_features(self) -> Tuple[_Feature]:
289
335
  """
290
336
  Features which will be the values in the adjacency_dict.
291
- :return: List of target features.
337
+ Returns:
338
+ List[_Feature]: A list of _Features.
292
339
  """
293
340
  return self._target_features
294
341
 
@@ -301,7 +348,9 @@ class AdjacencyEngine:
301
348
  """
302
349
  Features which can prevent source and target features from being adjacent. They
303
350
  Do not participate in the adjacency_dict.
304
- :return: List of obstacle features.
351
+
352
+ Returns:
353
+ List[_Feature]: A list of _Features.
305
354
  """
306
355
  return self._obstacle_features
307
356
 
@@ -316,8 +365,11 @@ class AdjacencyEngine:
316
365
  determine which coordinate belongs to which feature after we calculate the voronoi
317
366
  diagram.
318
367
 
319
- :return: A _Feature.
368
+ Args:
369
+ coord_index (int): The index of the coordinate in self._all_coordinates
320
370
 
371
+ Returns:
372
+ _Feature: A _Feature at the given index.
321
373
  """
322
374
  if not self._feature_indices:
323
375
  self._feature_indices = {}
@@ -335,9 +387,9 @@ class AdjacencyEngine:
335
387
  The Voronoi diagram object returned by Scipy. Useful primarily for debugging an
336
388
  adjacency analysis.
337
389
 
338
- :return: Voronoi object.
390
+ Returns:
391
+ scipy.spatial.Voronoi: The Scipy Voronoi object.
339
392
  """
340
-
341
393
  if not self._vor:
342
394
  self._vor = Voronoi(np.array(self.all_coordinates))
343
395
  return self._vor
@@ -346,12 +398,27 @@ class AdjacencyEngine:
346
398
  def vor(self, _):
347
399
  raise ImmutablePropertyError("Property vor is immutable.")
348
400
 
401
+ def _get_voronoi_vertex_idx_for_coord_idx(self, feature_coord_index: int) -> Generator[int, None, None]:
402
+ """
403
+ For a given feature coordinate index, return the indices of the voronoi vertices. Ignore
404
+ any "-1"s, which indicate vertices at infinity; these provide no adjacency information.
405
+
406
+ Args:
407
+ feature_coord_index (int): The index of the coordinate in self.all_coordinates
408
+
409
+ Returns:
410
+ Generator[int, None, None]: A generator of the indices of the voronoi vertices.
411
+ """
412
+ return (i for i in self.vor.regions[self.vor.point_region[feature_coord_index]] if i != -1)
413
+
349
414
  def _tag_feature_with_voronoi_vertices(self):
350
415
  """
351
416
  Tag each feature with the vertices of the voronoi region it belongs to. Runs the
352
417
  voronoi analysis if it has not been done already. This is broken out mostly for testing.
353
418
  Do not call this function directly.
354
- :return:
419
+
420
+ Returns:
421
+ None
355
422
  """
356
423
  # We don't need to tag obstacles with their voronoi vertices
357
424
  obstacle_coord_len = sum(len(feat.coords) for feat in self.obstacle_features)
@@ -362,29 +429,25 @@ class AdjacencyEngine:
362
429
  len(self.all_coordinates) - obstacle_coord_len
363
430
  ):
364
431
  feature = self.get_feature_from_coord_index(feature_coord_index)
365
- for voronoi_vertex_index in self.vor.regions[
366
- self.vor.point_region[feature_coord_index]
367
- ]:
368
- # "-1" indices indicate the vertex goes to infinity. These don't provide us
369
- # with adjacency information, so we ignore them.
370
- if voronoi_vertex_index != -1:
371
- feature.voronoi_points.add(voronoi_vertex_index)
432
+ for i in self._get_voronoi_vertex_idx_for_coord_idx(feature_coord_index):
433
+ feature.voronoi_points.add(i)
372
434
 
373
435
  def _determine_adjacency(
374
436
  self, source_set: Tuple[_Feature], target_set: Tuple[_Feature]
375
437
  ):
376
438
  """
377
439
  Determines the adjacency relationship between two sets of features.
378
- Parameters:
440
+ Args:
379
441
  source_set (Tuple[_Feature]): The set of source features.
380
442
  target_set (Tuple[_Feature]): The set of target features.
443
+
381
444
  Returns:
382
445
  None
383
446
  """
384
447
  min_overlapping_voronoi_vertices = 2
385
448
  for source_index, source_feature in enumerate(source_set):
386
449
  for target_index, target_feature in enumerate(target_set):
387
- if source_feature != target_feature and source_feature.is_adjacent(
450
+ if source_feature != target_feature and source_feature._is_adjacent(
388
451
  target_feature, min_overlapping_voronoi_vertices
389
452
  ):
390
453
  self._adjacency_dict[source_index].append(target_index)
@@ -397,12 +460,14 @@ class AdjacencyEngine:
397
460
  If no targets were specified, then calculate adjacency between source features and other
398
461
  source features.
399
462
 
400
- :return: dict A dictionary of indices. The keys are the indices of feature_geoms. The
401
- values are the indices of any adjacent features
463
+ Returns:
464
+ dict: A dictionary of indices. The keys are the indices of feature_geoms. The
465
+ values are the indices of any adjacent features.
466
+
402
467
  """
403
468
 
404
- # We want adjacent features to have at least two overlapping vertices, otherwise we might
405
- # call the features adjacent when their voronoi regions don't share any edges.
469
+ """Note: We want adjacent features to have at least two overlapping vertices, otherwise we
470
+ might call the features adjacent when their Voronoi regions don't share any edges."""
406
471
 
407
472
  if self._adjacency_dict is None:
408
473
  self._tag_feature_with_voronoi_vertices()
@@ -424,7 +489,9 @@ class AdjacencyEngine:
424
489
  """
425
490
  Plot the adjacency linkages between the source and target with pyplot. Runs the analysis if
426
491
  it has not already been run.
427
- :return: None
492
+
493
+ Returns:
494
+ None
428
495
  """
429
496
  # Plot the adjacency linkages between the source and target
430
497
  if len(self.target_features) > 0:
@@ -445,7 +512,7 @@ class AdjacencyEngine:
445
512
  )
446
513
  )
447
514
  except ValueError:
448
- logger.error(
515
+ log.error(
449
516
  f"Error creating link between '{target_poly}' and '{source_poly}'"
450
517
  )
451
518
  add_geometry_to_plot(links, "green")
geo_adjacency/utils.py CHANGED
@@ -13,8 +13,13 @@ def coords_from_point(point: Point) -> List[Tuple[float, float]]:
13
13
  """
14
14
  Convert a Point into a tuple of (x, y). We put this inside a list for consistency with other
15
15
  coordinate methods to allow us to seamlessly merge them later.
16
- :param point: A Shapely Point.
17
- :return:
16
+
17
+ Args:
18
+ point (Point): A Shapely Point.
19
+
20
+ Returns:
21
+ List[Tuple[float, float]]: A list of coordinate tuples.
22
+
18
23
  """
19
24
  assert isinstance(point, Point), "Geometry must be a Point, not '%s'." % type(point)
20
25
  return [(float(point.x), float(point.y))]
@@ -22,9 +27,13 @@ def coords_from_point(point: Point) -> List[Tuple[float, float]]:
22
27
 
23
28
  def coords_from_ring(ring: LineString) -> List[Tuple[float, float]]:
24
29
  """
25
- Convert a LinearRing into a list of (x, y) tuples
26
- :param ring: A Shapely LinearRing.
27
- :return:
30
+ Convert a LinearRing into a list of (x, y) tuples.
31
+
32
+ Args:
33
+ ring (LineString): A Shapely LinearString.
34
+
35
+ Returns:
36
+ List[Tuple[float, float]]: A list of coordinate tuples.
28
37
  """
29
38
  assert isinstance(
30
39
  ring, LineString
@@ -36,8 +45,12 @@ def coords_from_polygon(polygon: Polygon) -> List[Tuple[float, float]]:
36
45
  """
37
46
  Convert a Polygon into a list of (x, y) tuples. Does not repeat the first coordinate to close
38
47
  the ring.
39
- :param polygon: A Shapely Polygon.
40
- :return:
48
+
49
+ Args:
50
+ polygon (Polygon): A Shapely Polygon.
51
+
52
+ Returns:
53
+ List[Tuple[float, float]]: A list of coordinate tuples.
41
54
  """
42
55
  assert isinstance(polygon, Polygon), "Geometry must be a Polygon, not '%s'." % type(
43
56
  polygon
@@ -53,8 +66,12 @@ def coords_from_multipolygon(multipolygon: MultiPolygon) -> List[Tuple[float, fl
53
66
  """
54
67
  Convert a MultiPolygon into a list of (x, y) tuples. Does not repeat the first coordinate to
55
68
  close the ring.
56
- :param multipolygon: A Shapely MultiPolygon.
57
- :return:
69
+
70
+ Args:
71
+ multipolygon (MultiPolygon): A Shapely MultiPolygon.
72
+
73
+ Returns:
74
+ List[Tuple[float, float]]: A list of coordinate tuples.
58
75
  """
59
76
  assert isinstance(
60
77
  multipolygon, MultiPolygon
@@ -68,8 +85,11 @@ def coords_from_multipolygon(multipolygon: MultiPolygon) -> List[Tuple[float, fl
68
85
  def flatten_list(nested_list) -> List:
69
86
  """
70
87
  Flatten a list of lists.
71
- :param nested_list: A list of lists.
72
- :return:
88
+ Args:
89
+ nested_list (List): A list of lists.
90
+
91
+ Returns:
92
+
73
93
  """
74
94
  # check if list is empty
75
95
  if not bool(nested_list):
@@ -88,9 +108,13 @@ def add_geometry_to_plot(geoms, color="black"):
88
108
  """
89
109
  When updating the test data, it may be useful to visualize it. Add a geometry to the global
90
110
  maplotlib plt object. The next time we call plt.show(), this geometry will be plotted.
91
- :param geoms: A list of Shapely geometries.
92
- :param color: The color we want the geometry to be in the plot.
93
- :return: None
111
+
112
+ Args:
113
+ geoms (List[BaseGeometry]): A list of Shapely geometries.
114
+ color (str): The color we want the geometry to be in the plot.
115
+
116
+ Returns:
117
+ None
94
118
  """
95
119
  for geom in geoms:
96
120
  if isinstance(geom, Point):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: geo-adjacency
3
- Version: 1.1.1
3
+ Version: 1.1.2
4
4
  Summary: A package to determine which geometries are adjacent to each other, accounting for obstacles and gaps between features.
5
5
  Home-page: https://asmyth01.github.io/geo-adjacency/
6
6
  License: MIT
@@ -0,0 +1,8 @@
1
+ geo_adjacency/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ geo_adjacency/adjacency.py,sha256=bL6ErCwgtpvNu0XfgpQwCJ6RlK2M-vi-qx_veE1_0Rk,20844
3
+ geo_adjacency/exception.py,sha256=zZNdBOm5LpuiCpNuqH1FNLhiPnQqyCyuhOTMBDnLSTQ,230
4
+ geo_adjacency/utils.py,sha256=57Q-nRZQlW1QetlLoucbDr1jm3CRHYRCVzrarm7xxZw,4188
5
+ geo_adjacency-1.1.2.dist-info/LICENSE,sha256=p0PMGdB2iuOndKPbBCVhTNe9TMIxZRpJ64bQ_CoUIqY,1065
6
+ geo_adjacency-1.1.2.dist-info/METADATA,sha256=fpHyeHH726bndsYxfE_CWAtJLmBN9MlN3lFiraRX8PA,3857
7
+ geo_adjacency-1.1.2.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
8
+ geo_adjacency-1.1.2.dist-info/RECORD,,
geo_adjacency/file.log DELETED
@@ -1,10 +0,0 @@
1
- 2023-11-20 19:19:58,755 - __main__ - ERROR - This is an error
2
- 2023-11-20 19:21:23,871 - __main__ - ERROR - This is an error
3
- 2023-11-20 19:22:38,493 - __main__ - ERROR - This is an error
4
- 2023-11-20 19:22:48,026 - __main__ - ERROR - This is an error
5
- 2023-11-20 19:23:34,369 - __main__ - ERROR - This is an error
6
- 2023-11-20 19:23:44,297 - __main__ - ERROR - This is an error
7
- 2023-11-20 19:26:28,000 - __main__ - ERROR - This is an error
8
- 2023-11-20 19:26:58,737 - __main__ - ERROR - This is an error
9
- 2023-11-20 19:28:41,686 - __main__ - ERROR - This is an error
10
- 2023-11-20 19:29:03,485 - __main__ - ERROR - This is an error
@@ -1,9 +0,0 @@
1
- geo_adjacency/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- geo_adjacency/adjacency.py,sha256=owrsKi-SnCHa14JQGjW_lVXCKVz1yO5-Fr3r1Vp7Wpk,18598
3
- geo_adjacency/exception.py,sha256=zZNdBOm5LpuiCpNuqH1FNLhiPnQqyCyuhOTMBDnLSTQ,230
4
- geo_adjacency/file.log,sha256=Zc7rMTU9N_LJKx68zsOwDJcuTnD8Mxll3iHlmZWQUzg,620
5
- geo_adjacency/utils.py,sha256=YiyNDj-Ye6gK883Mg52lIabb0M5g8W5rj6-3aotvhdg,3789
6
- geo_adjacency-1.1.1.dist-info/LICENSE,sha256=p0PMGdB2iuOndKPbBCVhTNe9TMIxZRpJ64bQ_CoUIqY,1065
7
- geo_adjacency-1.1.1.dist-info/METADATA,sha256=QEWLk4kTRQ9NYlYhhG_QPfS_FfjPmbpPIan6zwfXjkM,3857
8
- geo_adjacency-1.1.1.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
9
- geo_adjacency-1.1.1.dist-info/RECORD,,