camera-client 0.2.5__tar.gz → 0.2.7__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.
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: camera-client
3
- Version: 0.2.5
3
+ Version: 0.2.7
4
4
  Summary: Python SDK for camera calibration and projection transformations - handle lens distortion, coordinate transformations, and 3D ray casting with symbolic expressions.
5
5
  Author-email: Alexander Abramov <extremal.ru@gmail.com>
6
6
  License: MIT
@@ -26,6 +26,7 @@ Description-Content-Type: text/markdown
26
26
  License-File: LICENSE
27
27
  Requires-Dist: numpy>=1.20.0
28
28
  Requires-Dist: sympy>=1.10.0
29
+ Dynamic: license-file
29
30
 
30
31
  # camera-client
31
32
 
@@ -49,6 +50,18 @@ Install from PyPI:
49
50
  pip install camera-client
50
51
  ```
51
52
 
53
+ ## CLI Usage
54
+
55
+ Download camera calibration archives from URL:
56
+
57
+ ```bash
58
+ # Download single archive
59
+ python -m camera_client get_camera_archive https://example.com/camera.npz
60
+
61
+ # Download from file with URLs (one per line, non-URL lines ignored)
62
+ python -m camera_client get_camera_archive -f urls.txt -o ./archives
63
+ ```
64
+
52
65
  ## Quick Start
53
66
 
54
67
  ```python
@@ -20,6 +20,18 @@ Install from PyPI:
20
20
  pip install camera-client
21
21
  ```
22
22
 
23
+ ## CLI Usage
24
+
25
+ Download camera calibration archives from URL:
26
+
27
+ ```bash
28
+ # Download single archive
29
+ python -m camera_client get_camera_archive https://example.com/camera.npz
30
+
31
+ # Download from file with URLs (one per line, non-URL lines ignored)
32
+ python -m camera_client get_camera_archive -f urls.txt -o ./archives
33
+ ```
34
+
23
35
  ## Quick Start
24
36
 
25
37
  ```python
@@ -0,0 +1,219 @@
1
+ """Command-line interface for camera-client package."""
2
+
3
+ import argparse
4
+ import json
5
+ import os
6
+ import sys
7
+ from pathlib import Path
8
+ from urllib.request import urlopen, Request
9
+ from urllib.parse import urlparse
10
+
11
+
12
+ def is_url(text: str) -> bool:
13
+ """
14
+ Check if a string is a valid URL.
15
+
16
+ Args:
17
+ text: String to check
18
+
19
+ Returns:
20
+ True if the string looks like a URL, False otherwise
21
+ """
22
+ text = text.strip()
23
+ return text.startswith('http://') or text.startswith('https://')
24
+
25
+
26
+ def download_archive(url: str, output_dir: str = ".", silent: bool = False) -> bool:
27
+ """
28
+ Download camera calibration archive from URL to the specified directory.
29
+
30
+ Args:
31
+ url: URL to download the archive from
32
+ output_dir: Directory to save the downloaded file (default: current directory)
33
+ silent: If True, suppress success messages (errors still printed)
34
+
35
+ Returns:
36
+ True if download succeeded, False otherwise
37
+ """
38
+ try:
39
+ # Parse the URL to extract filename from path or Content-Disposition header
40
+ parsed_url = urlparse(url)
41
+
42
+ # Create request with headers
43
+ request = Request(url, headers={'User-Agent': 'camera-client'})
44
+
45
+ # Open URL and get response
46
+ if not silent:
47
+ print(f"Downloading from: {url}")
48
+ with urlopen(request) as response:
49
+ # Try to get filename from Content-Disposition header
50
+ content_disposition = response.headers.get('Content-Disposition', '')
51
+ filename = None
52
+
53
+ if 'filename=' in content_disposition:
54
+ # Extract filename from Content-Disposition header
55
+ parts = content_disposition.split('filename=')
56
+ if len(parts) > 1:
57
+ filename = parts[1].strip('"')
58
+
59
+ # Fallback to URL path if no Content-Disposition
60
+ if not filename:
61
+ path_parts = parsed_url.path.split('/')
62
+ filename = path_parts[-1] if path_parts[-1] else 'camera_archive.npz'
63
+
64
+ # Ensure .npz extension
65
+ if not filename.endswith('.npz'):
66
+ filename += '.npz'
67
+
68
+ # Create output path
69
+ output_path = Path(output_dir) / filename
70
+
71
+ # Download file
72
+ if not silent:
73
+ print(f"Saving to: {output_path}")
74
+ with open(output_path, 'wb') as f:
75
+ f.write(response.read())
76
+
77
+ if not silent:
78
+ print(f"Successfully downloaded: {filename}")
79
+ print(f"File size: {output_path.stat().st_size} bytes")
80
+
81
+ return True
82
+
83
+ except Exception as e:
84
+ print(f"Error downloading archive from {url}: {e}", file=sys.stderr)
85
+ return False
86
+
87
+
88
+ def download_from_file(file_path: str, output_dir: str = ".", camera_id: int = None) -> None:
89
+ """
90
+ Download camera calibration archives from a .txt file with URLs or a .json config.
91
+
92
+ For .txt files: one URL per line, non-URL lines are ignored.
93
+ For .json files: expects a list of objects with "archive_url" key.
94
+ Optionally filter by camera_id.
95
+
96
+ Args:
97
+ file_path: Path to .txt or .json file
98
+ output_dir: Directory to save the downloaded files (default: current directory)
99
+ camera_id: If provided, only download archives for this camera_id (JSON only)
100
+ """
101
+ try:
102
+ if file_path.endswith('.json'):
103
+ with open(file_path, 'r') as f:
104
+ configs = json.load(f)
105
+
106
+ if not isinstance(configs, list):
107
+ configs = [configs]
108
+
109
+ if camera_id is not None:
110
+ configs = [c for c in configs if c.get('camera_id') == camera_id]
111
+
112
+ urls = [c['archive_url'] for c in configs if 'archive_url' in c]
113
+
114
+ if not urls:
115
+ msg = f"No matching entries found in {file_path}"
116
+ if camera_id is not None:
117
+ msg += f" for camera_id={camera_id}"
118
+ print(msg, file=sys.stderr)
119
+ sys.exit(1)
120
+ else:
121
+ with open(file_path, 'r') as f:
122
+ urls = [line.strip() for line in f if is_url(line)]
123
+
124
+ if not urls:
125
+ print(f"No URLs found in {file_path}", file=sys.stderr)
126
+ sys.exit(1)
127
+
128
+ print(f"Found {len(urls)} URL(s) in {file_path}")
129
+ print(f"Downloading to: {output_dir}\n")
130
+
131
+ success_count = 0
132
+ failed_count = 0
133
+
134
+ for i, url in enumerate(urls, 1):
135
+ print(f"[{i}/{len(urls)}] Processing: {url}")
136
+ if download_archive(url, output_dir, silent=False):
137
+ success_count += 1
138
+ else:
139
+ failed_count += 1
140
+ print() # Empty line between downloads
141
+
142
+ # Summary
143
+ print("=" * 50)
144
+ print(f"Download complete: {success_count} succeeded, {failed_count} failed")
145
+
146
+ if failed_count > 0:
147
+ sys.exit(1)
148
+
149
+ except FileNotFoundError:
150
+ print(f"Error: File not found: {file_path}", file=sys.stderr)
151
+ sys.exit(1)
152
+ except (json.JSONDecodeError, KeyError) as e:
153
+ print(f"Error parsing JSON file {file_path}: {e}", file=sys.stderr)
154
+ sys.exit(1)
155
+ except Exception as e:
156
+ print(f"Error reading file {file_path}: {e}", file=sys.stderr)
157
+ sys.exit(1)
158
+
159
+
160
+ def main():
161
+ """Main entry point for camera-client CLI."""
162
+ parser = argparse.ArgumentParser(
163
+ prog='camera-client',
164
+ description='Camera calibration client utilities'
165
+ )
166
+
167
+ subparsers = parser.add_subparsers(dest='command', help='Available commands')
168
+
169
+ # get_camera_archive command
170
+ download_parser = subparsers.add_parser(
171
+ 'get_camera_archive',
172
+ help='Get camera calibration archive(s) from URL or file'
173
+ )
174
+ download_parser.add_argument(
175
+ 'url',
176
+ nargs='?',
177
+ help='URL to download the archive from'
178
+ )
179
+ download_parser.add_argument(
180
+ '-f', '--file',
181
+ help='File containing URLs (one per line)'
182
+ )
183
+ download_parser.add_argument(
184
+ '-o', '--output-dir',
185
+ default='.',
186
+ help='Output directory (default: current directory)'
187
+ )
188
+ download_parser.add_argument(
189
+ '--camera_id',
190
+ type=int,
191
+ default=None,
192
+ help='Filter by camera_id (only used with JSON config files)'
193
+ )
194
+
195
+ args = parser.parse_args()
196
+
197
+ if args.command == 'get_camera_archive':
198
+ # Check that either url or file is provided (but not both)
199
+ if args.url and args.file:
200
+ print("Error: Cannot specify both URL and file. Use either positional URL or -f/--file option.", file=sys.stderr)
201
+ sys.exit(1)
202
+ elif not args.url and not args.file:
203
+ print("Error: Must specify either URL or file with -f/--file option.", file=sys.stderr)
204
+ download_parser.print_help()
205
+ sys.exit(1)
206
+
207
+ # Process based on input type
208
+ if args.file:
209
+ download_from_file(args.file, args.output_dir, camera_id=args.camera_id)
210
+ else:
211
+ success = download_archive(args.url, args.output_dir)
212
+ sys.exit(0 if success else 1)
213
+ else:
214
+ parser.print_help()
215
+ sys.exit(1)
216
+
217
+
218
+ if __name__ == '__main__':
219
+ main()
@@ -0,0 +1,7 @@
1
+ """Entry point script for camera-client console command."""
2
+
3
+ from camera_client.__main__ import main
4
+
5
+
6
+ if __name__ == '__main__':
7
+ main()
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: camera-client
3
- Version: 0.2.5
3
+ Version: 0.2.7
4
4
  Summary: Python SDK for camera calibration and projection transformations - handle lens distortion, coordinate transformations, and 3D ray casting with symbolic expressions.
