mirror of
https://gitlab.com/fdroid/fdroidserver.git
synced 2024-11-04 22:40:12 +01:00
Merge branch 'enforce-list-data-types' into 'master'
Enforce list data types Closes #578 See merge request fdroid/fdroidserver!583
This commit is contained in:
commit
2a9bc448ee
@ -473,6 +473,29 @@ def check_extlib_dir(apps):
|
||||
yield _("Unused extlib at %s") % os.path.join(dir_path, path)
|
||||
|
||||
|
||||
def check_app_field_types(app):
|
||||
"""Check the fields have valid data types"""
|
||||
|
||||
for field in app.keys():
|
||||
v = app.get(field)
|
||||
t = metadata.fieldtype(field)
|
||||
if v is None:
|
||||
continue
|
||||
elif field == 'builds':
|
||||
if not isinstance(v, list):
|
||||
yield(_("{appid}: {field} must be a '{type}', but it is a '{fieldtype}'!")
|
||||
.format(appid=app.id, field=field,
|
||||
type='list', fieldtype=v.__class__.__name__))
|
||||
elif t == metadata.TYPE_LIST and not isinstance(v, list):
|
||||
yield(_("{appid}: {field} must be a '{type}', but it is a '{fieldtype}!'")
|
||||
.format(appid=app.id, field=field,
|
||||
type='list', fieldtype=v.__class__.__name__))
|
||||
elif t == metadata.TYPE_STRING and not type(v) in (str, bool, dict):
|
||||
yield(_("{appid}: {field} must be a '{type}', but it is a '{fieldtype}'!")
|
||||
.format(appid=app.id, field=field,
|
||||
type='str', fieldtype=v.__class__.__name__))
|
||||
|
||||
|
||||
def check_for_unsupported_metadata_files(basedir=""):
|
||||
"""Checks whether any non-metadata files are in metadata/"""
|
||||
|
||||
@ -538,6 +561,7 @@ def main():
|
||||
continue
|
||||
|
||||
app_check_funcs = [
|
||||
check_app_field_types,
|
||||
check_regexes,
|
||||
check_update_check_data_url,
|
||||
check_vercode_operation,
|
||||
|
@ -156,7 +156,7 @@ class App(dict):
|
||||
self.Disabled = None
|
||||
self.AntiFeatures = []
|
||||
self.Provides = None
|
||||
self.Categories = ['None']
|
||||
self.Categories = []
|
||||
self.License = 'Unknown'
|
||||
self.AuthorName = None
|
||||
self.AuthorEmail = None
|
||||
@ -228,16 +228,15 @@ TYPE_LIST = 4
|
||||
TYPE_SCRIPT = 5
|
||||
TYPE_MULTILINE = 6
|
||||
TYPE_BUILD = 7
|
||||
TYPE_BUILD_V2 = 8
|
||||
TYPE_INT = 9
|
||||
TYPE_INT = 8
|
||||
|
||||
fieldtypes = {
|
||||
'Description': TYPE_MULTILINE,
|
||||
'MaintainerNotes': TYPE_MULTILINE,
|
||||
'Categories': TYPE_LIST,
|
||||
'AntiFeatures': TYPE_LIST,
|
||||
'BuildVersion': TYPE_BUILD,
|
||||
'Build': TYPE_BUILD_V2,
|
||||
'Build': TYPE_BUILD,
|
||||
'BuildVersion': TYPE_OBSOLETE,
|
||||
'UseBuilt': TYPE_OBSOLETE,
|
||||
}
|
||||
|
||||
@ -902,12 +901,14 @@ def post_metadata_parse(app):
|
||||
if 'flavours' in app and app['flavours'] == [True]:
|
||||
app['flavours'] = 'yes'
|
||||
|
||||
if isinstance(app.Categories, str):
|
||||
app.Categories = [app.Categories]
|
||||
elif app.Categories is None:
|
||||
app.Categories = ['None']
|
||||
else:
|
||||
app.Categories = [str(i) for i in app.Categories]
|
||||
for field, fieldtype in fieldtypes.items():
|
||||
if fieldtype != TYPE_LIST:
|
||||
continue
|
||||
value = app.get(field)
|
||||
if isinstance(value, str):
|
||||
app[field] = [value, ]
|
||||
elif value is not None:
|
||||
app[field] = [str(i) for i in value]
|
||||
|
||||
def _yaml_bool_unmapable(v):
|
||||
return v in (True, False, [True], [False])
|
||||
@ -1333,7 +1334,7 @@ def parse_txt_metadata(mf, app):
|
||||
f = f.replace(' ', '')
|
||||
|
||||
ftype = fieldtype(f)
|
||||
if ftype not in [TYPE_BUILD, TYPE_BUILD_V2]:
|
||||
if ftype not in [TYPE_BUILD]:
|
||||
add_comments(f)
|
||||
if ftype == TYPE_MULTILINE:
|
||||
mode = 1
|
||||
@ -1345,15 +1346,6 @@ def parse_txt_metadata(mf, app):
|
||||
elif ftype == TYPE_LIST:
|
||||
app[f] = split_list_values(v)
|
||||
elif ftype == TYPE_BUILD:
|
||||
if v.endswith("\\"):
|
||||
mode = 2
|
||||
del buildlines[:]
|
||||
buildlines.append(v[:-1])
|
||||
else:
|
||||
build = parse_buildline([v])
|
||||
app.builds.append(build)
|
||||
add_comments('build:' + app.builds[-1].versionCode)
|
||||
elif ftype == TYPE_BUILD_V2:
|
||||
vv = v.split(',')
|
||||
if len(vv) != 2:
|
||||
warn_or_exception(_('Build should have comma-separated '
|
||||
@ -1372,7 +1364,9 @@ def parse_txt_metadata(mf, app):
|
||||
del buildlines[:]
|
||||
mode = 3
|
||||
elif ftype == TYPE_OBSOLETE:
|
||||
pass # Just throw it away!
|
||||
warn_or_exception(_("'{field}' in {linedesc} is obsolete, see docs for current fields:")
|
||||
.format(field=f, linedesc=linedesc)
|
||||
+ '\nhttps://f-droid.org/docs/')
|
||||
else:
|
||||
warn_or_exception(_("Unrecognised field '{field}' in {linedesc}")
|
||||
.format(field=f, linedesc=linedesc))
|
||||
|
@ -70,6 +70,59 @@ class LintTest(unittest.TestCase):
|
||||
logging.debug(warn)
|
||||
self.assertTrue(anywarns)
|
||||
|
||||
def test_check_app_field_types(self):
|
||||
config = dict()
|
||||
fdroidserver.common.fill_config_defaults(config)
|
||||
fdroidserver.common.config = config
|
||||
fdroidserver.lint.config = config
|
||||
|
||||
app = fdroidserver.metadata.App()
|
||||
app.id = 'fake.app'
|
||||
app.Name = 'Bad App'
|
||||
app.Summary = 'We pwn you'
|
||||
app.Description = 'These are some back'
|
||||
|
||||
fields = {
|
||||
'AntiFeatures': {
|
||||
'good': [
|
||||
['KnownVuln', ],
|
||||
['NonFreeNet', 'KnownVuln'],
|
||||
],
|
||||
'bad': [
|
||||
'KnownVuln',
|
||||
'NonFreeNet,KnownVuln',
|
||||
],
|
||||
},
|
||||
'Categories': {
|
||||
'good': [
|
||||
['Sports & Health', ],
|
||||
['Multimedia', 'Graphics'],
|
||||
],
|
||||
'bad': [
|
||||
'Science & Education',
|
||||
'Multimedia,Graphics',
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
for field, values in fields.items():
|
||||
|
||||
for bad in values['bad']:
|
||||
anywarns = False
|
||||
app[field] = bad
|
||||
for warn in fdroidserver.lint.check_app_field_types(app):
|
||||
anywarns = True
|
||||
logging.debug(warn)
|
||||
self.assertTrue(anywarns)
|
||||
|
||||
for good in values['good']:
|
||||
anywarns = False
|
||||
app[field] = good
|
||||
for warn in fdroidserver.lint.check_app_field_types(app):
|
||||
anywarns = True
|
||||
logging.debug(warn)
|
||||
self.assertFalse(anywarns)
|
||||
|
||||
def test_check_vercode_operation(self):
|
||||
config = dict()
|
||||
fdroidserver.common.fill_config_defaults(config)
|
||||
|
Loading…
Reference in New Issue
Block a user