osmsg 1.2.3__tar.gz → 1.2.4__tar.gz

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.
Files changed (44) hide show
  1. {osmsg-1.2.3 → osmsg-1.2.4}/PKG-INFO +1 -1
  2. osmsg-1.2.4/osmsg/__version__.py +1 -0
  3. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/_http.py +7 -3
  4. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/gui.py +26 -0
  5. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/pipeline.py +26 -6
  6. {osmsg-1.2.3 → osmsg-1.2.4}/pyproject.toml +1 -1
  7. osmsg-1.2.3/osmsg/__version__.py +0 -1
  8. {osmsg-1.2.3 → osmsg-1.2.4}/LICENSE +0 -0
  9. {osmsg-1.2.3 → osmsg-1.2.4}/README.md +0 -0
  10. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/__init__.py +0 -0
  11. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/_tick.py +0 -0
  12. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/auth.py +0 -0
  13. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/boundary.py +0 -0
  14. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/cli.py +0 -0
  15. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/db/__init__.py +0 -0
  16. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/db/duckdb_schema.py +0 -0
  17. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/db/ingest.py +0 -0
  18. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/db/queries.py +0 -0
  19. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/db/schema.py +0 -0
  20. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/exceptions.py +0 -0
  21. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/export/__init__.py +0 -0
  22. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/export/csv.py +0 -0
  23. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/export/json.py +0 -0
  24. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/export/markdown.py +0 -0
  25. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/export/parquet.py +0 -0
  26. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/export/psql.py +0 -0
  27. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/fetch.py +0 -0
  28. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/geofabrik.py +0 -0
  29. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/handlers.py +0 -0
  30. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/history.py +0 -0
  31. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/maintain/__init__.py +0 -0
  32. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/maintain/cli.py +0 -0
  33. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/maintain/convert.py +0 -0
  34. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/maintain/manifest.py +0 -0
  35. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/maintain/month.py +0 -0
  36. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/maintain/parquet.py +0 -0
  37. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/maintain/pbf_split.py +0 -0
  38. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/models.py +0 -0
  39. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/pg_schema.py +0 -0
  40. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/py.typed +0 -0
  41. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/replication.py +0 -0
  42. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/tm.py +0 -0
  43. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/ui.py +0 -0
  44. {osmsg-1.2.3 → osmsg-1.2.4}/osmsg/workers.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: osmsg
3
- Version: 1.2.3
3
+ Version: 1.2.4
4
4
  Summary: OpenStreetMap Stats Generator: Commandline
5
5
  Keywords: osm,stats,commandline,openstreetmap
6
6
  Author: Kshitij Raj Sharma
@@ -0,0 +1 @@
1
+ __version__ = "1.2.4"
@@ -11,7 +11,7 @@ from requests.adapters import HTTPAdapter
11
11
  from urllib3.util.retry import Retry
12
12
 
13
13
  USER_AGENT = "osmsg"
14
- DEFAULT_TIMEOUT = (10, 60) # (connect, read) seconds
14
+ DEFAULT_TIMEOUT = (30, 120) # (connect, read) seconds
15
15
 
16
16
 
17
17
  class _TimeoutSession(requests.Session):
@@ -26,10 +26,14 @@ def make_session() -> requests.Session:
26
26
  """Fresh session with the standard timeout + retry policy (use when a flow needs its own cookie jar)."""
27
27
  s = _TimeoutSession()
28
28
  retry = Retry(
29
- total=5,
30
- backoff_factor=0.5,
29
+ total=10,
30
+ connect=10,
31
+ read=10,
32
+ backoff_factor=1.0,
33
+ backoff_max=120,
31
34
  status_forcelist=(429, 500, 502, 503, 504),
32
35
  allowed_methods=frozenset({"GET", "POST", "HEAD"}),
36
+ respect_retry_after_header=True,
33
37
  )
34
38
  adapter = HTTPAdapter(max_retries=retry, pool_maxsize=32)
35
39
  s.mount("https://", adapter)
@@ -7,14 +7,21 @@ import os
7
7
  import queue
8
8
  import sys
9
9
  import threading
10
+ import webbrowser
10
11
  from pathlib import Path
11
12
  from typing import Any
12
13
 
14
+ from .__version__ import __version__
13
15
  from .exceptions import NoDataFoundError, OsmsgError
14
16
  from .pipeline import RunConfig, run
15
17
 
16
18
  UTC = dt.UTC
17
19
  FORMATS = ["parquet", "csv", "json", "markdown"]
20
+ ABOUT_LINKS = [
21
+ ("Star osmsg on GitHub", "https://github.com/osgeonepal/osmsg"),
22
+ ("Report a bug or request a feature", "https://github.com/osgeonepal/osmsg/issues"),
23
+ ("Sponsor the developer", "https://github.com/sponsors/kshitijrajsharma"),
24
+ ]
18
25
  PRESETS = ["Last hour", "Last day", "Last week", "Last month", "Last year", "All time"]
