Univention Bugzilla – Attachment 6383 Details for
Bug 36730
Check description length
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
applint
applint (text/plain), 6.80 KB, created by
Philipp Hahn
on 2014-11-17 08:33 CET
(
hide
)
Description:
applint
Filename:
MIME Type:
Creator:
Philipp Hahn
Created:
2014-11-17 08:33 CET
Size:
6.80 KB
patch
obsolete
>#!/usr/bin/python >''' >Validate App-Center .ini files >''' >import os >import sys >import ConfigParser >import re >from optparse import OptionParser > >DIRS = ( > '/var/univention/buildsystem2/mirror/appcenter/meta-inf', > '/var/univention/buildsystem2/mirror/appcenter.test/meta-inf', >) >IGNORE_FILES = ( > 'categories.ini', >) >IGNORE_DIRS = ( > 'REMOVED', >) > > >def main(): > for top in parse_args(): > if os.path.isfile(top): > AppCheck(top).check() > elif os.path.isdir(top): > for pname in find(top): > AppCheck(pname).check() > else: > print >> sys.stderr, 'SKIP: "%s"' % top > > >def parse_args(): > description = sys.modules[__name__].__doc__ > parser = OptionParser(description=description) > options, args = parser.parse_args() > return args or DIRS > > >def find(top): > for root, dirs, files in os.walk(top): > zap(files, IGNORE_FILES) > for fname in files: > if not fname.endswith('.ini'): > continue > pname = os.path.join(root, fname) > yield pname > zap(dirs, IGNORE_DIRS) > > >def zap(names, remove): > for name in remove: > try: > names.remove(name) > except ValueError: > pass > > >class AppCheck(object): > def __init__(self, pname): > self.pname = pname > self.config = ConfigParser.RawConfigParser() > self.config.read((pname,)) > > def check(self): > for section in self.config.sections(): > with Section(self, section) as sec: > if section == 'Application': > sec.check_all(sec.APPLICATION) > elif section.startswith('Sizing: '): > sec.check_all(sec.SIZING) > else: > sec.check_all(sec.TRANSLATION) > > def log(self, msg, *args): > print self.pname, msg % args > > >class Error(Exception): > pass > > >class Final(Exception): > pass > > >class Fatal(Error, Final): > pass > > >class Value(object): > DOMAIN = r'(?:[0-9A-Za-z]+(?:[0-9A-Za-z-]*[0-9A-Za-z])?\.)+[0-9A-Za-z-]+(?:[0-9A-Za-z-]*[0-9A-Za-z])?' > PATH = r'/[#$%&+,./0-9:;=?@A-Z_a-z-]*' > RE_EMAIL = re.compile(r'^.+@' + DOMAIN + r'$') > RE_WWW = re.compile(r'^https?://' + DOMAIN + r'(?::\d+)?(?:' + PATH + r')?$') > RE_CAPACITY = re.compile(r'\d+(?:\s*[G]B)?$') > RE_URL = re.compile(r'^(?:https?://' + DOMAIN + r'(?::\d+)?)?' + PATH + r'$') > > def __init__(self, value): > self.value = value > > def __str__(self): > return str(self.value) > > def require(self): > if not self.value: > raise Fatal('Empty') > > def optional(self): > if not self.value: > raise Final() > > def is_bool(self): > if self.value in ('True', 'False', 'true', 'false'): > return > raise Error('Not boolean: %s' % self.value) > > def is_60c(self): > if len(self.value) <= 60: > return > raise Error('Over 60c long: >%s<>%s<' % (self.value[:61], self.value[61:])) > > def is_email(self): > if self.RE_EMAIL.match(self.value): > return > raise Error('No email: "%s"' % self.value) > > def is_www(self): > if self.RE_WWW.match(self.value): > return > raise Error('No WWW: "%s"' % self.value) > > def is_url(self): > if self.RE_URL.match(self.value): > return > raise Error('No URL: "%s"' % self.value) > > def is_role(self): > ALLOWED = set(('domaincontroller_master', 'domaincontroller_backup', 'domaincontroller_slave', 'memberserver')) > if set(self.value.split(',')) - ALLOWED: > raise Error('Invalid server role: "%s"' % self.value) > > def is_arch(self): > ALLOWED = set(('amd64', 'i386')) > if set(self.value.split(',')) - ALLOWED: > raise Error('Invalid architectures: "%s"' % self.value) > > def is_capacity(self): > if self.RE_CAPACITY.match(self.value): > return > raise Error('No capacity: "%s"' % self.value) > > def is_category(self): > ALLOWED = set(('admin', 'services', 'False')) > if self.value in ALLOWED: > return > raise Error('Not an allowed category: "%s"' % self.value) > > >class Section(object): > APPLICATION = { > 'ADMemberIssueHide': ('optional',), > 'ADMemberIssuePassword': ('optional',), > 'Categories': ('optional',), > 'Code': ('optional',), # required > 'ConflictedApps': ('optional',), > 'ConflictedSystemPackages': ('optional',), > 'Contact': ('require', 'is_email',), > 'DefaultPackagesMaster': ('optional',), > 'DefaultPackages': ('require',), > 'Description': ('require', 'is_60c',), > 'EmailRequired': ('optional',), > 'EndOfLife': ('optional', 'is_bool',), > 'ID': ('require',), > 'LicenseFile': ('optional',), > 'LongDescription': ('require',), > 'Maintainer': ('optional',), > 'MinPhysicalRAM': ('optional', 'is_capacity',), > 'Name': ('require',), > 'NotificationEmail': ('optional', 'is_email',), > 'NotifyVendor': ('optional', 'is_bool',), > 'RequiredApps': ('optional',), > 'Screenshot': ('optional',), > 'ServerRole': ('optional', 'is_role',), > 'ShopURL': ('optional', 'is_www',), > 'SupportedArchitectures': ('optional', 'is_arch',), > 'SupportURL': ('optional', 'is_www',), > 'UCSOverviewCategory': ('optional', 'is_category',), > 'UMCModuleFlavor': ('optional',), > 'UMCModuleName': ('optional',), > 'UserActivationRequired': ('optional', 'is_bool',), > 'UseShop': ('optional', 'is_bool',), > 'UseShop': ('optional', 'is_bool',), > 'vendor': ('optional',), > 'Version': ('require',), > 'VisibleInAppCatalogue': ('optional', 'is_bool',), > 'WebInterfaceName': ('optional',), > 'WebInterface': ('optional', 'is_url',), > 'WebsiteMaintainer': ('optional', 'is_www',), > 'Website': ('optional', 'is_www',), > 'Websitevendor': ('optional', 'is_www',), > 'WithoutRepository': ('optional', 'is_bool',), > } > SIZING = { > 'CPU': ('optional',), > 'RAM': ('optional', 'is_capacity',), > 'Disk': ('optional', 'is_capacity',), > } > TRANSLATION = { > 'Name': ('optional',) + APPLICATION['Name'], > 'Website': APPLICATION['Website'], > 'SupportURL': APPLICATION['SupportURL'], > 'ShopURL': APPLICATION['ShopURL'], > 'Description': APPLICATION['Description'], > 'LongDescription': APPLICATION['LongDescription'], > } > > def __init__(self, check, section): > self.config = check.config > self.section = section > self.log = check.log > > def __enter__(self): > return self > > def __exit__(self, exc_type, exc_value, traceback): > if not exc_type: > return > if issubclass(exc_type, ConfigParser.NoSectionError): > self.log('[%s] missing', self.section) > > def check_all(self, options): > # print >> sys.stderr, self.section, self.config.options(self.section) > for option, checks in options.iteritems(): > self.check(option, *checks) > self.config.remove_option(self.section, option) > for option, value in self.config.items(self.section): > self.log('[%s].%s: Remaining %s', self.section, option, value) > > def check(self, option, *checks): > value = self.get(option) > # print >> sys.stderr, self.section, option, value > for cname in checks: > try: > check = getattr(value, cname) > check() > except Fatal as ex: > self.log('[%s].%s: %s', self.section, option, ex) > return > except Error as ex: > self.log('[%s].%s: %s', self.section, option, ex) > except Final as ex: > return > > def get(self, option): > try: > value = self.config.get(self.section, option) > except ConfigParser.NoOptionError as ex: > # print >> sys.stderr, ex > value = None > return Value(value) > > >if __name__ == '__main__': > main()
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
Actions:
View
Attachments on
bug 36730
: 6383