synapse-sdk 1.0.0a95__py3-none-any.whl → 1.0.0a98__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 synapse-sdk might be problematic. Click here for more details.

@@ -24,6 +24,20 @@ from synapse_sdk.utils.pydantic.validators import non_blank
24
24
  from synapse_sdk.utils.storage import get_pathlib
25
25
 
26
26
 
27
+ class PathAwareJSONEncoder(json.JSONEncoder):
28
+ """Custom JSON encoder that handles Path-like objects."""
29
+
30
+ def default(self, obj):
31
+ if hasattr(obj, '__fspath__') or hasattr(obj, 'as_posix'):
32
+ # Handle Path-like objects (including UPath, SFTPPath, pathlib.Path, etc.)
33
+ return str(obj)
34
+ elif hasattr(obj, 'isoformat'):
35
+ # Handle datetime objects
36
+ return obj.isoformat()
37
+ # Let the base class handle other types
38
+ return super().default(obj)
39
+
40
+
27
41
  class UploadStatus(str, Enum):
28
42
  SUCCESS = 'success'
29
43
  FAILED = 'failed'
@@ -67,7 +81,8 @@ class UploadRun(Run):
67
81
  status (UploadStatus): The status of the data file.
68
82
  """
69
83
  now = datetime.now().isoformat()
70
- data_file_info_str = json.dumps(data_file_info, ensure_ascii=False)
84
+ # Use custom JSON encoder to handle Path-like objects
85
+ data_file_info_str = json.dumps(data_file_info, ensure_ascii=False, cls=PathAwareJSONEncoder)
71
86
  self.log(
72
87
  'upload_data_file',
73
88
  self.DataFileLog(data_file_info=data_file_info_str, status=status.value, created=now).model_dump(),
@@ -27,7 +27,9 @@ class FromDMToPascalConverter(FromDMConverter):
27
27
  return img_path
28
28
  return None
29
29
 
30
- def build_pascal_xml(self, img_filename: str, img_size: tuple, objects: List[dict]) -> ET.ElementTree:
30
+ def build_pascal_xml(
31
+ self, img_filename: str, img_size: tuple, objects: List[dict], has_segmentation: bool = None
32
+ ) -> ET.ElementTree:
31
33
  """Build a Pascal VOC XML tree from image filename, size, and objects."""
32
34
  folder = 'Images'
33
35
  width, height, depth = img_size
@@ -41,7 +43,12 @@ class FromDMToPascalConverter(FromDMConverter):
41
43
  ET.SubElement(size, 'width').text = str(width)
42
44
  ET.SubElement(size, 'height').text = str(height)
43
45
  ET.SubElement(size, 'depth').text = str(depth)
44
- ET.SubElement(annotation, 'segmented').text = '0'
46
+
47
+ # Set segmented to 1 if there are any segmentation objects, 0 otherwise
48
+ if has_segmentation is None:
49
+ has_segmentation = any(obj.get('has_segmentation', False) for obj in objects)
50
+ ET.SubElement(annotation, 'segmented').text = '1' if has_segmentation else '0'
51
+
45
52
  for obj in objects:
46
53
  obj_elem = ET.SubElement(annotation, 'object')
47
54
  ET.SubElement(obj_elem, 'name').text = obj['name']
@@ -58,6 +65,8 @@ class FromDMToPascalConverter(FromDMConverter):
58
65
  def parse_dm_annotations(self, annotation: dict):
59
66
  """Parse DM annotations and convert to Pascal VOC format."""
60
67
  objects = []
68
+ has_segmentation = 'segmentation' in annotation
69
+
61
70
  # Only include bounding_box (Pascal VOC does not support polyline/keypoint by default)
62
71
  if 'bounding_box' in annotation:
63
72
  for box in annotation['bounding_box']:
@@ -67,10 +76,18 @@ class FromDMToPascalConverter(FromDMConverter):
67
76
  ymin = int(round(y))
68
77
  xmax = int(round(x + w))
69
78
  ymax = int(round(y + h))
70
- objects.append({'name': class_name, 'xmin': xmin, 'ymin': ymin, 'xmax': xmax, 'ymax': ymax})
79
+ objects.append({
80
+ 'name': class_name,
81
+ 'xmin': xmin,
82
+ 'ymin': ymin,
83
+ 'xmax': xmax,
84
+ 'ymax': ymax,
85
+ 'has_segmentation': has_segmentation,
86
+ })
71
87
  self.class_names.add(class_name)
88
+
72
89
  # polyline, keypoint 등은 무시
73
- return objects
90
+ return objects, has_segmentation
74
91
 
75
92
  def _convert_split_dir(self, split_dir: str, split_name: str):
76
93
  """Convert a split dir (train/valid/test) to list of (xml_tree, xml_filename, img_src, img_name)."""
@@ -89,8 +106,10 @@ class FromDMToPascalConverter(FromDMConverter):
89
106
  with Image.open(img_path) as img:
90
107
  width, height = img.size
91
108
  depth = len(img.getbands())
92
- objects = self.parse_dm_annotations(img_ann)
93
- xml_tree = self.build_pascal_xml(os.path.basename(img_path), (width, height, depth), objects)
109
+ objects, has_segmentation = self.parse_dm_annotations(img_ann)
110
+ xml_tree = self.build_pascal_xml(
111
+ os.path.basename(img_path), (width, height, depth), objects, has_segmentation
112
+ )
94
113
  xml_filename = base + '.xml'
95
114
  results.append((xml_tree, xml_filename, img_path, os.path.basename(img_path)))
96
115
  return results
@@ -112,8 +131,10 @@ class FromDMToPascalConverter(FromDMConverter):
112
131
  with Image.open(img_path) as img:
113
132
  width, height = img.size
114
133
  depth = len(img.getbands())
115
- objects = self.parse_dm_annotations(img_ann)
116
- xml_tree = self.build_pascal_xml(os.path.basename(img_path), (width, height, depth), objects)
134
+ objects, has_segmentation = self.parse_dm_annotations(img_ann)
135
+ xml_tree = self.build_pascal_xml(
136
+ os.path.basename(img_path), (width, height, depth), objects, has_segmentation
137
+ )
117
138
  xml_filename = base + '.xml'
118
139
  results.append((xml_tree, xml_filename, img_path, os.path.basename(img_path)))
119
140
  return results
@@ -202,12 +223,13 @@ class FromDMToPascalConverter(FromDMConverter):
202
223
  # Process annotations from the first (and only) image in data
203
224
  if 'images' in data and len(data['images']) > 0:
204
225
  img_ann = data['images'][0]
205
- objects = self.parse_dm_annotations(img_ann)
226
+ objects, has_segmentation = self.parse_dm_annotations(img_ann)
206
227
  else:
207
228
  objects = []
229
+ has_segmentation = False
208
230
 
209
231
  # Build Pascal VOC XML
210
- xml_tree = self.build_pascal_xml(img_filename, (width, height, depth), objects)
232
+ xml_tree = self.build_pascal_xml(img_filename, (width, height, depth), objects, has_segmentation)
211
233
  xml_filename = os.path.splitext(img_filename)[0] + '.xml'
212
234
 
213
235
  # Convert XML tree to string for easy viewing
@@ -23,10 +23,23 @@ class FileSystemStorage(BaseStorage):
23
23
  >>> storage = FileSystemStorage(config)
24
24
  """
25
25
 
26
- def __init__(self, url):
27
- super().__init__(url)
26
+ def __init__(self, connection_params: str | dict):
27
+ super().__init__(connection_params)
28
28
  self.base_path = Path(self.query_params['location'])
29
29
 
30
+ def get_pathlib(self, path):
31
+ """Get the path as a pathlib object.
32
+
33
+ Args:
34
+ path (str): The path to convert.
35
+
36
+ Returns:
37
+ pathlib.Path: The converted path.
38
+ """
39
+ if path == '/' or path == '':
40
+ return self.base_path
41
+ return self.base_path / path
42
+
30
43
  def upload(self, source, target):
31
44
  """Upload a file from source to target location.
32
45
 
@@ -72,17 +85,6 @@ class FileSystemStorage(BaseStorage):
72
85
  target_path = self.base_path / target
73
86
  return f'file://{target_path.absolute()}'
74
87
 
75
- def get_pathlib(self, path):
76
- """Get the path as a pathlib object.
77
-
78
- Args:
79
- path (str): The path to convert.
80
-
81
- Returns:
82
- pathlib.Path: The converted path.
83
- """
84
- return self.base_path / path
85
-
86
88
  def get_path_file_count(self, pathlib_obj):
87
89
  """Get the file count in the path.
88
90
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: synapse-sdk
3
- Version: 1.0.0a95
3
+ Version: 1.0.0a98
4
4
  Summary: synapse sdk
5
5
  Author-email: datamaker <developer@datamaker.io>
6
6
  License: MIT
@@ -165,7 +165,7 @@ synapse_sdk/plugins/categories/smart_tool/templates/plugin/__init__.py,sha256=47
165
165
  synapse_sdk/plugins/categories/smart_tool/templates/plugin/auto_label.py,sha256=eevNg0nOcYFR4z_L_R-sCvVOYoLWSAH1jwDkAf3YCjY,320
166
166
  synapse_sdk/plugins/categories/upload/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
167
167
  synapse_sdk/plugins/categories/upload/actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
168
- synapse_sdk/plugins/categories/upload/actions/upload.py,sha256=W2GYvzzV1ZPljUezwZiFYlihq1muIJVdinnsNW7Nyw8,37673
168
+ synapse_sdk/plugins/categories/upload/actions/upload.py,sha256=YATMn9ud8cqWKw4Pq14XhuCPvn5NTq_7RyfZv5hG75w,38279
169
169
  synapse_sdk/plugins/categories/upload/templates/config.yaml,sha256=6_dRa0_J2aS8NSUfO4MKbPxZcdPS2FpJzzp51edYAZc,281
170
170
  synapse_sdk/plugins/categories/upload/templates/plugin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
171
171
  synapse_sdk/plugins/categories/upload/templates/plugin/upload.py,sha256=IZU4sdSMSLKPCtlNqF7DP2howTdYR6hr74HCUZsGdPk,1559
@@ -204,7 +204,7 @@ synapse_sdk/utils/converters/dm/__init__.py,sha256=_B6w814bMPhisNCNlSPEiQOs9RH0E
204
204
  synapse_sdk/utils/converters/dm/from_v1.py,sha256=4BG_NA_7YdW5rI1F8LCFg39M-IJZVfRgi2b9FBxTAmw,26059
205
205
  synapse_sdk/utils/converters/dm/to_v1.py,sha256=A123zAR_dLqEW83BgAl5_J1ACstjZWTHivlW5qvOu_E,13432
206
206
  synapse_sdk/utils/converters/pascal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
207
- synapse_sdk/utils/converters/pascal/from_dm.py,sha256=GKO1zT6SvvEFWuHvBIgl1Fn2UQHw8xpZ1Ikgq9kacEY,10378
207
+ synapse_sdk/utils/converters/pascal/from_dm.py,sha256=kyVl1TBsPY-zWNusMNX5kjKD3VUu-HO71-HJ_b0NNec,11119
208
208
  synapse_sdk/utils/converters/pascal/to_dm.py,sha256=bQNUepahOCot4J23LCPOlFOhIZJ8cAK-pge23eJZETM,8614
209
209
  synapse_sdk/utils/converters/yolo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