19
26
  _PRESET_DELTAS = {
20
27
  "Last hour": dt.timedelta(hours=1),
@@ -109,6 +116,7 @@ class App:
109
116
  from tkinter import filedialog, scrolledtext, ttk
110
117
 
111
118
  self._tk = tk
119
+ self._ttk = ttk
112
120
  self._filedialog = filedialog
113
121
  self.events: queue.Queue = queue.Queue()
114
122
  self.out_dir = str(Path.home() / "osmsg")
@@ -164,8 +172,26 @@ class App:
164
172
 
165
173
  self.log = scrolledtext.ScrolledText(frame, width=70, height=14, state="disabled")
166
174
  self.log.grid(row=10, column=0, columnspan=4, sticky="nsew")
175
+
176
+ ttk.Button(frame, text="About", command=self._show_about).grid(row=11, column=0, pady=(6, 0), sticky="w")
177
+ ttk.Label(frame, text="A project of OSGeo Nepal").grid(row=11, column=1, columnspan=3, pady=(6, 0), sticky="e")
167
178
  self.root.after(120, self._drain)
168
179
 
180
+ def _show_about(self) -> None:
181
+ tk, ttk = self._tk, self._ttk
182
+ win = tk.Toplevel(self.root)
183
+ win.title("About osmsg")
184
+ box = ttk.Frame(win, padding=16)
185
+ box.grid(sticky="nsew")
186
+ ttk.Label(box, text=f"osmsg {__version__}", font=("", 12, "bold")).grid(sticky="w")
187
+ ttk.Label(box, text="OpenStreetMap Stats Generator").grid(sticky="w")
188
+ ttk.Label(box, text="A project of OSGeo Nepal").grid(sticky="w", pady=(0, 10))
189
+ for text, url in ABOUT_LINKS:
190
+ link = ttk.Label(box, text=text, foreground="#1a73e8", cursor="hand2")
191
+ link.grid(sticky="w", pady=2)
192
+ link.bind("<Button-1>", lambda _event, target=url: webbrowser.open(target))
193
+ ttk.Button(box, text="Close", command=win.destroy).grid(sticky="e", pady=(12, 0))
194
+
169
195
  def _apply_preset(self, name: str) -> None:
170
196
  start, end = preset_range(name)
171
197
  self.vars["start"].set(_fmt(start))
@@ -14,6 +14,7 @@ from pathlib import Path
14
14
  from typing import Any
15
15
 
16
16
  import duckdb
17
+ import requests
17
18
  from platformdirs import user_cache_dir
18
19
  from shapely.ops import unary_union
19
20
 
@@ -539,6 +540,11 @@ def _processing_config(cfg: RunConfig, *, parquet_dir: Path, geom_wkt: str | Non
539
540
  }
540
541
 
541
542
 
543
+ # Replication servers throttle many concurrent connections, so downloads stay polite regardless of
544
+ # the worker count used for local parsing. Already-downloaded files are cached, so a rerun resumes.
545
+ _DOWNLOAD_WORKERS = 4
546
+
547
+
542
548
  def _download_all(
543
549
  urls: list[str],
544
550
  mode: str,
@@ -548,12 +554,19 @@ def _download_all(
548
554
  label: str,
549
555
  description: str = "downloading",
550
556
  ) -> None:
551
- with (
552
- progress_bar(len(urls), unit=label, description=description) as advance,
553
- concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as pool,
554
- ):
555
- for _ in pool.map(lambda u: download_osm_file(u, mode=mode, cookie=cookie, cache_dir=cache_dir), urls):
556
- advance()
557
+ workers = min(max_workers, _DOWNLOAD_WORKERS)
558
+ try:
559
+ with (
560
+ progress_bar(len(urls), unit=label, description=description) as advance,
561
+ concurrent.futures.ThreadPoolExecutor(max_workers=workers) as pool,
562
+ ):
563
+ for _ in pool.map(lambda u: download_osm_file(u, mode=mode, cookie=cookie, cache_dir=cache_dir), urls):
564
+ advance()
565
+ except requests.exceptions.RequestException as exc:
566
+ raise OsmsgError(
567
+ f"Network error downloading {label} after retries ({type(exc).__name__}). "
568
+ "Re-run to resume: finished downloads are cached, so it continues from where it stopped."
569
+ ) from exc
557
570
 
558
571
 
559
572
  def _process_all(
@@ -727,6 +740,13 @@ def run(cfg: RunConfig) -> dict[str, Any]:
727
740
  else f"first run with {cfg.changeset_pad_hours}h backward pad"
728
741
  )
729
742
  info(f"Changesets: {len(urls)} files (seq {cs_start}-{cs_end}), {pad_note}.")
743
+ if len(urls) > 5000:
744
+ warn(
745
+ f"Hashtag/changeset filtering downloads the per-minute changeset stream for the live "
746
+ f"tail ({len(urls):,} files here). This is slow over a busy network and resumes from "
747
+ f"cache if interrupted; a shorter range or waiting for the dataset to cover more months "
748
+ f"reduces it."
749
+ )
730
750
 
731
751
  cs_frontier_ts = cs_repl.sequence_to_timestamp(cs_end)
732
752
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "osmsg"
3
- version = "1.2.3"
3
+ version = "1.2.4"
4
4
  description = "OpenStreetMap Stats Generator: Commandline"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -1 +0,0 @@
1
- __version__ = "1.2.3"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes