move decorators into separate module

This commit is contained in:
Laszlo Nagy
2014-08-07 15:28:36 +02:00
parent 81ecf3cd73
commit 9320af35e2
4 changed files with 100 additions and 85 deletions

View File

@@ -4,14 +4,19 @@
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
import analyzer.driver
import shlex
import logging
import multiprocessing
import json
import itertools
from analyzer.decorators import trace, require
from analyzer.driver import run, get_clang_arguments, check_output, filter_dict
def run():
def main():
multiprocessing.freeze_support()
logging.basicConfig(format='%(message)s')
def cleanup_out_directory(dir_name):
import shutils
shutil.rmtree(dir_name)
@@ -28,10 +33,9 @@ def run():
import tempfile
return tempfile.mkdtemp(prefix='beye-', suffix='.out')
multiprocessing.freeze_support()
args = parse_command_line()
logging.basicConfig(format='%(message)s', level=args.log_level)
logging.getLogger().setLevel(args.log_level)
out_dir = create_out_directory(args.output)
if run_analyzer(args, out_dir) and found_bugs(out_dir):
@@ -42,6 +46,7 @@ def run():
logging.warning('no bugs were found')
@trace
def parse_command_line():
from argparse import ArgumentParser
parser = ArgumentParser()
@@ -66,24 +71,26 @@ def parse_command_line():
return parser.parse_args()
@trace
def found_bugs(out_dir):
return True
@trace
def generate_report(out_dir):
pass
@trace
def run_analyzer(args, out_dir):
def set_common_params(opts):
output = analyzer.driver.check_output
return analyzer.driver.filter_dict(
return filter_dict(
opts,
frozenset(['output', 'input', 'sequential', 'log_level']),
{'verbose': True,
{'verbose': logging.getLogger().isEnabledFor(logging.INFO),
'html_dir': out_dir,
'output_format': opts.get('output_format', 'html'),
'uname': output(['uname', '-a']).decode('ascii'),
'uname': check_output(['uname', '-a']).decode('ascii'),
'clang': 'clang'})
const = set_common_params(args.__dict__)
@@ -92,8 +99,26 @@ def run_analyzer(args, out_dir):
for c in json.load(fd):
c.update(const)
c.update(command=shlex.split(c['command']))
pool.apply_async(func=analyzer.driver.run, args=(c,))
pool.apply_async(func=run, args=(c,))
pool.close()
pool.join()
return True
@trace
def get_default_checkers(clang):
""" To get the default plugins we execute Clang to print how this
comilation would be called. For input file we specify stdin. And
pass only language information. """
def checkers(language):
pattern = re.compile('^-analyzer-checker=(.*)$')
cmd = [clang, '--analyze', '-x', language, '-']
return [pattern.match(arg).group(1)
for arg
in get_clang_arguments('.', cmd)
if pattern.match(arg)]
return set(itertools.chain.from_iterable(
[checkers(language)
for language
in ['c', 'c++', 'objective-c', 'objective-c++']]))

47
analyzer/decorators.py Normal file
View File

@@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
import logging
import functools
def trace(function):
""" Decorator to simplify debugging. """
@functools.wraps(function)
def wrapper(*args, **kwargs):
logging.debug('entering {0}'.format(function.__name__))
result = function(*args, **kwargs)
logging.debug('leaving {0}'.format(function.__name__))
return result
return wrapper
def require(required=[]):
""" Decorator for checking the required values in state.
It checks the required attributes in the passed state and stop when
any of those is missing.
"""
def decorator(function):
@functools.wraps(function)
def wrapper(opts, cont):
try:
precondition(opts)
return function(opts, cont)
except Exception as e:
logging.error(str(e))
return None
def precondition(opts):
for key in required:
if key not in opts:
raise KeyError(
'{0} not passed to {1}'.format(key, function.__name__))
return wrapper
return decorator

View File

@@ -14,23 +14,12 @@ import tempfile
import copy
import functools
import shlex
import itertools
from analyzer.decorators import trace, require
@trace
def run(opts):
""" Creates a method to run the command and the analyzer. """
chain = stack([parse,
filter_action,
arch_loop,
set_language,
set_analyzer_output,
run_analyzer,
report_failure])
return chain(opts)
def stack(conts):
def stack(conts):
""" Creates a single method from multiple continuations.
The analysis is written continuation-passing like style.
@@ -45,44 +34,15 @@ def stack(conts):
conts.reverse()
return bind(conts, lambda x: x)
chain = stack([parse,
filter_action,
arch_loop,
set_language,
set_analyzer_output,
run_analyzer,
report_failure])
def trace(function):
""" Decorator to simplify debugging. """
@functools.wraps(function)
def wrapper(*args, **kwargs):
logging.debug('entering {0}'.format(function.__name__))
result = function(*args, **kwargs)
logging.debug('leaving {0}'.format(function.__name__))
return result
return wrapper
def require(required=[]):
""" Decorator for checking the required values in state.
It checks the required attributes in the passed state and stop when
any of those is missing.
"""
def decorator(function):
@functools.wraps(function)
def wrapper(opts, cont):
try:
precondition(opts)
return function(opts, cont)
except Exception as e:
logging.error(str(e))
return None
def precondition(opts):
for key in required:
if key not in opts:
raise KeyError(
'{0} not passed to {1}'.format(key, function.__name__))
return wrapper
return decorator
return chain(opts)
def filter_dict(original, removables, additions):
@@ -118,23 +78,6 @@ def check_output(*popenargs, **kwargs):
return output
def get_default_checkers(clang):
""" To get the default plugins we execute Clang to print how this
comilation would be called. For input file we specify stdin. And
pass only language information. """
def checkers(language):
pattern = re.compile('^-analyzer-checker=(.*)$')
cmd = [clang, '--analyze', '-x', language, '-']
return [pattern.match(arg).group(1)
for arg
in get_clang_arguments('.', cmd)
if pattern.match(arg)]
return set(itertools.chain.from_iterable(
[checkers(language)
for language
in ['c', 'c++', 'objective-c', 'objective-c++']]))
class Action(object):
""" Enumeration class for compiler action. """
Link, Compile, Preprocess, Info = range(4)

View File

@@ -17,7 +17,7 @@ setup(
packages=find_packages(),
entry_points={
'console_scripts': [
'beye = analyzer.beye:run'
'beye = analyzer.beye:main'
]
},
classifiers=[