1010import argparse
1111import plistlib
1212from datetime import datetime
13+ from xml .parsers .expat import ExpatError
1314
14- from pre_commit_hooks .util import PLIST_TYPES , validate_required_keys
15+ from pre_commit_hooks .util import PLIST_TYPES
1516
1617# List keys and their expected item types
1718PFM_LIST_TYPES = {
@@ -38,6 +39,16 @@ def build_argument_parser():
3839 return parser
3940
4041
42+ def validate_required_keys (input_dict , required_keys , dict_name , filename ):
43+ """Verifies that required_keys are present in dictionary."""
44+ passed = True
45+ for req_key in required_keys :
46+ if not input_dict .get (req_key ):
47+ print ("{}: {} missing required key {}" .format (filename , dict_name , req_key ))
48+ passed = False
49+ return passed
50+
51+
4152def validate_manifest_key_types (manifest , filename ):
4253 """Validation of manifest key types."""
4354
@@ -265,17 +276,18 @@ def validate_pfm_default(subkey, filename):
265276 # TODO: Should we validate pfm_value_placeholder here too?
266277 for test_key in ("pfm_default" ,):
267278 if test_key in subkey :
268- if PLIST_TYPES [subkey ["pfm_type" ]] == list :
269- try :
270- desired_type = type (subkey ["pfm_subkeys" ][0 ])
271- except IndexError :
272- # Unknown desired type
273- continue
274- else :
275- desired_type = PLIST_TYPES [subkey ["pfm_type" ]]
279+ # TODO: Should the default for list types be the type of the first list item, or <list> itself?
280+ # if PLIST_TYPES[subkey["pfm_type"]] == list:
281+ # try:
282+ # desired_type = type(subkey["pfm_subkeys"][0])
283+ # except IndexError:
284+ # # Unknown desired type
285+ # continue
286+ # else:
287+ desired_type = PLIST_TYPES [subkey ["pfm_type" ]]
276288 if type (subkey [test_key ]) != desired_type :
277289 print (
278- "{}: {} value for {} should be {}, not {}" .format (
290+ "{}: {} value for {} should be type {}, not type {}" .format (
279291 filename ,
280292 test_key ,
281293 subkey .get ("pfm_name" ),
@@ -316,14 +328,23 @@ def validate_subkeys(subkeys, filename):
316328
317329 # Check for presence of required keys.
318330 required_keys = ("pfm_type" ,)
319- if not validate_required_keys (subkey , filename , required_keys ):
331+ if not validate_required_keys (
332+ subkey , required_keys , subkey .get ("pfm_name" , "<unnamed key>" ), filename
333+ ):
320334 passed = False
321335 break # No need to continue checking this list of subkeys
322336
323337 # Check for rogue pfm_type strings and deprecated keys.
324338 if not validate_pfm_type_strings (subkey , filename ):
325339 passed = False
326340
341+ # Check that list items are of the expected type
342+ if "pfm_type" not in subkey :
343+ print (
344+ "WARNING: Recommend adding a pfm_title to %s"
345+ % subkey .get ("pfm_name" , "<unnamed key>" )
346+ )
347+
327348 # Check that list items are of the expected type
328349 if not validate_list_item_types (subkey , filename ):
329350 passed = False
@@ -375,14 +396,16 @@ def main(argv=None):
375396
376397 # Check for presence of required keys.
377398 required_keys = ("pfm_title" , "pfm_domain" , "pfm_description" )
378- if not validate_required_keys (manifest , filename , required_keys ):
399+ if not validate_required_keys (manifest , required_keys , "<root dict>" , filename ):
379400 retval = 1
380401 break # No need to continue checking this file
381402
382403 # Ensure pfm_format_version has expected value
383404 if manifest .get ("pfm_format_version" , 1 ) != 1 :
384405 print (
385- "{}: pfm_format_version should be 1, not {}" .format (
406+ "{}: pfm_format_version should be 1, not {} "
407+ "(https://github.com/ProfileCreator/ProfileManifests"
408+ "/wiki/Manifest-Format-Versions)" .format (
386409 filename , manifest .get ("pfm_format_version" )
387410 )
388411 )
0 commit comments