kleinkram 0.13.1__py3-none-any.whl → 0.13.2.dev20240830095132__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.

Potentially problematic release.


This version of kleinkram might be problematic. Click here for more details.

kleinkram/helper.py CHANGED
@@ -2,14 +2,82 @@ import glob
2
2
  import os
3
3
  import queue
4
4
  import threading
5
+ from functools import partial
5
6
  from typing import Dict
7
+ import boto3
6
8
 
7
9
  import httpx
8
10
  import tqdm
11
+ from boto3.s3.transfer import TransferConfig
12
+ from botocore.client import BaseClient
9
13
  from rich import print
10
14
 
11
15
  from kleinkram.api_client import AuthenticatedClient
12
16
 
17
+ class TransferCallback:
18
+ """
19
+ Handle callbacks from the transfer manager.
20
+
21
+ The transfer manager periodically calls the __call__ method throughout
22
+ the upload process so that it can take action, such as displaying progress
23
+ to the user and collecting data about the transfer.
24
+ """
25
+
26
+ def __init__(self):
27
+ """
28
+ Initialize the TransferCallback.
29
+
30
+ This initializes an empty dictionary to hold progress bars for each file.
31
+ """
32
+ self._lock = threading.Lock()
33
+ self.file_progress = {}
34
+
35
+ def add_file(self, file_id, target_size):
36
+ """
37
+ Add a new file to track.
38
+
39
+ :param file_id: A unique identifier for the file (e.g., file name or ID).
40
+ :param target_size: The total size of the file being transferred.
41
+ """
42
+ with self._lock:
43
+ tqdm_instance = tqdm.tqdm(total=target_size, unit='B', unit_scale=True, desc=f'Uploading {file_id}')
44
+ self.file_progress[file_id] = {
45
+ 'tqdm': tqdm_instance,
46
+ 'total_transferred': 0
47
+ }
48
+
49
+ def __call__(self, file_id, bytes_transferred):
50
+ """
51
+ The callback method that is called by the transfer manager.
52
+
53
+ Display progress during file transfer and collect per-thread transfer
54
+ data. This method can be called by multiple threads, so shared instance
55
+ data is protected by a thread lock.
56
+
57
+ :param file_id: The identifier of the file being transferred.
58
+ :param bytes_transferred: The number of bytes transferred in this call.
59
+ """
60
+ with self._lock:
61
+ if file_id in self.file_progress:
62
+ progress = self.file_progress[file_id]
63
+ progress['total_transferred'] += bytes_transferred
64
+
65
+ # Update tqdm progress bar
66
+ progress['tqdm'].update(bytes_transferred)
67
+
68
+ def close(self):
69
+ """Close all tqdm progress bars."""
70
+ with self._lock:
71
+ for progress in self.file_progress.values():
72
+ progress['tqdm'].close()
73
+ def create_transfer_callback(callback_instance, file_id):
74
+ """
75
+ Factory function to create a partial function for TransferCallback.
76
+ :param callback_instance: Instance of TransferCallback.
77
+ :param file_id: The unique identifier for the file.
78
+ :return: A callable that can be passed as a callback to boto3's upload_file method.
79
+ """
80
+ return partial(callback_instance.__call__, file_id)
13
81
 
14
82
  def expand_and_match(path_pattern):
15
83
  expanded_path = os.path.expanduser(path_pattern)
@@ -25,40 +93,52 @@ def expand_and_match(path_pattern):
25
93
  return file_list
26
94
 
27
95
 
28
- def uploadFiles(files: Dict[str, str], paths: Dict[str, str], nrThreads: int):
96
+ def uploadFiles(files: Dict[str, str], credentials: Dict[str, str], nrThreads: int):
97
+ client = AuthenticatedClient()
98
+
99
+ session = boto3.Session(
100
+ aws_access_key_id=credentials["accessKey"],
101
+ aws_secret_access_key=credentials["secretKey"],
102
+ aws_session_token=credentials["sessionToken"])
103
+ api_endpoint = client.tokenfile.endpoint
104
+ if api_endpoint == 'http://localhost:3000':
105
+ minio_endpoint = 'http://localhost:9000'
106
+ else:
107
+ minio_endpoint = api_endpoint.replace("api", "minio")
108
+ s3 = session.resource("s3", endpoint_url=minio_endpoint)
109
+
29
110
  _queue = queue.Queue()
