unitysvc-services 0.2.6__py3-none-any.whl → 0.3.0__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.
@@ -421,7 +421,7 @@ def query_offerings(
421
421
  help="Output format: table, json",
422
422
  ),
423
423
  fields: str = typer.Option(
424
- "id,service_name,service_type,provider_name,status",
424
+ "id,name,service_type,provider_name,status",
425
425
  "--fields",
426
426
  help=(
427
427
  "Comma-separated list of fields to display. Available fields: "
@@ -447,7 +447,7 @@ def query_offerings(
447
447
  unitysvc_services query offerings
448
448
 
449
449
  # Show only specific fields
450
- unitysvc_services query offerings --fields id,service_name,status
450
+ unitysvc_services query offerings --fields id,name,status
451
451
 
452
452
  # Retrieve more than 100 records
453
453
  unitysvc_services query offerings --limit 500
@@ -469,7 +469,7 @@ def query_offerings(
469
469
  "provider_id",
470
470
  "status",
471
471
  "price",
472
- "service_name",
472
+ "name",
473
473
  "service_type",
474
474
  "provider_name",
475
475
  }
@@ -205,6 +205,54 @@ class DataValidator:
205
205
  normalized = normalized.strip("-")
206
206
  return normalized
207
207
 
208
+ def validate_with_pydantic_model(self, data: dict[str, Any], schema_name: str) -> list[str]:
209
+ """
210
+ Validate data using Pydantic models for additional validation rules.
211
+
212
+ This complements JSON schema validation with Pydantic field validators
213
+ like name format validation.
214
+
215
+ Args:
216
+ data: The data to validate
217
+ schema_name: The schema name (e.g., 'provider_v1', 'seller_v1')
218
+
219
+ Returns:
220
+ List of validation error messages
221
+ """
222
+ from pydantic import BaseModel
223
+
224
+ from unitysvc_services.models import ListingV1, ProviderV1, SellerV1, ServiceV1
225
+
226
+ errors: list[str] = []
227
+
228
+ # Map schema names to Pydantic model classes
229
+ model_map: dict[str, type[BaseModel]] = {
230
+ "provider_v1": ProviderV1,
231
+ "seller_v1": SellerV1,
232
+ "service_v1": ServiceV1,
233
+ "listing_v1": ListingV1,
234
+ }
235
+
236
+ if schema_name not in model_map:
237
+ return errors # No Pydantic model for this schema
238
+
239
+ model_class = model_map[schema_name]
240
+
241
+ try:
242
+ # Validate using the Pydantic model
243
+ model_class.model_validate(data)
244
+
245
+ except Exception as e:
246
+ # Extract meaningful error message from Pydantic ValidationError
247
+ error_msg = str(e)
248
+ # Pydantic errors can be verbose, try to extract just the relevant part
249
+ if "validation error" in error_msg.lower():
250
+ errors.append(f"Pydantic validation error: {error_msg}")
251
+ else:
252
+ errors.append(error_msg)
253
+
254
+ return errors
255
+
208
256
  def load_data_file(self, file_path: Path) -> tuple[dict[str, Any] | None, list[str]]:
209
257
  """Load data from JSON or TOML file."""
210
258
  errors: list[str] = []
@@ -259,6 +307,10 @@ class DataValidator:
259
307
  except Exception as e:
260
308
  errors.append(f"Validation error: {e}")
261
309
 
310
+ # Also validate using Pydantic models for additional validation rules
311
+ pydantic_errors = self.validate_with_pydantic_model(data, schema_name)
312
+ errors.extend(pydantic_errors)
313
+
262
314
  # Find Union[str, HttpUrl] fields and validate file references
263
315
  union_fields = self.find_union_fields(schema)
264
316
  file_ref_errors = self.validate_file_references(data, file_path, union_fields)
@@ -308,6 +360,10 @@ class DataValidator:
308
360
 
309
361
  # Find all data files with seller_v1 schema
310
362
  for file_path in self.data_dir.rglob("*"):
363
+ # Skip hidden directories (those starting with .)
364
+ if any(part.startswith(".") for part in file_path.parts):
365
+ continue
366
+
311
367
  if file_path.is_file() and file_path.suffix in [".json", ".toml"]:
312
368
  try:
313
369
  data, load_errors = self.load_data_file(file_path)
@@ -341,20 +397,17 @@ class DataValidator:
341
397
 
342
398
  warnings: list[str] = []
343
399
 
344
- # Find all provider files
345
- provider_files = list(self.data_dir.glob("*/provider.*"))
400
+ # Find all provider files (skip hidden directories)
401
+ provider_files = [
402
+ f for f in self.data_dir.glob("*/provider.*") if not any(part.startswith(".") for part in f.parts)
403
+ ]
346
404
 
347
405
  for provider_file in provider_files:
348
406
  try:
349
- # Load provider data
350
- data = {}
351
- if provider_file.suffix == ".json":
352
- with open(provider_file, encoding="utf-8") as f:
353
- data = json.load(f)
354
- elif provider_file.suffix == ".toml":
355
- with open(provider_file, "rb") as f:
356
- data = toml.load(f)
357
- else:
407
+ # Load provider data using existing helper method
408
+ data, load_errors = self.load_data_file(provider_file)
409
+ if load_errors or data is None:
410
+ warnings.append(f"Failed to load provider file {provider_file}: {load_errors}")
358
411
  continue
359
412
 
360
413
  # Parse as ProviderV1
@@ -391,20 +444,15 @@ class DataValidator:
391
444
 
392
445
  warnings: list[str] = []
393
446
 
394
- # Find all seller files
395
- seller_files = list(self.data_dir.glob("seller.*"))
447
+ # Find all seller files (skip hidden files)
448
+ seller_files = [f for f in self.data_dir.glob("seller.*") if not f.name.startswith(".")]
396
449
 
397
450
  for seller_file in seller_files:
398
451
  try:
399
- # Load seller data
400
- data = {}
401
- if seller_file.suffix == ".json":
402
- with open(seller_file, encoding="utf-8") as f:
403
- data = json.load(f)
404
- elif seller_file.suffix == ".toml":
405
- with open(seller_file, "rb") as f:
406
- data = toml.load(f)
407
- else:
452
+ # Load seller data using existing helper method
453
+ data, load_errors = self.load_data_file(seller_file)
454
+ if load_errors or data is None:
455
+ warnings.append(f"Failed to load seller file {seller_file}: {load_errors}")
408
456
  continue
409
457
 
410
458
  # Parse as SellerV1
@@ -448,8 +496,12 @@ class DataValidator:
448
496
  provider_warnings,
449
497
  ) # Warnings, not errors
450
498
 
451
- # Find all data and MD files recursively
499
+ # Find all data and MD files recursively, skipping hidden directories
452
500
  for file_path in self.data_dir.rglob("*"):
501
+ # Skip hidden directories (those starting with .)
502
+ if any(part.startswith(".") for part in file_path.parts):
503
+ continue
504
+
453
505
  if file_path.is_file() and file_path.suffix in [".json", ".toml", ".md"]:
454
506
  relative_path = file_path.relative_to(self.data_dir)
455
507
 
@@ -560,6 +612,10 @@ class DataValidator:
560
612
 
561
613
  for pattern in ["*.json", "*.toml"]:
562
614
  for file_path in data_dir.rglob(pattern):
615
+ # Skip hidden directories (those starting with .)
616
+ if any(part.startswith(".") for part in file_path.parts):
617
+ continue
618
+
563
619
  try:
564
620
  data, load_errors = self.load_data_file(file_path)
565
621
  if load_errors or data is None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: unitysvc-services
3
- Version: 0.2.6
3
+ Version: 0.3.0
4
4
  Summary: SDK for digital service providers on UnitySVC
5
5
  Author-email: Bo Peng <bo.peng@unitysvc.com>
6
6
  Maintainer-email: Bo Peng <bo.peng@unitysvc.com>
@@ -0,0 +1,24 @@
1
+ unitysvc_services/__init__.py,sha256=J6F3RlZCJUVjhZoprfbrYCxe3l9ynQQbGO7pf7FyqlM,110
2
+ unitysvc_services/cli.py,sha256=OK0IZyAckxP15jRWU_W49hl3t7XcNRtd8BoDMyRKqNM,682
3
+ unitysvc_services/format_data.py,sha256=Jl9Vj3fRX852fHSUa5DzO-oiFQwuQHC3WMCDNIlo1Lc,5460
4
+ unitysvc_services/list.py,sha256=QDp9BByaoeFeJxXJN9RQ-jU99mH9Guq9ampfXCbpZmI,7033
5
+ unitysvc_services/populate.py,sha256=zkcjIy8BWuQSO7JwiRNHKgGoxQvc3ujluUQdYixdBvY,6626
6
+ unitysvc_services/publisher.py,sha256=sNqGbLQ3QulNCGzyRjBg6ks-I2nTVgip4vGFV4XCUto,52285
7
+ unitysvc_services/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ unitysvc_services/query.py,sha256=x2VUnfva21-mVd-JgtChajNBgXG1AQJ6c3umCw2FNWU,24089
9
+ unitysvc_services/scaffold.py,sha256=Y73IX8vskImxSvxDgR0mvEFuAMYnBKfttn3bjcz3jmQ,40331
10
+ unitysvc_services/update.py,sha256=K9swocTUnqqiSgARo6GmuzTzUySSpyqqPPW4xF7ZU-g,9659
11
+ unitysvc_services/utils.py,sha256=GN0gkVTU8fOx2G0EbqnWmx8w9eFsoPfRprPjwCyPYkE,11371
12
+ unitysvc_services/validator.py,sha256=VAII5mu_Jdyr96v4nwXzihsoAj7DJiXN6LjhL8lGGUo,29054
13
+ unitysvc_services/models/__init__.py,sha256=hJCc2KSZmIHlKWKE6GpLGdeVB6LIpyVUKiOKnwmKvCs,200
14
+ unitysvc_services/models/base.py,sha256=3FdlR-_tBOFC2JbVNFNQA4-D1Lhlo5UZQh1QDgKnS_I,18293
15
+ unitysvc_services/models/listing_v1.py,sha256=PPb9hIdWQp80AWKLxFXYBDcWXzNcDrO4v6rqt5_i2qo,3083
16
+ unitysvc_services/models/provider_v1.py,sha256=76EK1i0hVtdx_awb00-ZMtSj4Oc9Zp4xZ-DeXmG3iTY,2701
17
+ unitysvc_services/models/seller_v1.py,sha256=oll2ZZBPBDX8wslHrbsCKf_jIqHNte2VEj5RJ9bawR4,3520
18
+ unitysvc_services/models/service_v1.py,sha256=Xpk-K-95M1LRqYM8nNJcll8t-lsW9Xdi2_bVbYNs8-M,3019
19
+ unitysvc_services-0.3.0.dist-info/licenses/LICENSE,sha256=_p8V6A8OMPu2HIztn3O01v0-urZFwk0Dd3Yk_PTIlL8,1065
20
+ unitysvc_services-0.3.0.dist-info/METADATA,sha256=QPZzgXqlKCPdsJCuWnbxxcXe7sfk-SBTxCJbq2npEc8,6628
21
+ unitysvc_services-0.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
22
+ unitysvc_services-0.3.0.dist-info/entry_points.txt,sha256=-vodnbPmo7QQmFu8jdG6sCyGRVM727w9Nhwp4Vwau_k,64
23
+ unitysvc_services-0.3.0.dist-info/top_level.txt,sha256=GIotQj-Ro2ruR7eupM1r58PWqIHTAq647ORL7E2kneo,18
24
+ unitysvc_services-0.3.0.dist-info/RECORD,,
@@ -1,24 +0,0 @@
1
- unitysvc_services/__init__.py,sha256=J6F3RlZCJUVjhZoprfbrYCxe3l9ynQQbGO7pf7FyqlM,110
2
- unitysvc_services/cli.py,sha256=OK0IZyAckxP15jRWU_W49hl3t7XcNRtd8BoDMyRKqNM,682
3
- unitysvc_services/format_data.py,sha256=Jl9Vj3fRX852fHSUa5DzO-oiFQwuQHC3WMCDNIlo1Lc,5460
4
- unitysvc_services/list.py,sha256=QDp9BByaoeFeJxXJN9RQ-jU99mH9Guq9ampfXCbpZmI,7033
5
- unitysvc_services/populate.py,sha256=zkcjIy8BWuQSO7JwiRNHKgGoxQvc3ujluUQdYixdBvY,6626
6
- unitysvc_services/publisher.py,sha256=s3px0i1ov6FisnnYG-gkkMHwJhnGbf-Ug225vosfxxM,35733
7
- unitysvc_services/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- unitysvc_services/query.py,sha256=Fz7ZXm_TOf2BVZsTUKGp61OArAjhChpdJsBUFDGaOrA,24113
9
- unitysvc_services/scaffold.py,sha256=Y73IX8vskImxSvxDgR0mvEFuAMYnBKfttn3bjcz3jmQ,40331
10
- unitysvc_services/update.py,sha256=K9swocTUnqqiSgARo6GmuzTzUySSpyqqPPW4xF7ZU-g,9659
11
- unitysvc_services/utils.py,sha256=GN0gkVTU8fOx2G0EbqnWmx8w9eFsoPfRprPjwCyPYkE,11371
12
- unitysvc_services/validator.py,sha256=zuFA44ezKlfUTtdJ8M2Xd7nk1Eot4HxbBksEUaIIpZs,26790
13
- unitysvc_services/models/__init__.py,sha256=hJCc2KSZmIHlKWKE6GpLGdeVB6LIpyVUKiOKnwmKvCs,200
14
- unitysvc_services/models/base.py,sha256=gm3xlcC35QNRST5ikJPhdk-dTTXoY9D_5Jxkyt8SBCU,13173
15
- unitysvc_services/models/listing_v1.py,sha256=FJWRMdouz3NgiNI6E4uBxG1V_Cbb249NpKyKgvAwtRM,2450
16
- unitysvc_services/models/provider_v1.py,sha256=cYK5kDDmzQEnLvUC2C8dKz-ZXci7hVn3fjNrJkaSr10,2050
17
- unitysvc_services/models/seller_v1.py,sha256=SU4rqYAh9hE4EeUrEkqaVrLwusenV7MotPF77VcsRKo,3263
18
- unitysvc_services/models/service_v1.py,sha256=u16zqM3khrJoTw_v0d45tMcKXjko5k_v3w8xwUtZ6nM,2720
19
- unitysvc_services-0.2.6.dist-info/licenses/LICENSE,sha256=_p8V6A8OMPu2HIztn3O01v0-urZFwk0Dd3Yk_PTIlL8,1065
20
- unitysvc_services-0.2.6.dist-info/METADATA,sha256=AjeLF0eSLtzkflQsrL3GP99DdZ853cfsZfWksap6AWw,6628
21
- unitysvc_services-0.2.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
22
- unitysvc_services-0.2.6.dist-info/entry_points.txt,sha256=-vodnbPmo7QQmFu8jdG6sCyGRVM727w9Nhwp4Vwau_k,64
23
- unitysvc_services-0.2.6.dist-info/top_level.txt,sha256=GIotQj-Ro2ruR7eupM1r58PWqIHTAq647ORL7E2kneo,18
24
- unitysvc_services-0.2.6.dist-info/RECORD,,