mapillary-downloader 0.1.0__tar.gz → 0.1.1__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.
@@ -0,0 +1,97 @@
1
+ Metadata-Version: 2.4
2
+ Name: mapillary_downloader
3
+ Version: 0.1.1
4
+ Summary: Download your Mapillary data before it's gone
5
+ Author-email: Gareth Davidson <gaz@bitplane.net>
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ Classifier: License :: Public Domain
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ License-File: LICENSE.md
14
+ Requires-Dist: requests>=2.31.0
15
+ Requires-Dist: piexif>=1.1.3
16
+ Requires-Dist: pre-commit ; extra == "dev"
17
+ Requires-Dist: pytest ; extra == "dev"
18
+ Requires-Dist: coverage ; extra == "dev"
19
+ Requires-Dist: pytest-cov ; extra == "dev"
20
+ Requires-Dist: build ; extra == "dev"
21
+ Requires-Dist: twine ; extra == "dev"
22
+ Requires-Dist: ruff ; extra == "dev"
23
+ Requires-Dist: pydoc-markdown ; extra == "dev"
24
+ Requires-Dist: Pillow ; extra == "dev"
25
+ Project-URL: Documentation, https://bitplane.net/dev/python/mapillary_downloader/pydoc
26
+ Project-URL: Homepage, https://bitplane.net/dev/python/mapillary_downloader
27
+ Project-URL: Issues, https://github.com/bitplane/mapillary_downloader/issues
28
+ Project-URL: Repository, https://github.com/bitplane/mapillary_downloader
29
+ Provides-Extra: dev
30
+
31
+ # Mapillary Downloader
32
+
33
+ Download your Mapillary data before it's gone.
34
+
35
+ ## Installation
36
+
37
+ ```bash
38
+ pip install mapillary-downloader
39
+ ```
40
+
41
+ Or from source:
42
+
43
+ ```bash
44
+ make install
45
+ ```
46
+
47
+ ## Usage
48
+
49
+ First, get your Mapillary API access token from https://www.mapillary.com/dashboard/developers
50
+
51
+ ```bash
52
+ mapillary-download --token YOUR_TOKEN --username YOUR_USERNAME --output ./downloads
53
+ ```
54
+
55
+ Options:
56
+ - `--token`: Your Mapillary API access token (required)
57
+ - `--username`: Your Mapillary username (required)
58
+ - `--output`: Output directory (default: ./mapillary_data)
59
+ - `--quality`: Image quality - 256, 1024, 2048, or original (default: original)
60
+ - `--bbox`: Bounding box filter: west,south,east,north
61
+
62
+ The downloader will:
63
+ - Fetch all your uploaded images from Mapillary
64
+ - Download full-resolution images organized by sequence
65
+ - Inject EXIF metadata (GPS coordinates, camera info, timestamps, compass direction)
66
+ - Save progress so you can safely resume if interrupted
67
+
68
+ ## Features
69
+
70
+ - **Resume capability**: Interrupt and restart anytime - it tracks what's downloaded
71
+ - **EXIF restoration**: Restores GPS, camera, and timestamp metadata that Mapillary stripped
72
+ - **Atomic writes**: Progress tracking uses atomic file operations to prevent corruption
73
+ - **Organized output**: Images organized by sequence ID with metadata in JSONL format
74
+
75
+ ## Development
76
+
77
+ ```bash
78
+ make dev # Setup dev environment
79
+ make test # Run tests
80
+ make coverage # Run tests with coverage
81
+ ```
82
+
83
+ ## Links
84
+
85
+ * [🏠 home](https://bitplane.net/dev/python/mapillary_downloader)
86
+ * [📖 pydoc](https://bitplane.net/dev/python/mapillary_downloader/pydoc)
87
+ * [🐍 pypi](https://pypi.org/project/mapillary-downloader)
88
+ * [🐱 github](https://github.com/bitplane/mapillary_downloader)
89
+
90
+ ## License
91
+
92
+ WTFPL with one additional clause
93
+
94
+ 1. Don't blame me
95
+
96
+ Do wtf you want, but don't blame me when it breaks.
97
+
@@ -0,0 +1,66 @@
1
+ # Mapillary Downloader
2
+
3
+ Download your Mapillary data before it's gone.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install mapillary-downloader
9
+ ```
10
+
11
+ Or from source:
12
+
13
+ ```bash
14
+ make install
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ First, get your Mapillary API access token from https://www.mapillary.com/dashboard/developers
20
+
21
+ ```bash
22
+ mapillary-download --token YOUR_TOKEN --username YOUR_USERNAME --output ./downloads
23
+ ```
24
+
25
+ Options:
26
+ - `--token`: Your Mapillary API access token (required)
27
+ - `--username`: Your Mapillary username (required)
28
+ - `--output`: Output directory (default: ./mapillary_data)
29
+ - `--quality`: Image quality - 256, 1024, 2048, or original (default: original)
30
+ - `--bbox`: Bounding box filter: west,south,east,north
31
+
32
+ The downloader will:
33
+ - Fetch all your uploaded images from Mapillary
34
+ - Download full-resolution images organized by sequence
35
+ - Inject EXIF metadata (GPS coordinates, camera info, timestamps, compass direction)
36
+ - Save progress so you can safely resume if interrupted
37
+
38
+ ## Features
39
+
40
+ - **Resume capability**: Interrupt and restart anytime - it tracks what's downloaded
41
+ - **EXIF restoration**: Restores GPS, camera, and timestamp metadata that Mapillary stripped
42
+ - **Atomic writes**: Progress tracking uses atomic file operations to prevent corruption
43
+ - **Organized output**: Images organized by sequence ID with metadata in JSONL format
44
+
45
+ ## Development
46
+
47
+ ```bash
48
+ make dev # Setup dev environment
49
+ make test # Run tests
50
+ make coverage # Run tests with coverage
51
+ ```
52
+
53
+ ## Links
54
+
55
+ * [🏠 home](https://bitplane.net/dev/python/mapillary_downloader)
56
+ * [📖 pydoc](https://bitplane.net/dev/python/mapillary_downloader/pydoc)
57
+ * [🐍 pypi](https://pypi.org/project/mapillary-downloader)
58
+ * [🐱 github](https://github.com/bitplane/mapillary_downloader)
59
+
60
+ ## License
61
+
62
+ WTFPL with one additional clause
63
+
64
+ 1. Don't blame me
65
+
66
+ Do wtf you want, but don't blame me when it breaks.
@@ -1,18 +1,35 @@
1
1
  [project]
2
2
  name = "mapillary_downloader"
3
3
  description = "Download your Mapillary data before it's gone"
4
- version = "0.1.0"
4
+ version = "0.1.1"
5
5
  authors = [
6
6
  { name = "Gareth Davidson", email = "gaz@bitplane.net" }
7
7
  ]
8
8
  readme = "README.md"
9
9
  requires-python = ">=3.10"
10
+ license = { text = "Public Domain" }
11
+ classifiers = [
12
+ "License :: Public Domain",
13
+ "Programming Language :: Python :: 3",
14
+ "Programming Language :: Python :: 3.10",
15
+ "Programming Language :: Python :: 3.11",
16
+ "Programming Language :: Python :: 3.12",
17
+ ]
10
18
 
11
19
  dependencies = [
12
20
  "requests>=2.31.0",
13
21
  "piexif>=1.1.3",
14
22
  ]
15
23
 
24
+ [project.urls]
25
+ Homepage = "https://bitplane.net/dev/python/mapillary_downloader"
26
+ Documentation = "https://bitplane.net/dev/python/mapillary_downloader/pydoc"
27
+ Repository = "https://github.com/bitplane/mapillary_downloader"
28
+ Issues = "https://github.com/bitplane/mapillary_downloader/issues"
29
+
30
+ [project.scripts]
31
+ mapillary-download = "mapillary_downloader.__main__:main"
32
+
16
33
  [project.optional-dependencies]
17
34
  dev = [
18
35
  "pre-commit",
@@ -22,8 +39,6 @@ dev = [
22
39
  "build",
23
40
  "twine",
24
41
  "ruff",
25
- "mkdocs",
26
- "mkdocs-material",
27
42
  "pydoc-markdown",
28
43
  "Pillow",
29
44
  ]
@@ -2,6 +2,7 @@
2
2
 
3
3
  import time
4
4
  import requests
5
+ from requests.exceptions import RequestException
5
6
 
6
7
 
7
8
  class MapillaryClient:
@@ -66,8 +67,22 @@ class MapillaryClient:
66
67
  url = f"{self.base_url}/images"
67
68
 
68
69
  while url:
69
- response = self.session.get(url, params=params)
70
- response.raise_for_status()
70
+ max_retries = 10
71
+ base_delay = 1.0
72
+
73
+ for attempt in range(max_retries):
74
+ try:
75
+ response = self.session.get(url, params=params)
76
+ response.raise_for_status()
77
+ break
78
+ except RequestException as e:
79
+ if attempt == max_retries - 1:
80
+ raise
81
+
82
+ delay = base_delay * (2 ** attempt)
83
+ print(f"Request failed (attempt {attempt + 1}/{max_retries}): {e}")
84
+ print(f"Retrying in {delay:.1f} seconds...")
85
+ time.sleep(delay)
71
86
 
72
87
  data = response.json()
73
88
 
@@ -91,17 +106,27 @@ class MapillaryClient:
91
106
  Returns:
92
107
  Number of bytes downloaded if successful, 0 otherwise
93
108
  """
94
- try:
95
- response = self.session.get(image_url, stream=True)
96
- response.raise_for_status()
97
-
98
- total_bytes = 0
99
- with open(output_path, "wb") as f:
100
- for chunk in response.iter_content(chunk_size=8192):
101
- f.write(chunk)
102
- total_bytes += len(chunk)
103
-
104
- return total_bytes
105
- except Exception as e:
106
- print(f"Error downloading {image_url}: {e}")
107
- return 0
109
+ max_retries = 10
110
+ base_delay = 1.0
111
+
112
+ for attempt in range(max_retries):
113
+ try:
114
+ response = self.session.get(image_url, stream=True)
115
+ response.raise_for_status()
116
+
117
+ total_bytes = 0
118
+ with open(output_path, "wb") as f:
119
+ for chunk in response.iter_content(chunk_size=8192):
120
+ f.write(chunk)
121
+ total_bytes += len(chunk)
122
+
123
+ return total_bytes
124
+ except RequestException as e:
125
+ if attempt == max_retries - 1:
126
+ print(f"Error downloading {image_url} after {max_retries} attempts: {e}")
127
+ return 0
128
+
129
+ delay = base_delay * (2 ** attempt)
130
+ print(f"Download failed (attempt {attempt + 1}/{max_retries}): {e}")
131
+ print(f"Retrying in {delay:.1f} seconds...")
132
+ time.sleep(delay)
@@ -1,54 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: mapillary_downloader
3
- Version: 0.1.0
4
- Summary: Download your Mapillary data before it's gone
5
- Author-email: Gareth Davidson <gaz@bitplane.net>
6
- Requires-Python: >=3.10
7
- Description-Content-Type: text/markdown
8
- License-File: LICENSE.md
9
- Requires-Dist: requests>=2.31.0
10
- Requires-Dist: piexif>=1.1.3
11
- Requires-Dist: pre-commit ; extra == "dev"
12
- Requires-Dist: pytest ; extra == "dev"
13
- Requires-Dist: coverage ; extra == "dev"
14
- Requires-Dist: pytest-cov ; extra == "dev"
15
- Requires-Dist: build ; extra == "dev"
16
- Requires-Dist: twine ; extra == "dev"
17
- Requires-Dist: ruff ; extra == "dev"
18
- Requires-Dist: mkdocs ; extra == "dev"
19
- Requires-Dist: mkdocs-material ; extra == "dev"
20
- Requires-Dist: pydoc-markdown ; extra == "dev"
21
- Requires-Dist: Pillow ; extra == "dev"
22
- Provides-Extra: dev
23
-
24
- # Mapillary Downloader
25
-
26
- Download your Mapillary data before it's gone.
27
-
28
- ## Installation
29
-
30
- ```bash
31
- make install
32
- ```
33
-
34
- ## Usage
35
-
36
- First, get your Mapillary API access token from https://www.mapillary.com/dashboard/developers
37
-
38
- ```bash
39
- source .venv/bin/activate
40
- python -m mapillary_downloader --token YOUR_TOKEN --username YOUR_USERNAME --output ./downloads
41
- ```
42
-
43
- ## Development
44
-
45
- ```bash
46
- make dev # Setup dev environment
47
- make test # Run tests
48
- make coverage # Run tests with coverage
49
- ```
50
-
51
- ## License
52
-
53
- WTFPL + Warranty (Don't blame me)
54
-
@@ -1,30 +0,0 @@
1
- # Mapillary Downloader
2
-
3
- Download your Mapillary data before it's gone.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- make install
9
- ```
10
-
11
- ## Usage
12
-
13
- First, get your Mapillary API access token from https://www.mapillary.com/dashboard/developers
14
-
15
- ```bash
16
- source .venv/bin/activate
17
- python -m mapillary_downloader --token YOUR_TOKEN --username YOUR_USERNAME --output ./downloads
18
- ```
19
-
20
- ## Development
21
-
22
- ```bash
23
- make dev # Setup dev environment
24
- make test # Run tests
25
- make coverage # Run tests with coverage
26
- ```
27
-
28
- ## License
29
-
30
- WTFPL + Warranty (Don't blame me)