geo-activity-playground 1.3.0__py3-none-any.whl → 1.3.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.
@@ -13,7 +13,7 @@ from scipy.interpolate import RegularGridInterpolator
13
13
  from .paths import USER_CACHE_DIR
14
14
 
15
15
 
16
- def s3_path(lat: int, lon: int) -> pathlib.Path:
16
+ def _s3_path(lat: int, lon: int) -> pathlib.Path:
17
17
  lat_str = f"N{(lat):02d}" if lat >= 0 else f"S{(-lat):02d}"
18
18
  lon_str = f"E{(lon):03d}" if lon >= 0 else f"W{(-lon):03d}"
19
19
  result = (
@@ -26,7 +26,7 @@ def s3_path(lat: int, lon: int) -> pathlib.Path:
26
26
  return result
27
27
 
28
28
 
29
- def ensure_copernicus_file(p: pathlib.Path) -> None:
29
+ def _ensure_copernicus_file(p: pathlib.Path) -> None:
30
30
  if p.exists():
31
31
  return
32
32
  s3 = boto3.client(
@@ -39,10 +39,12 @@ def ensure_copernicus_file(p: pathlib.Path) -> None:
39
39
 
40
40
 
41
41
  @functools.lru_cache(9)
42
- def get_elevation_arrays(p: pathlib.Path) -> Optional[np.ndarray]:
43
- ensure_copernicus_file(p)
42
+ def _get_elevation_arrays(p: pathlib.Path) -> Optional[np.ndarray]:
43
+
44
+ _ensure_copernicus_file(p)
44
45
  if not p.exists():
45
46
  return None
47
+
46
48
  gt = geotiff.GeoTiff(p)
47
49
  a = np.array(gt.read())
48
50
  lon_array, lat_array = gt.get_coord_arrays()
@@ -50,8 +52,8 @@ def get_elevation_arrays(p: pathlib.Path) -> Optional[np.ndarray]:
50
52
 
51
53
 
52
54
  @functools.lru_cache(1)
53
- def get_interpolator(lat: int, lon: int) -> Optional[RegularGridInterpolator]:
54
- arrays = get_elevation_arrays(s3_path(lat, lon))
55
+ def _get_interpolator(lat: int, lon: int) -> Optional[RegularGridInterpolator]:
56
+ arrays = _get_elevation_arrays(_s3_path(lat, lon))
55
57
  # If we don't have data for the current center, we cannot do anything.
56
58
  if arrays is None:
57
59
  return None
@@ -88,7 +90,7 @@ def get_interpolator(lat: int, lon: int) -> Optional[RegularGridInterpolator]:
88
90
 
89
91
 
90
92
  def get_elevation(lat: float, lon: float) -> float:
91
- interpolator = get_interpolator(math.floor(lat), math.floor(lon))
93
+ interpolator = _get_interpolator(math.floor(lat), math.floor(lon))
92
94
  if interpolator is not None:
93
95
  return float(interpolator((lat, lon)))
94
96
  else:
@@ -1,5 +1,6 @@
1
1
  import datetime
2
2
  import logging
3
+ import uuid
3
4
  import zoneinfo
4
5
  from typing import Callable
5
6
 
@@ -8,7 +9,6 @@ import pandas as pd
8
9
 
9
10
  from .config import Config
10
11
  from .coordinates import get_distance
11
- from .copernicus_dem import get_elevation
12
12
  from .datamodel import Activity
13
13
  from .datamodel import DB
14
14
  from .missing_values import some
@@ -108,6 +108,8 @@ def enrichment_compute_tile_xy(
108
108
  def enrichment_copernicus_elevation(
109
109
  activity: Activity, time_series: pd.DataFrame, config: Config
110
110
  ) -> bool:
111
+ from .copernicus_dem import get_elevation
112
+
111
113
  if "copernicus_elevation" not in time_series.columns:
112
114
  time_series["copernicus_elevation"] = [
113
115
  get_elevation(lat, lon)
@@ -246,7 +248,7 @@ enrichments: list[Callable[[Activity, pd.DataFrame, Config], bool]] = [
246
248
  enrichment_normalize_time,
247
249
  enrichment_rename_altitude,
248
250
  enrichment_compute_tile_xy,
249
- enrichment_copernicus_elevation,
251
+ # enrichment_copernicus_elevation,
250
252
  enrichment_elevation_gain,
251
253
  enrichment_add_calories,
252
254
  enrichment_distance,
@@ -268,6 +270,8 @@ def update_and_commit(
268
270
  activity: Activity, time_series: pd.DataFrame, config: Config
269
271
  ) -> None:
270
272
  changed = apply_enrichments(activity, time_series, config)
273
+ if not activity.time_series_uuid:
274
+ activity.time_series_uuid = str(uuid.uuid4())
271
275
  if changed:
272
276
  activity.replace_time_series(time_series)
273
277
  DB.session.add(activity)
@@ -27,6 +27,9 @@ def read_activity(path: pathlib.Path) -> tuple[Activity, pd.DataFrame]:
27
27
  suffixes = [s.lower() for s in path.suffixes]
28
28
  activity = Activity()
29
29
 
30
+ if len(suffixes) == 0:
31
+ raise ActivityParseError(f"File has no suffix, ignoring")
32
+
30
33
  if suffixes[-1] == ".gz":
31
34
  opener = gzip.open
32
35
  file_type = suffixes[-2]
@@ -132,7 +135,13 @@ def read_fit_activity(path: pathlib.Path, open) -> tuple[Activity, pd.DataFrame]
132
135
  factor = _fit_speed_unit_factor(
133
136
  fields["enhanced_speed"].units
134
137
  )
135
- row["speed"] = values["enhanced_speed"] * factor
138
+ try:
139
+ row["speed"] = values["enhanced_speed"] * factor
140
+ except TypeError as e:
141
+ # https://github.com/martin-ueding/geo-activity-playground/issues/301
142
+ raise ActivityParseError(
143
+ f'Cannot work with {values["enhanced_speed"]!r}, {factor!r}'
144
+ ) from e
136
145
  if "grade" in fields:
137
146
  row["grade"] = values["grade"]
138
147
  if "temperature" in fields:
@@ -38,13 +38,15 @@ def import_from_directory(
38
38
  and not path.suffix in config.ignore_suffixes
39
39
  ]
40
40
 
41
- for activity_path in activity_paths:
41
+ for i, activity_path in enumerate(activity_paths):
42
42
  with DB.session.no_autoflush:
43
43
  activity = DB.session.scalar(
44
44
  sqlalchemy.select(Activity).filter(Activity.path == str(activity_path))
45
45
  )
46
46
  if activity is None:
47
- import_from_file(activity_path, repository, tile_visit_accessor, config)
47
+ import_from_file(
48
+ activity_path, repository, tile_visit_accessor, config, i
49
+ )
48
50
 
49
51
 
50
52
  def import_from_file(
@@ -52,6 +54,7 @@ def import_from_file(
52
54
  repository: ActivityRepository,
53
55
  tile_visit_accessor: TileVisitAccessor,
54
56
  config: Config,
57
+ i: int,
55
58
  ) -> None:
56
59
  logger.info(f"Importing {path} …")
57
60
  try:
@@ -74,6 +77,10 @@ def import_from_file(
74
77
 
75
78
  meta_from_path = _get_metadata_from_path(path, config.metadata_extraction_regexes)
76
79
  activity.name = meta_from_path.get("name", activity.name)
80
+ if "equipment" in meta_from_path:
81
+ activity.equipment = get_or_make_equipment(meta_from_path["equipment"], config)
82
+ if "kind" in meta_from_path:
83
+ activity.kind = get_or_make_kind(meta_from_path["kind"])
77
84
  if activity.equipment is None:
78
85
  activity.equipment = get_or_make_equipment(
79
86
  meta_from_path.get("equipment", DEFAULT_UNKNOWN_NAME), config
@@ -85,7 +92,7 @@ def import_from_file(
85
92
 
86
93
  update_and_commit(activity, time_series, config)
87
94
 
88
- if len(repository) > 0:
95
+ if len(repository) > 0 and i % 50 == 0:
89
96
  compute_tile_visits_new(repository, tile_visit_accessor)
90
97
  compute_tile_evolution(tile_visit_accessor.tile_state, config)
91
98
  tile_visit_accessor.save()
@@ -25,6 +25,8 @@ from ..core.paths import strava_api_dir
25
25
  from ..core.paths import strava_last_activity_date_path
26
26
  from ..core.tasks import get_state
27
27
  from ..core.tasks import set_state
28
+ from ..explorer.tile_visits import compute_tile_evolution
29
+ from ..explorer.tile_visits import compute_tile_visits_new
28
30
  from ..explorer.tile_visits import TileVisitAccessor
29
31
 
30
32
 
@@ -3,6 +3,7 @@ import logging
3
3
  import pathlib
4
4
  import shutil
5
5
  import sys
6
+ import urllib.parse
6
7
  import zoneinfo
7
8
  from typing import Optional
8
9
 
@@ -266,7 +267,7 @@ def convert_strava_checkout(
266
267
  "-",
267
268
  f"{activity_date.hour:02d}-{activity_date.minute:02d}-{activity_date.second:02d}",
268
269
  " ",
269
- activity_name.replace("/", "_"),
270
+ urllib.parse.quote_plus(activity_name),
270
271
  ]
271
272
  + activity_file.suffixes
272
273
  )
@@ -131,6 +131,12 @@ def web_ui_main(
131
131
  old_path = TIME_SERIES_DIR() / f"{activity.id}.parquet"
132
132
  if old_path.exists() and not activity.time_series_path.exists():
133
133
  old_path.rename(activity.time_series_path)
134
+ if not activity.time_series_path.exists():
135
+ logger.error(
136
+ f"Time series for {activity.id=}, expected at {activity.time_series_path}, does not exist. Deleting activity."
137
+ )
138
+ DB.session.delete(activity)
139
+ DB.session.commit()
134
140
 
135
141
  if not skip_reload:
136
142
  thread = threading.Thread(
@@ -177,7 +177,7 @@ def make_activity_blueprint(
177
177
  )
178
178
  ) is not None:
179
179
  context["heart_zones_plot"] = heart_rate_zone_plot(heart_zones)
180
- if "copernicus_elevation" in time_series.columns:
180
+ if "elevation" in time_series.columns:
181
181
  context["elevation_time_plot"] = elevation_time_plot(time_series)
182
182
  if "elevation_gain_cum" in time_series.columns:
183
183
  context["elevation_gain_cum_plot"] = elevation_gain_cum_plot(time_series)
@@ -508,7 +508,7 @@ def elevation_time_plot(time_series: pd.DataFrame) -> str:
508
508
  .encode(
509
509
  alt.X("time", title="Time"),
510
510
  alt.Y(
511
- "copernicus_elevation",
511
+ "elevation",
512
512
  scale=alt.Scale(zero=False),
513
513
  title="Elevation / m",
514
514
  ),
@@ -42,6 +42,8 @@
42
42
  <dt>Average elapsed speed</dt>
43
43
  <dd>{{ activity.average_speed_elapsed_kmh|round(1) }} km/h = {{
44
44
  (60/activity.average_speed_elapsed_kmh)|round(1) }} min/km</dd>
45
+ {% endif %}
46
+ {% if date is defined %}
45
47
  <dt>Start time</dt>
46
48
  <dd><a href="{{ url_for('activity.day', year=date.year, month=date.month, day=date.day) }}">{{ date }}</a>
47
49
  {{ time }} {{ activity.iana_timezone }}
@@ -1,13 +1,14 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: geo-activity-playground
3
- Version: 1.3.0
3
+ Version: 1.3.2
4
4
  Summary: Analysis of geo data activities like rides, runs or hikes.
5
5
  License: MIT
6
6
  Author: Martin Ueding
7
7
  Author-email: mu@martin-ueding.de
8
- Requires-Python: >=3.11,<3.14
8
+ Requires-Python: >=3.10,<3.14
9
9
  Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.10
11
12
  Classifier: Programming Language :: Python :: 3.11
12
13
  Classifier: Programming Language :: Python :: 3.12
13
14
  Classifier: Programming Language :: Python :: 3.13
@@ -15,7 +16,6 @@ Requires-Dist: Pillow (>=11.0.0,<12.0.0)
15
16
  Requires-Dist: alembic (>=1.15.2,<2.0.0)
16
17
  Requires-Dist: altair (>=5.5.0,<6.0.0)
17
18
  Requires-Dist: appdirs (>=1.4.4,<2.0.0)
18
- Requires-Dist: boto3 (>=1.38.45,<2.0.0)
19
19
  Requires-Dist: charset-normalizer (>=3.3.2,<4.0.0)
20
20
  Requires-Dist: coloredlogs (>=15.0.1,<16.0.0)
21
21
  Requires-Dist: exifread (>=3.2.0,<4.0.0)
@@ -24,19 +24,15 @@ Requires-Dist: flask (>=3.0.0,<4.0.0)
24
24
  Requires-Dist: flask-alembic (>=3.1.1,<4.0.0)
25
25
  Requires-Dist: flask-sqlalchemy (>=3.1.1,<4.0.0)
26
26
  Requires-Dist: geojson (>=3.0.1,<4.0.0)
27
- Requires-Dist: geotiff (>=0.2.10,<0.3.0)
28
27
  Requires-Dist: gpxpy (>=1.5.0,<2.0.0)
29
- Requires-Dist: imagecodecs (>=2025.3.30,<2026.0.0)
30
28
  Requires-Dist: jinja2 (>=3.1.2,<4.0.0)
31
29
  Requires-Dist: matplotlib (>=3.10.1,<4.0.0)
32
- Requires-Dist: numcodecs (<0.15.0)
33
30
  Requires-Dist: numpy (>=2.2.3,<3.0.0)
34
31
  Requires-Dist: openpyxl (>=3.1.5,<4.0.0)
35
32
  Requires-Dist: pandas (>=2.2.3,<3.0.0)
36
33
  Requires-Dist: pyarrow (>=19.0.1,<20.0.0)
37
34
  Requires-Dist: python-dateutil (>=2.8.2,<3.0.0)
38
35
  Requires-Dist: requests (>=2.28.1,<3.0.0)
39
- Requires-Dist: scipy (>=1.16.0,<2.0.0)
40
36
  Requires-Dist: shapely (>=2.0.5,<3.0.0)
41
37
  Requires-Dist: sqlalchemy (>=2.0.40,<3.0.0)
42
38
  Requires-Dist: stravalib (>=2.0,<3.0)
@@ -20,9 +20,9 @@ geo_activity_playground/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NM
20
20
  geo_activity_playground/core/activities.py,sha256=apP_-Rg1ub3lh7RARMGXf2BOmJTiahxqpX_soEnYF3E,4681
21
21
  geo_activity_playground/core/config.py,sha256=mmdMQ5iCLNGnAlriT1ETEVS-gM6Aq_9sg22QECHj4n8,5358
22
22
  geo_activity_playground/core/coordinates.py,sha256=rW_OmMRpTUyIsQwrT6mgT9Y6uPGuwqTo5XDDMS7mGuo,1140
23
- geo_activity_playground/core/copernicus_dem.py,sha256=U6pvUAymLCX4CpbQKvUoXRj8LYdlaQTKtEVlrlHH3kw,2934
23
+ geo_activity_playground/core/copernicus_dem.py,sha256=t6Bc9fsyGyx1awdePXvlN-Zc-tiT2eGSJ80SV5B1Z9A,2944
24
24
  geo_activity_playground/core/datamodel.py,sha256=3LdTm7lqykeLM6KYviW9WamgnS61nGNl-NHSEQdwTXY,15765
25
- geo_activity_playground/core/enrichment.py,sha256=gb8amLAjpcEYTeseQl6U6kOy8o1p63pzvoOf2f7iryY,8597
25
+ geo_activity_playground/core/enrichment.py,sha256=pw9VEyDAtdNbjQ1HOPYyXCXT8SLL5i3Cp6KWjKK7puM,8708
26
26
  geo_activity_playground/core/export.py,sha256=ayOmhWL72263oP9NLIZRYCg_Db0GLUFhgNIL_MCrV-E,4435
27
27
  geo_activity_playground/core/heart_rate.py,sha256=-S3WAhS7AOywrw_Lk5jfuo_fu6zvZQ1VtjwEKSycWpU,1542
28
28
  geo_activity_playground/core/meta_search.py,sha256=nyvCuR7v0pd6KjA8W5Kr71bBafRdE_ol7uSFRJs4eAM,6662
@@ -51,19 +51,19 @@ geo_activity_playground/explorer/tile_visits.py,sha256=WK_H5fdy3S69BT4zZGP0R92qq
51
51
  geo_activity_playground/explorer/video.py,sha256=7j6Qv3HG6On7Tn7xh7Olwrx_fbQnfzS7CeRg3TEApHg,4397
52
52
  geo_activity_playground/heatmap_video.py,sha256=I8i1uVvbbPUXVtvLAROaLy58nQoUPnuMCZkERWNkQjg,3318
53
53
  geo_activity_playground/importers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
- geo_activity_playground/importers/activity_parsers.py,sha256=HVkW4Ql5vVRPlrhHgJEWeCEc1yTEWQTgJ6rkKOPWAfQ,10955
54
+ geo_activity_playground/importers/activity_parsers.py,sha256=zWgLkHHd8rjWnKs-COBegpAUh7dXxYOJsQL_L2-Qc7M,11435
55
55
  geo_activity_playground/importers/csv_parser.py,sha256=O1pP5GLhWhnWcy2Lsrr9g17Zspuibpt-GtZ3ZS5eZF4,2143
56
- geo_activity_playground/importers/directory.py,sha256=kkutzFliffBjxj1GJrqhMp2cLeiAK6ZGE9Gi6Ptl-NY,3255
57
- geo_activity_playground/importers/strava_api.py,sha256=LG8M8NRSv3kK3npf9gSY20YcqzJ0xiQoVEv0oeDXbNY,8309
58
- geo_activity_playground/importers/strava_checkout.py,sha256=eDzjK0r3rMICSMBtfSlSwwkRxRthWjRUA5zAnblhmNQ,8910
56
+ geo_activity_playground/importers/directory.py,sha256=ucnB5sPBvXzLdaza2v8GVU75ArfGG4E7d5OXrCgoFq4,3562
57
+ geo_activity_playground/importers/strava_api.py,sha256=Fiqlc-VeuzsvgDcWt71JoPMri221cMjkeL4SH80gC5s,8426
58
+ geo_activity_playground/importers/strava_checkout.py,sha256=6RJoGRN3OdEXODeB8yzhT1OJglBGgsaZdNath1rzooA,8937
59
59
  geo_activity_playground/importers/test_csv_parser.py,sha256=nOTVTdlzIY0TDcbWp7xNyNaIO6Mkeu55hVziVl22QE4,1092
60
60
  geo_activity_playground/importers/test_directory.py,sha256=_fn_-y98ZyElbG0BRxAmGFdtGobUShPU86SdEOpuv-A,691
61
61
  geo_activity_playground/importers/test_strava_api.py,sha256=7b8bl5Rh2BctCmvTPEhCadxtUOq3mfzuadD6F5XxRio,398
62
62
  geo_activity_playground/webui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
- geo_activity_playground/webui/app.py,sha256=gvvzPpYTlC5KhMOdpvDtiH2jPyvsLMM9Wf4yWkCoyzc,10020
63
+ geo_activity_playground/webui/app.py,sha256=4dCfzxPk7KJTAwEXyw3NPiQQz-udvgECqeL8CtOj0Es,10334
64
64
  geo_activity_playground/webui/authenticator.py,sha256=dhREYOu_TCD_nzFNuSlHIbf5K6TmwKdXtr1wxD8fBcc,1491
65
65
  geo_activity_playground/webui/blueprints/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
66
- geo_activity_playground/webui/blueprints/activity_blueprint.py,sha256=kfI7GrQUm36GuSNWv8vYQEmT7bshDFrLkWchqesa_9k,26793
66
+ geo_activity_playground/webui/blueprints/activity_blueprint.py,sha256=tFy0GpOBhIP8xlmYc9PF4kAng-0MosXMJudVupGz2Yw,26771
67
67
  geo_activity_playground/webui/blueprints/auth_blueprint.py,sha256=iCm3hZphQKR9qFgytOrfnSmr-Og1gHuQ1Djiv2o_bkE,1031
68
68
  geo_activity_playground/webui/blueprints/bubble_chart_blueprint.py,sha256=8R1rUVoyofGhUgesPunys1HoLPYinvhA46BBnMvEn9Q,2880
69
69
  geo_activity_playground/webui/blueprints/calendar_blueprint.py,sha256=SmOu5AfNNoWcJJNduEfPtaPRvr4EZLYAeIDLUK9P1LY,2939
@@ -126,7 +126,7 @@ geo_activity_playground/webui/templates/activity/day.html.j2,sha256=CHEvxlZralCm
126
126
  geo_activity_playground/webui/templates/activity/edit.html.j2,sha256=r979JPqaZi_2ymTykxpkjdpw0D2tsB9VJaf7OaGPaME,1961
127
127
  geo_activity_playground/webui/templates/activity/lines.html.j2,sha256=_ZDg1ruW-9UMJfOudy1-uY_-IcSSaagq7tPCih5Bb8g,1079
128
128
  geo_activity_playground/webui/templates/activity/name.html.j2,sha256=RYbNGzPexa4gRUWRjw-C9nWvp5lI7agAZZCS3Du7nAs,2661
129
- geo_activity_playground/webui/templates/activity/show.html.j2,sha256=e-jMjZ4fBwK4-u0qZmbiN76ZqrptD4xrGYhxwaUQsEE,10913
129
+ geo_activity_playground/webui/templates/activity/show.html.j2,sha256=gE4RraLi-h63KvHO4oXLDWPcXN1FB6wqMxVKB75Zn0k,10974
130
130
  geo_activity_playground/webui/templates/activity/trim.html.j2,sha256=3oAXQab6QqWjGBC9KCvWNOVn8uRmxoDLj3hx_O63TXc,1836
131
131
  geo_activity_playground/webui/templates/auth/index.html.j2,sha256=wzA0uxpiT1ktDadgnjvFXc9iUGMFm9GhjDkavl3S1h4,646
132
132
  geo_activity_playground/webui/templates/bubble_chart/index.html.j2,sha256=yd7lWjtxxVmJZqCiXb0Y1gMEOQ7LQYJXEdpE7JB1OZY,1616
@@ -171,8 +171,8 @@ geo_activity_playground/webui/templates/summary/vega-chart.html.j2,sha256=mw8Hti
171
171
  geo_activity_playground/webui/templates/time_zone_fixer/index.html.j2,sha256=s9r6BJMXmd7kLSyjkvH4xLi6e01S5bpGRcMgMMJyCAE,1760
172
172
  geo_activity_playground/webui/templates/upload/index.html.j2,sha256=I1Ix8tDS3YBdi-HdaNfjkzYXVVCjfUTe5PFTnap1ydc,775
173
173
  geo_activity_playground/webui/templates/upload/reload.html.j2,sha256=YZWX5eDeNyqKJdQAywDBcU8DZBm22rRBbZqFjrFrCvQ,556
174
- geo_activity_playground-1.3.0.dist-info/LICENSE,sha256=4RpAwKO8bPkfXH2lnpeUW0eLkNWglyG4lbrLDU_MOwY,1070
175
- geo_activity_playground-1.3.0.dist-info/METADATA,sha256=CWWk8dBKRARHREz5Ux11u0U_qtrwqIRHJC-toP7hsLM,2045
176
- geo_activity_playground-1.3.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
177
- geo_activity_playground-1.3.0.dist-info/entry_points.txt,sha256=pbNlLI6IIZIp7nPYCfAtiSiz2oxJSCl7DODD6SPkLKk,81
178
- geo_activity_playground-1.3.0.dist-info/RECORD,,
174
+ geo_activity_playground-1.3.2.dist-info/LICENSE,sha256=4RpAwKO8bPkfXH2lnpeUW0eLkNWglyG4lbrLDU_MOwY,1070
175
+ geo_activity_playground-1.3.2.dist-info/METADATA,sha256=0VFH55TyvrqQZOz60YN1odpofpP3iT7d5w8y2v6O268,1890
176
+ geo_activity_playground-1.3.2.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
177
+ geo_activity_playground-1.3.2.dist-info/entry_points.txt,sha256=pbNlLI6IIZIp7nPYCfAtiSiz2oxJSCl7DODD6SPkLKk,81
178
+ geo_activity_playground-1.3.2.dist-info/RECORD,,