30
111
  for file in files.items():
31
112
  _queue.put(file)
32
113
  threads = []
33
- pbar = tqdm.tqdm(total=len(files.items()) * 100)
114
+ transferCallback = TransferCallback()
115
+
34
116
  for i in range(nrThreads):
35
- thread = threading.Thread(target=uploadFile, args=(_queue, paths, pbar))
117
+ thread = threading.Thread(target=uploadFile, args=(_queue, s3, transferCallback))
36
118
  thread.start()
37
119
  threads.append(thread)
38
120
  for thread in threads:
39
121
  thread.join()
40
122
 
41
123
 
42
- def uploadFile(_queue: queue.Queue, paths: Dict[str, str], pbar: tqdm):
124
+ def uploadFile(_queue: queue.Queue, s3: BaseClient, transferCallback: TransferCallback):
43
125
  while True:
44
126
  try:
45
- filename, info = _queue.get(timeout=3)
46
- url = info["url"]
47
- uuid = info["uuid"]
48
- filepath = paths[filename]
49
- headers = {"Content-Type": "application/octet-stream"}
127
+ filename, _file = _queue.get(timeout=3)
128
+ queueUUID = _file['queueUUID']
129
+ filepath = _file['filepath']
130
+ bucket = _file['bucket']
131
+ target_location = _file['location']
132
+ config = TransferConfig(multipart_chunksize=10*1024*1024, max_concurrency=5)
50
133
  with open(filepath, "rb") as f:
51
- with httpx.Client() as cli:
52
- # Using PUT method directly for the upload
53
- response = cli.put(url, content=f, headers=headers)
54
- if response.status_code == 200:
55
- pbar.update(100) # Update progress for each file
56
- client = AuthenticatedClient()
57
- client.post("/queue/confirmUpload", json={"uuid": uuid})
58
- else:
59
- print(
60
- f"Failed to upload {filename}. HTTP status: {response.status_code}"
61
- )
134
+ size = os.path.getsize(filepath)
135
+ transferCallback.add_file(filename, size)
136
+ callback_function = create_transfer_callback(transferCallback, filename)
137
+ s3.Bucket(bucket).upload_file(filepath, target_location, Config=config, Callback=callback_function)
138
+
139
+ client = AuthenticatedClient()
140
+ res = client.post("/queue/confirmUpload", json={"uuid": queueUUID})
141
+ res.raise_for_status()
62
142
  _queue.task_done()
63
143
  except queue.Empty:
64
144
  break
@@ -67,6 +147,8 @@ def uploadFile(_queue: queue.Queue, paths: Dict[str, str], pbar: tqdm):
67
147
  _queue.task_done()
68
148
 
69
149
 
150
+
151
+
70
152
  if __name__ == "__main__":
