camera-client 0.2.5__tar.gz → 0.2.6__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.6
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,188 @@
1
+ """Command-line interface for camera-client package."""
2
+
3
+ import argparse
4
+ import os
5
+ import sys
6
+ from pathlib import Path
7
+ from urllib.request import urlopen, Request
8
+ from urllib.parse import urlparse
9
+
10
+
11
+ def is_url(text: str) -> bool:
12
+ """
13
+ Check if a string is a valid URL.
14
+
15
+ Args:
16
+ text: String to check
17
+
18
+ Returns:
19
+ True if the string looks like a URL, False otherwise
20
+ """
21
+ text = text.strip()
22
+ return text.startswith('http://') or text.startswith('https://')
23
+
24
+
25
+ def download_archive(url: str, output_dir: str = ".", silent: bool = False) -> bool:
26
+ """
27
+ Download camera calibration archive from URL to the specified directory.
28
+
29
+ Args:
30
+ url: URL to download the archive from
31
+ output_dir: Directory to save the downloaded file (default: current directory)
32
+ silent: If True, suppress success messages (errors still printed)
33
+
34
+ Returns:
35
+ True if download succeeded, False otherwise
36
+ """
37
+ try:
38
+ # Parse the URL to extract filename from path or Content-Disposition header
39
+ parsed_url = urlparse(url)
40
+
41
+ # Create request with headers
42
+ request = Request(url, headers={'User-Agent': 'camera-client'})
43
+
44
+ # Open URL and get response
45
+ if not silent:
46
+ print(f"Downloading from: {url}")
47
+ with urlopen(request) as response:
48
+ # Try to get filename from Content-Disposition header
49
+ content_disposition = response.headers.get('Content-Disposition', '')
50
+ filename = None
51
+
52
+ if 'filename=' in content_disposition:
53
+ # Extract filename from Content-Disposition header
54
+ parts = content_disposition.split('filename=')
55
+ if len(parts) > 1:
56
+ filename = parts[1].strip('"')
57
+
58
+ # Fallback to URL path if no Content-Disposition
59
+ if not filename:
60
+ path_parts = parsed_url.path.split('/')
61
+ filename = path_parts[-1] if path_parts[-1] else 'camera_archive.npz'
62
+
63
+ # Ensure .npz extension
64
+ if not filename.endswith('.npz'):
65
+ filename += '.npz'
66
+
67
+ # Create output path
68
+ output_path = Path(output_dir) / filename
69
+
70
+ # Download file
71
+ if not silent:
72
+ print(f"Saving to: {output_path}")
73
+ with open(output_path, 'wb') as f:
74
+ f.write(response.read())
75
+
76
+ if not silent:
77
+ print(f"Successfully downloaded: {filename}")
78
+ print(f"File size: {output_path.stat().st_size} bytes")
79
+
80
+ return True
81
+
82
+ except Exception as e:
83
+ print(f"Error downloading archive from {url}: {e}", file=sys.stderr)
84
+ return False
85
+
86
+
87
+ def download_from_file(file_path: str, output_dir: str = ".") -> None:
88
+ """
89
+ Download multiple camera calibration archives from URLs listed in a file.
90
+
91
+ Non-URL lines (comments, notes, etc.) are automatically skipped.
92
+
93
+ Args:
94
+ file_path: Path to file containing URLs (one per line, non-URL lines are ignored)
95
+ output_dir: Directory to save the downloaded files (default: current directory)
96
+ """
97
+ try:
98
+ with open(file_path, 'r') as f:
99
+ # Filter only lines that are valid URLs
100
+ urls = [line.strip() for line in f if is_url(line)]
101
+
102
+ if not urls:
103
+ print(f"No URLs found in {file_path}", file=sys.stderr)
104
+ sys.exit(1)
105
+
106
+ print(f"Found {len(urls)} URL(s) in {file_path}")
107
+ print(f"Downloading to: {output_dir}\n")
108
+
109
+ success_count = 0
110
+ failed_count = 0
111
+
112
+ for i, url in enumerate(urls, 1):
113
+ print(f"[{i}/{len(urls)}] Processing: {url}")
114
+ if download_archive(url, output_dir, silent=False):
115
+ success_count += 1
116
+ else:
117
+ failed_count += 1
118
+ print() # Empty line between downloads
119
+
120
+ # Summary
121
+ print("=" * 50)
122
+ print(f"Download complete: {success_count} succeeded, {failed_count} failed")
123
+
124
+ if failed_count > 0:
125
+ sys.exit(1)
126
+
127
+ except FileNotFoundError:
128
+ print(f"Error: File not found: {file_path}", file=sys.stderr)
129
+ sys.exit(1)
130
+ except Exception as e:
131
+ print(f"Error reading file {file_path}: {e}", file=sys.stderr)
132
+ sys.exit(1)
133
+
134
+
135
+ def main():
136
+ """Main entry point for camera-client CLI."""
137
+ parser = argparse.ArgumentParser(
138
+ prog='camera-client',
139
+ description='Camera calibration client utilities'
140
+ )
141
+
142
+ subparsers = parser.add_subparsers(dest='command', help='Available commands')
143
+
144
+ # get_camera_archive command
145
+ download_parser = subparsers.add_parser(
146
+ 'get_camera_archive',
147
+ help='Get camera calibration archive(s) from URL or file'
148
+ )
149
+ download_parser.add_argument(
150
+ 'url',
151
+ nargs='?',
152
+ help='URL to download the archive from'
153
+ )
154
+ download_parser.add_argument(
155
+ '-f', '--file',
156
+ help='File containing URLs (one per line)'
157
+ )
158
+ download_parser.add_argument(
159
+ '-o', '--output-dir',
160
+ default='.',
161
+ help='Output directory (default: current directory)'
162
+ )
163
+
164
+ args = parser.parse_args()
165
+
166
+ if args.command == 'get_camera_archive':
167
+ # Check that either url or file is provided (but not both)
168
+ if args.url and args.file:
169
+ print("Error: Cannot specify both URL and file. Use either positional URL or -f/--file option.", file=sys.stderr)
170
+ sys.exit(1)
171
+ elif not args.url and not args.file:
172
+ print("Error: Must specify either URL or file with -f/--file option.", file=sys.stderr)
173
+ download_parser.print_help()
174
+ sys.exit(1)
175
+
176
+ # Process based on input type
177
+ if args.file:
178
+ download_from_file(args.file, args.output_dir)
179
+ else:
180
+ success = download_archive(args.url, args.output_dir)
181
+ sys.exit(0 if success else 1)
182
+ else:
183
+ parser.print_help()
184
+ sys.exit(1)
185
+
186
+
187
+ if __name__ == '__main__':
188
+ 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.6
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.6"
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