5
5
  Author-email: Alexander Abramov <extremal.ru@gmail.com>
6
6
  License: MIT
@@ -26,6 +26,7 @@ Description-Content-Type: text/markdown
26
26
  License-File: LICENSE
27
27
  Requires-Dist: numpy>=1.20.0
28
28
  Requires-Dist: sympy>=1.10.0
29
+ Dynamic: license-file
29
30
 
30
31
  # camera-client
31
32
 
@@ -49,6 +50,18 @@ Install from PyPI:
49
50
  pip install camera-client
50
51
  ```
51
52
 
53
+ ## CLI Usage
54
+
55
+ Download camera calibration archives from URL:
56
+
57
+ ```bash
58
+ # Download single archive
59
+ python -m camera_client get_camera_archive https://example.com/camera.npz
60
+
61
+ # Download from file with URLs (one per line, non-URL lines ignored)
62
+ python -m camera_client get_camera_archive -f urls.txt -o ./archives
63
+ ```
64
+
52
65
  ## Quick Start
53
66
 
54
67
  ```python
@@ -5,8 +5,10 @@ pyproject.toml
5
5
  requirements.txt
6
6
  setup.py
7
7
  camera_client/__init__.py
8
+ camera_client/__main__.py
8
9
  camera_client/client.py
9
10
  camera_client/loading.py
11
+ camera_client/script.py
10
12
  camera_client.egg-info/PKG-INFO
11
13
  camera_client.egg-info/SOURCES.txt
12
14
  camera_client.egg-info/dependency_links.txt
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "camera-client"
7
- version = "0.2.5"
7
+ version = "0.2.7"
8
8
  description = "Python SDK for camera calibration and projection transformations - handle lens distortion, coordinate transformations, and 3D ray casting with symbolic expressions."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.7"
File without changes
File without changes
File without changes
File without changes