71
153
  res = expand_and_match(
72
154
  "~/Downloads/dodo_mission_2024_02_08-20240408T074313Z-003/**.bag"
kleinkram/main.py CHANGED
@@ -179,23 +179,25 @@ def upload(
179
179
  )
180
180
  new_mission.raise_for_status()
181
181
  new_mission_data = new_mission.json()
182
- print(f"Created mission: {new_mission_data['name']}")
183
182
 
184
- get_presigned_url = "/queue/createPreSignedURLS"
183
+ get_temporary_credentials = "/file/temporaryAccess"
185
184
 
186
185
  response_2 = client.post(
187
- get_presigned_url,
186
+ get_temporary_credentials,
188
187
  json={"filenames": filenames, "missionUUID": new_mission_data["uuid"]},
189
188
  )
190
189
  response_2.raise_for_status()
191
- presigned_urls = response_2.json()
192
- for file in filenames:
193
- if not file in presigned_urls.keys():
190
+ temp_credentials = response_2.json()
191
+ credential = temp_credentials["credentials"]
192
+ confirmed_files = temp_credentials["files"]
193
+ for _file in filenames:
194
+ if not _file in confirmed_files.keys():
194
195
  raise Exception(
195
196
  "Could not upload File '" + file + "'. Is the filename unique? "
196
197
  )
197
- if len(presigned_urls) > 0:
198
- uploadFiles(presigned_urls, filepaths, 4)
198
+ confirmed_files[_file]['filepath'] = filepaths[_file]
199
+ if len(confirmed_files.keys()) > 0:
200
+ uploadFiles(confirmed_files, credential, 4)
199
201
 
200
202
  except httpx.HTTPError as e:
201
203
  print(e)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: kleinkram
3
- Version: 0.13.1
3
+ Version: 0.13.2.dev20240830095132
4
4
  Summary: A CLI for the ETH project kleinkram
5
5
  Project-URL: Homepage, https://github.com/leggedrobotics/kleinkram
6
6
  Project-URL: Issues, https://github.com/leggedrobotics/kleinkram/issues
@@ -2,8 +2,8 @@ kleinkram/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  kleinkram/api_client.py,sha256=1GPsM-XFbPYEKP7RfWmzMTwxRqnVh4wtHVuW25KT8kA,2264
3
3
  kleinkram/consts.py,sha256=pm_6OuQcO-tYcRhwauTtyRRsuYY0y0yb6EGuIl49LnI,50
4
4
  kleinkram/error_handling.py,sha256=Nm3tUtc4blQylJLNChSLgkDLFDHg3Xza0CghRrd_SYE,4015
5
- kleinkram/helper.py,sha256=9YUuCH0pfj7gK88XRtR0SD-cfdcbR-4g0DdAcUfwdm4,2334
6
- kleinkram/main.py,sha256=LIhlsepSWm_cl_VN0TuvPYtdKX_2Mz7d3Q-piebj3O8,7983
5
+ kleinkram/helper.py,sha256=oG_6izoMdWWxw4SFgDsnhsXDwPFLOmXW_18-wRbgUjk,5410
6
+ kleinkram/main.py,sha256=QwC8Mhpr6uk1x5W43UU9a-2nwnfy8lmsi52hOFzpOVA,8118
7
7
  kleinkram/auth/auth.py,sha256=bROptCsE0r5D416_7l1lfw52IX_mSVEnjaKiU2_b1Ms,4980
8
8
  kleinkram/endpoint/endpoint.py,sha256=KAYQgK8J6Et8V_ho2wBUIAdg25Mps6l_glCfC1vvC2g,1372
9
9
  kleinkram/file/file.py,sha256=HsKzg8xn-AHJJIF11H6c0Gy61cRX3MyTMYdcyypUxWo,3195
@@ -13,8 +13,8 @@ kleinkram/queue/queue.py,sha256=MaLBjAu8asi9BkPvbbT-5AobCcpy3ex5rxM1kHpRINA,181
13
13
  kleinkram/tag/tag.py,sha256=TZHh1GIV4LhwhqEGKdTJkM5mCIoLXAopBgWdLX1AEz8,1819
14
14
  kleinkram/topic/topic.py,sha256=qit-DECI19QocXEkkkBC0FAlzpZnotAtX8mylA9zqAA,1630
15
15
  kleinkram/user/user.py,sha256=i_QfsctjhImvKKjuDPfOIyDr322SXgV-KxJo-a7qNZw,1368
16
- kleinkram-0.13.1.dist-info/METADATA,sha256=hSkr3cBsUq6jdaTYGbvDZDOcbc1eqGMMkRcL0P5irNQ,756
17
- kleinkram-0.13.1.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
18
- kleinkram-0.13.1.dist-info/entry_points.txt,sha256=RHXtRzcreVHImatgjhQwZQ6GdJThElYjHEWcR1BPXUI,45
19
- kleinkram-0.13.1.dist-info/licenses/LICENSE,sha256=ixuiBLtpoK3iv89l7ylKkg9rs2GzF9ukPH7ynZYzK5s,35148
20
- kleinkram-0.13.1.dist-info/RECORD,,
16
+ kleinkram-0.13.2.dev20240830095132.dist-info/METADATA,sha256=QBM1O7N_9iYGDyfzwZfGe4RxQusF25dPMVF6yNsBfZ8,774
17
+ kleinkram-0.13.2.dev20240830095132.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
18
+ kleinkram-0.13.2.dev20240830095132.dist-info/entry_points.txt,sha256=RHXtRzcreVHImatgjhQwZQ6GdJThElYjHEWcR1BPXUI,45
19
+ kleinkram-0.13.2.dev20240830095132.dist-info/licenses/LICENSE,sha256=ixuiBLtpoK3iv89l7ylKkg9rs2GzF9ukPH7ynZYzK5s,35148
20
+ kleinkram-0.13.2.dev20240830095132.dist-info/RECORD,,