azureml-registry-tools 0.1.0a15__py3-none-any.whl → 0.1.0a17__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.
- azureml/registry/data/model.schema.json +2 -1
- azureml/registry/data/validate_model_schema.py +72 -47
- azureml/registry/mgmt/asset_management.py +3 -0
- {azureml_registry_tools-0.1.0a15.dist-info → azureml_registry_tools-0.1.0a17.dist-info}/METADATA +1 -1
- {azureml_registry_tools-0.1.0a15.dist-info → azureml_registry_tools-0.1.0a17.dist-info}/RECORD +9 -9
- {azureml_registry_tools-0.1.0a15.dist-info → azureml_registry_tools-0.1.0a17.dist-info}/WHEEL +0 -0
- {azureml_registry_tools-0.1.0a15.dist-info → azureml_registry_tools-0.1.0a17.dist-info}/entry_points.txt +0 -0
- {azureml_registry_tools-0.1.0a15.dist-info → azureml_registry_tools-0.1.0a17.dist-info}/licenses/LICENSE.txt +0 -0
- {azureml_registry_tools-0.1.0a15.dist-info → azureml_registry_tools-0.1.0a17.dist-info}/top_level.txt +0 -0
@@ -432,7 +432,7 @@
|
|
432
432
|
"skuListDefinition": {
|
433
433
|
"type": "string",
|
434
434
|
"description": "A comma-separated list of valid SKUs with no duplicates",
|
435
|
-
"pattern": "^(Standard_(DS3_v2|NC12s_v3|NC16as_T4_v3|NC24ads_A100_v4|NC24rs_v3|NC24s_v3|NC40ads_H100_v5|NC48ads_A100_v4|NC4as_T4_v3|NC64as_T4_v3|NC6s_v3|NC80adis_H100_v5|NC8as_T4_v3|NC96ads_A100_v4|ND40rs_v2|ND96amsr_A100_v4|ND96asr_v4|ND96isr_H100_v5|DS12_v2|DS4_v2|DS5_v2|D16a_v4|D16as_v4|D32a_v4|D32as_v4|D48a_v4|D48as_v4|D64a_v4|D64as_v4|D8a_v4|D8as_v4|D96a_v4|D96as_v4|E16s_v3|E2s_v3|E32s_v3|E48s_v3|E4s_v3|E64s_v3|E8s_v3|F16s_v2|F32s_v2|F48s_v2|F4s_v2|F64s_v2|F72s_v2|F8s_v2|FX12mds|FX24mds|FX36mds|FX48mds|FX4mds|NV12s_v3|NV24s_v3|NV48s_v3))(?:\\s*,\\s*Standard_(DS3_v2|NC12s_v3|NC16as_T4_v3|NC24ads_A100_v4|NC24rs_v3|NC24s_v3|NC40ads_H100_v5|NC48ads_A100_v4|NC4as_T4_v3|NC64as_T4_v3|NC6s_v3|NC80adis_H100_v5|NC8as_T4_v3|NC96ads_A100_v4|ND40rs_v2|ND96amsr_A100_v4|ND96asr_v4|ND96isr_H100_v5|DS12_v2|DS4_v2|DS5_v2|D16a_v4|D16as_v4|D32a_v4|D32as_v4|D48a_v4|D48as_v4|D64a_v4|D64as_v4|D8a_v4|D8as_v4|D96a_v4|D96as_v4|E16s_v3|E2s_v3|E32s_v3|E48s_v3|E4s_v3|E64s_v3|E8s_v3|F16s_v2|F32s_v2|F48s_v2|F4s_v2|F64s_v2|F72s_v2|F8s_v2|FX12mds|FX24mds|FX36mds|FX48mds|FX4mds|NV12s_v3|NV24s_v3|NV48s_v3))*$"
|
435
|
+
"pattern": "^(Standard_(DS3_v2|NC12s_v3|NC16as_T4_v3|NC24ads_A100_v4|NC24rs_v3|NC24s_v3|NC40ads_H100_v5|NC48ads_A100_v4|NC4as_T4_v3|NC64as_T4_v3|NC6s_v3|NC80adis_H100_v5|NC8as_T4_v3|NC96ads_A100_v4|ND40rs_v2|ND96amsr_A100_v4|ND96amsr_v4|ND96asr_v4|ND96isr_H100_v5|DS12_v2|DS4_v2|DS5_v2|D16a_v4|D16as_v4|D32a_v4|D32as_v4|D48a_v4|D48as_v4|D64a_v4|D64as_v4|D8a_v4|D8as_v4|D96a_v4|D96as_v4|E16s_v3|E2s_v3|E32s_v3|E48s_v3|E4s_v3|E64s_v3|E8s_v3|F16s_v2|F32s_v2|F48s_v2|F4s_v2|F64s_v2|F72s_v2|F8s_v2|FX12mds|FX24mds|FX36mds|FX48mds|FX4mds|NV12s_v3|NV24s_v3|NV48s_v3))(?:\\s*,\\s*Standard_(DS3_v2|NC12s_v3|NC16as_T4_v3|NC24ads_A100_v4|NC24rs_v3|NC24s_v3|NC40ads_H100_v5|NC48ads_A100_v4|NC4as_T4_v3|NC64as_T4_v3|NC6s_v3|NC80adis_H100_v5|NC8as_T4_v3|NC96ads_A100_v4|ND40rs_v2|ND96amsr_A100_v4|ND96amsr_v4|ND96asr_v4|ND96isr_H100_v5|DS12_v2|DS4_v2|DS5_v2|D16a_v4|D16as_v4|D32a_v4|D32as_v4|D48a_v4|D48as_v4|D64a_v4|D64as_v4|D8a_v4|D8as_v4|D96a_v4|D96as_v4|E16s_v3|E2s_v3|E32s_v3|E48s_v3|E4s_v3|E64s_v3|E8s_v3|F16s_v2|F32s_v2|F48s_v2|F4s_v2|F64s_v2|F72s_v2|F8s_v2|FX12mds|FX24mds|FX36mds|FX48mds|FX4mds|NV12s_v3|NV24s_v3|NV48s_v3))*$"
|
436
436
|
},
|
437
437
|
"skuEnum": {
|
438
438
|
"enum": [
|
@@ -452,6 +452,7 @@
|
|
452
452
|
"Standard_NC96ads_A100_v4",
|
453
453
|
"Standard_ND40rs_v2",
|
454
454
|
"Standard_ND96amsr_A100_v4",
|
455
|
+
"Standard_ND96amsr_v4",
|
455
456
|
"Standard_ND96asr_v4",
|
456
457
|
"Standard_ND96isr_H100_v5",
|
457
458
|
"Standard_DS12_v2",
|
@@ -53,7 +53,8 @@ def load_schema(schema_file: Path, allow_additional_properties: bool = False) ->
|
|
53
53
|
def validate_model_schema(input_dirs: List[Path],
|
54
54
|
schema_file: Path,
|
55
55
|
asset_config_filename: str,
|
56
|
-
allow_additional_properties: bool = False
|
56
|
+
allow_additional_properties: bool = False,
|
57
|
+
changed_files: List[Path] = None) -> bool:
|
57
58
|
"""Validate model variant schema.
|
58
59
|
|
59
60
|
Args:
|
@@ -61,6 +62,7 @@ def validate_model_schema(input_dirs: List[Path],
|
|
61
62
|
schema_file (Path): File containing model variant schema.
|
62
63
|
asset_config_filename (str): Asset config filename to search for.
|
63
64
|
allow_additional_properties (bool): Whether to allow additional properties not defined in schema.
|
65
|
+
changed_files (List[Path], optional): List of changed files, used to filter assets. Defaults to None.
|
64
66
|
|
65
67
|
Returns:
|
66
68
|
bool: True on success.
|
@@ -71,63 +73,82 @@ def validate_model_schema(input_dirs: List[Path],
|
|
71
73
|
# Create validator instance for collecting all errors
|
72
74
|
validator = jsonschema.Draft7Validator(loaded_schema)
|
73
75
|
|
76
|
+
# Gather list of just changed assets, for later filtering
|
77
|
+
changed_assets = util.find_asset_config_files(input_dirs, asset_config_filename, changed_files) if changed_files else None # noqa: E501
|
78
|
+
|
74
79
|
asset_count = 0
|
75
80
|
model_count = 0
|
81
|
+
changed_model_count = 0
|
76
82
|
error_count = 0
|
77
83
|
for input_dir in input_dirs:
|
78
84
|
# Recursively find all files with the name matching asset_config_filename
|
79
|
-
for
|
85
|
+
for asset_config_path in util.find_asset_config_files(input_dir, asset_config_filename):
|
80
86
|
asset_count += 1
|
87
|
+
|
88
|
+
validate_this = changed_assets is None or asset_config_path in changed_assets
|
89
|
+
|
90
|
+
try:
|
91
|
+
asset_config = assets.AssetConfig(asset_config_path)
|
92
|
+
except Exception as e:
|
93
|
+
raise Exception(f"Error loading asset config from {asset_config_path}: {e}")
|
94
|
+
|
81
95
|
file_path = asset_config.spec_with_path
|
96
|
+
|
82
97
|
if asset_config.type == assets.AssetType.MODEL:
|
83
98
|
model_count += 1
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
99
|
+
|
100
|
+
if validate_this:
|
101
|
+
changed_model_count += 1
|
102
|
+
# Validate the file against the schema
|
103
|
+
try:
|
104
|
+
with open(file_path, "r") as f:
|
105
|
+
spec_config = yaml.safe_load(f)
|
106
|
+
|
107
|
+
# Collect all validation errors
|
108
|
+
errors = list(validator.iter_errors(spec_config))
|
109
|
+
|
110
|
+
if not errors:
|
111
|
+
logger.print(f"{file_path} is valid.")
|
112
|
+
else:
|
113
|
+
logger.log_error(f"\n‼️{file_path} has {len(errors)} validation error(s):")
|
114
|
+
|
115
|
+
for e in errors:
|
116
|
+
# Get detailed error information for each error
|
117
|
+
error_path = '.'.join(str(p) for p in e.path) if e.path else "root"
|
118
|
+
line_info = ""
|
119
|
+
|
120
|
+
# Get line number from jsonschema error if available
|
121
|
+
if hasattr(e, 'lineno') and e.lineno is not None:
|
122
|
+
line_info = f" at line {e.lineno}"
|
123
|
+
else:
|
124
|
+
# Try to find line number by looking at the path and instance
|
125
|
+
try:
|
126
|
+
with open(file_path, "r") as f:
|
127
|
+
yaml_content = f.readlines()
|
128
|
+
yaml_lines = []
|
129
|
+
for idx, line in enumerate(yaml_content):
|
130
|
+
if error_path in line:
|
131
|
+
yaml_lines.append(f"line {idx+1}: {line.strip()}")
|
132
|
+
if yaml_lines:
|
133
|
+
line_info = "\nPossible location(s):\n " + "\n ".join(yaml_lines)
|
134
|
+
except Exception:
|
135
|
+
pass
|
136
|
+
|
137
|
+
schema_path = '.'.join(str(p) for p in e.schema_path)
|
138
|
+
logger.print(f"⚠️ {file_path} is invalid at path '{error_path}'{line_info}:")
|
139
|
+
logger.print(f" Error: {e.message}")
|
140
|
+
logger.print(f" Instance: {e.instance}")
|
141
|
+
logger.print(f" Schema path: {schema_path}")
|
142
|
+
error_count += 1
|
143
|
+
except Exception as e:
|
144
|
+
logger.log_error(f"Error processing {file_path}: {str(e)}")
|
124
145
|
error_count += 1
|
125
|
-
except Exception as e:
|
126
|
-
logger.log_error(f"Error processing {file_path}: {str(e)}")
|
127
|
-
error_count += 1
|
128
146
|
|
129
147
|
logger.print(f"Found {asset_count} total asset(s).")
|
130
|
-
|
148
|
+
if changed_assets is not None:
|
149
|
+
logger.print(f"Found {error_count} model(s) with error(s) out of {changed_model_count} total changed model(s)")
|
150
|
+
else:
|
151
|
+
logger.print(f"Found {error_count} model(s) with error(s) out of {model_count} total model(s)")
|
131
152
|
return error_count == 0
|
132
153
|
|
133
154
|
|
@@ -142,16 +163,20 @@ if __name__ == "__main__":
|
|
142
163
|
help="Asset config file name to search for")
|
143
164
|
parser.add_argument("--allow-additional-properties", action="store_true",
|
144
165
|
help="Allow additional properties not defined in the schema")
|
166
|
+
parser.add_argument("-c", "--changed-files",
|
167
|
+
help="Comma-separated list of changed files, used to filter assets")
|
145
168
|
args = parser.parse_args()
|
146
169
|
|
147
170
|
# Convert comma-separated values to lists
|
148
171
|
input_dirs = [Path(d) for d in args.input_dirs.split(",")]
|
172
|
+
changed_files = [Path(f) for f in args.changed_files.split(",")] if args.changed_files else []
|
149
173
|
|
150
174
|
# Validate against model schema
|
151
175
|
success = validate_model_schema(input_dirs=input_dirs,
|
152
176
|
schema_file=args.schema_file,
|
153
177
|
asset_config_filename=args.asset_config_filename,
|
154
|
-
allow_additional_properties=args.allow_additional_properties
|
178
|
+
allow_additional_properties=args.allow_additional_properties,
|
179
|
+
changed_files=changed_files)
|
155
180
|
|
156
181
|
if not success:
|
157
182
|
sys.exit(1)
|
@@ -123,6 +123,9 @@ def build_mutable_asset(base_asset: AssetConfig, mutable_asset_dir: str, overrid
|
|
123
123
|
spec_config = yaml.safe_load(f)
|
124
124
|
spec_config["version"] = datetime.now().strftime("%Y%m%d%H%M%S")
|
125
125
|
|
126
|
+
# Remove intellectualPropertyPublisher if it exists in properties
|
127
|
+
spec_config["properties"].pop("intellectualPropertyPublisher", None)
|
128
|
+
|
126
129
|
with open(spec_config_file, "w") as f:
|
127
130
|
yaml.dump(spec_config, f)
|
128
131
|
|
{azureml_registry_tools-0.1.0a15.dist-info → azureml_registry_tools-0.1.0a17.dist-info}/RECORD
RENAMED
@@ -13,13 +13,13 @@ azureml/registry/data/asset.yaml.template,sha256=WTgfuvKEBp-EVFSQ0JpU0h4z_ULJdUL
|
|
13
13
|
azureml/registry/data/description.md.template,sha256=wQLk54U8hoXU1y9235R4irc6FGYPXGO-x9EHUorP15Q,84
|
14
14
|
azureml/registry/data/evaluation.md.template,sha256=JaDecIfLV9vZDUrZzVRPzVHHnKD-BQGBgQ-cw1dHavU,277
|
15
15
|
azureml/registry/data/model-variant.schema.json,sha256=AT4Dy6cCtp_SFUfSqYIqcER8AldpYm0QIEy1abY3QWE,1699
|
16
|
-
azureml/registry/data/model.schema.json,sha256=
|
16
|
+
azureml/registry/data/model.schema.json,sha256=TORbhePqEYovjg2Cem-JGJL7Tm-EbA00WvYeybMuWO4,26118
|
17
17
|
azureml/registry/data/model.yaml.template,sha256=h5uqAN22FLaWrbPxIb8yVKH9cGDBrIwooXYYfsKhxDw,245
|
18
18
|
azureml/registry/data/notes.md.template,sha256=zSRyOR__9NGL2j0tugY7HgFkwkAdcE2pJyyyGsz1SAk,248
|
19
|
-
azureml/registry/data/validate_model_schema.py,sha256=
|
19
|
+
azureml/registry/data/validate_model_schema.py,sha256=OQp2E01kdxSphvUQYQvelSiD24-qUG6nTFuzW60wX2c,8322
|
20
20
|
azureml/registry/data/validate_model_variant_schema.py,sha256=JPVNtRBn6qciMu4PaRXOvS86OGGW0cocL2Rri4xYKo8,3629
|
21
21
|
azureml/registry/mgmt/__init__.py,sha256=LMhqcEC8ItmmpKZljElGXH-6olHlT3SLl0dJU01OvuM,226
|
22
|
-
azureml/registry/mgmt/asset_management.py,sha256=
|
22
|
+
azureml/registry/mgmt/asset_management.py,sha256=x-deg8nwVODqDlIAZOagzghuBS7qG-j8h35TO0hcicI,11129
|
23
23
|
azureml/registry/mgmt/create_asset_template.py,sha256=ejwLuIsmzJOoUePoxbM-eGMg2E3QHfdX-nPMBzYUVMQ,3525
|
24
24
|
azureml/registry/mgmt/create_manifest.py,sha256=N9wRmjAKO09A3utN_lCUsM_Ufpj7PL0SJz-XHPHWuyM,9528
|
25
25
|
azureml/registry/mgmt/create_model_spec.py,sha256=1PdAcUf-LomvljoT8wKQihXMTLd7DoTgN0qDX4Lol1A,10473
|
@@ -30,9 +30,9 @@ azureml/registry/tools/config.py,sha256=tjPaoBsWtPXBL8Ww1hcJtsr2SuIjPKt79dR8iovc
|
|
30
30
|
azureml/registry/tools/create_or_update_assets.py,sha256=Q-_BV7KWn1huQn5JriKT_8xJNoQQ_HK5wCftrq9DepA,15988
|
31
31
|
azureml/registry/tools/registry_utils.py,sha256=zgYlCiOONtQJ4yZ9wg8tKVoE8dh6rrjB8hYBGhpV9-0,1403
|
32
32
|
azureml/registry/tools/repo2registry_config.py,sha256=eXp_tU8Jyi30g8xGf7wbpLgKEPpieohBANKxMSLzq7s,4873
|
33
|
-
azureml_registry_tools-0.1.
|
34
|
-
azureml_registry_tools-0.1.
|
35
|
-
azureml_registry_tools-0.1.
|
36
|
-
azureml_registry_tools-0.1.
|
37
|
-
azureml_registry_tools-0.1.
|
38
|
-
azureml_registry_tools-0.1.
|
33
|
+
azureml_registry_tools-0.1.0a17.dist-info/licenses/LICENSE.txt,sha256=n20rxwp7_NGrrShv9Qvcs90sjI1l3Pkt3m-5OPCWzgs,845
|
34
|
+
azureml_registry_tools-0.1.0a17.dist-info/METADATA,sha256=isMAD05HJyZh7u2C6jHaGd1JSMQSGSqxL3NLWjAx6OI,522
|
35
|
+
azureml_registry_tools-0.1.0a17.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
36
|
+
azureml_registry_tools-0.1.0a17.dist-info/entry_points.txt,sha256=iRUkAeQidMnO6RQzpLqMUBTcyYtNzAfSin9WnSdVGLw,147
|
37
|
+
azureml_registry_tools-0.1.0a17.dist-info/top_level.txt,sha256=ZOeEa0TAXo6i5wOjwBoqfIGEuxOcKuscGgNSpizqREY,8
|
38
|
+
azureml_registry_tools-0.1.0a17.dist-info/RECORD,,
|
{azureml_registry_tools-0.1.0a15.dist-info → azureml_registry_tools-0.1.0a17.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|