210
210
  synapse_sdk/utils/converters/yolo/from_dm.py,sha256=-JDCQLk4g1_FIVoOwZ1Tcs2kWFkhXRCAPVLKLXz6sLU,16180
@@ -216,14 +216,14 @@ synapse_sdk/utils/pydantic/validators.py,sha256=G47P8ObPhsePmd_QZDK8EdPnik2CbaYz
216
216
  synapse_sdk/utils/storage/__init__.py,sha256=HmZHqvoV-EogV2bE-Sw5XQRlrNuf3gfNL9irAJeRYsA,2195
217
217
  synapse_sdk/utils/storage/registry.py,sha256=-VNIM7wERubomcyXMuAlPPRKyy87kVpkRAsdlBRp2ig,589
218
218
  synapse_sdk/utils/storage/providers/__init__.py,sha256=crxrRzXXfBAmyR4nZS2RZvlLnr4IP1S-6eYeX_bSnLI,6412
219
- synapse_sdk/utils/storage/providers/file_system.py,sha256=MBBXxWRgVSDtjP4T0L0sbaZkXEI4B8ANtLweaMWtaaQ,3217
219
+ synapse_sdk/utils/storage/providers/file_system.py,sha256=kJJmVPOsDpRwZQ-Sh4VvOP1cfknJ2tiqPp6WnB93iqM,3329
220
220
  synapse_sdk/utils/storage/providers/gcp.py,sha256=i2BQCu1Kej1If9SuNr2_lEyTcr5M_ncGITZrL0u5wEA,363
221
221
  synapse_sdk/utils/storage/providers/http.py,sha256=2DhIulND47JOnS5ZY7MZUex7Su3peAPksGo1Wwg07L4,5828
222
222
  synapse_sdk/utils/storage/providers/s3.py,sha256=ZmqekAvIgcQBdRU-QVJYv1Rlp6VHfXwtbtjTSphua94,2573
223
223
  synapse_sdk/utils/storage/providers/sftp.py,sha256=_8s9hf0JXIO21gvm-JVS00FbLsbtvly4c-ETLRax68A,1426
224
- synapse_sdk-1.0.0a95.dist-info/licenses/LICENSE,sha256=bKzmC5YAg4V1Fhl8OO_tqY8j62hgdncAkN7VrdjmrGk,1101
225
- synapse_sdk-1.0.0a95.dist-info/METADATA,sha256=xvnJ6ZPqDHNbb1yBCb0jmh456ZLZTJjoWjhmGGXlSgk,3837
226
- synapse_sdk-1.0.0a95.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
227
- synapse_sdk-1.0.0a95.dist-info/entry_points.txt,sha256=VNptJoGoNJI8yLXfBmhgUefMsmGI0m3-0YoMvrOgbxo,48
228
- synapse_sdk-1.0.0a95.dist-info/top_level.txt,sha256=ytgJMRK1slVOKUpgcw3LEyHHP7S34J6n_gJzdkcSsw8,12
229
- synapse_sdk-1.0.0a95.dist-info/RECORD,,
224
+ synapse_sdk-1.0.0a98.dist-info/licenses/LICENSE,sha256=bKzmC5YAg4V1Fhl8OO_tqY8j62hgdncAkN7VrdjmrGk,1101
225
+ synapse_sdk-1.0.0a98.dist-info/METADATA,sha256=nCN-bJ6izW6M1RD2PEtcHLcWA5QpjGmhncI29PNERrg,3837
226
+ synapse_sdk-1.0.0a98.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
227
+ synapse_sdk-1.0.0a98.dist-info/entry_points.txt,sha256=VNptJoGoNJI8yLXfBmhgUefMsmGI0m3-0YoMvrOgbxo,48
228
+ synapse_sdk-1.0.0a98.dist-info/top_level.txt,sha256=ytgJMRK1slVOKUpgcw3LEyHHP7S34J6n_gJzdkcSsw8,12
229
+ synapse_sdk-1.0.0a98.dist-info/RECORD,,