[DEV] basic version that start to work

This commit is contained in:
Edouard DUPIN 2017-08-15 23:49:49 +02:00
parent 8b1d7c6c81
commit b34ab69747
16 changed files with 180300 additions and 0 deletions

9
.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
# Compiled python modules.
*.pyc
# Setuptools distribution folder.
/dist/
/build/
# Python egg metadata, regenerated from source files by setuptools.
/*.egg-info

69
.travis.yml Normal file
View File

@ -0,0 +1,69 @@
#language: python
sudo: false
branches:
only:
- master
- dev
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.9
- expect
- binutils-mingw-w64-i686 # 32bit MinGW
- gcc-mingw-w64-i686
- g++-mingw-w64-i686
- binutils-mingw-w64-x86-64 # 64bit MinGW
- gcc-mingw-w64-x86-64
- g++-mingw-w64-x86-64
matrix:
include:
- os: linux
env: CONF=release BUILDER=gcc TARGET=Linux TAG=Linux
compiler: gcc
- os: linux
env: CONF=debug BUILDER=clang TARGET=Linux
compiler: clang
- os: linux
env: CONF=release BUILDER=gcc TARGET=Windows TAG=Mingw
compiler: gcc
- os: linux
env: CONF=release BUILDER=gcc TARGET=Android TAG=Android DISABLE_PACKAGE=-p
compiler: gcc
- os: osx
env: CONF=release BUILDER=clang TARGET=MacOs TAG=MacOs
compiler: clang
- os: osx
env: CONF=release BUILDER=clang TARGET=IOs TAG=IOs
compiler: clang
install:
- cd ..
# download NDK
- if [ "$TAG" == "Android" ]; then
git clone --depth 1 --branch master https://github.com/HeeroYui/android-download-tool;
./android-download-tool/dl-android.sh;
fi
- git clone --depth 1 --branch master https://github.com/atria-soft/ci.git
- cd -
before_script:
- ./setup.py build
- export PYTHONPATH=$PYTHONPATH:./lutin/build/lib.linux-x86_64-2.7/:./lutin/build/lib.linux-x86_64-2.7/lutin/:./lutin/build/lib:./lutin/build/lib/lutin/
- cd ..
- pwd
- ls -l *
- ./ci/build_send.py --tag=$TAG --status=START;
script:
- ./lutin/build/scripts-2.7/lutin -w -j4 -C -P -t$TARGET -c $BUILDER $COMPILATOR_OPTION $BUS -m $CONF $GCOV $DISABLE_PACKAGE test-c; STATUS=$?
- ./ci/build_send.py --tag=$TAG --status="$STATUS";
notifications:
email:
- yui.heero@gmail.com

2
MANIFEST.in Normal file
View File

@ -0,0 +1,2 @@
include README.rst
include bash-autocompletion/monk

109
README.rst Normal file
View File

@ -0,0 +1,109 @@
Prude
=====
`prude` is a generic C++ annalysing code to check language error (english).
.. image:: https://badge.fury.io/py/prude.png
:target: https://pypi.python.org/pypi/prude
Release (master)
----------------
.. image:: https://travis-ci.org/HeeroYui/prude.svg?branch=master
:target: https://travis-ci.org/HeeroYui/prude
.. image:: http://atria-soft.com/ci/build/HeeroYui/prude.svg?branch=master&tag=Linux
:target: http://atria-soft.com/ci/HeeroYui/prude
.. image:: http://atria-soft.com/ci/build/HeeroYui/prude.svg?branch=master&tag=MacOs
:target: http://atria-soft.com/ci/HeeroYui/prude
.. image:: http://atria-soft.com/ci/build/HeeroYui/prude.svg?branch=master&tag=Mingw
:target: http://atria-soft.com/ci/HeeroYui/prude
.. image:: http://atria-soft.com/ci/build/HeeroYui/prude.svg?branch=master&tag=Android
:target: http://atria-soft.com/ci/HeeroYui/prude
.. image:: http://atria-soft.com/ci/build/HeeroYui/prude.svg?branch=master&tag=IOs
:target: http://atria-soft.com/ci/HeeroYui/prude
Developement (dev)
------------------
.. image:: https://travis-ci.org/HeeroYui/prude.svg?branch=dev
:target: https://travis-ci.org/HeeroYui/prude
.. image:: http://atria-soft.com/ci/build/HeeroYui/prude.svg?branch=dev&tag=Linux
:target: http://atria-soft.com/ci/HeeroYui/prude
.. image:: http://atria-soft.com/ci/build/HeeroYui/prude.svg?branch=dev&tag=MacOs
:target: http://atria-soft.com/ci/HeeroYui/prude
.. image:: http://atria-soft.com/ci/build/HeeroYui/prude.svg?branch=dev&tag=Mingw
:target: http://atria-soft.com/ci/HeeroYui/prude
.. image:: http://atria-soft.com/ci/build/HeeroYui/prude.svg?branch=dev&tag=Android
:target: http://atria-soft.com/ci/HeeroYui/prude
.. image:: http://atria-soft.com/ci/build/HeeroYui/prude.svg?branch=dev&tag=IOs
:target: http://atria-soft.com/ci/HeeroYui/prude
Instructions
------------
This is a tool to annalyse C, C++ file and determone if it have some english word that does not exist.
Prude is under a FREE license that can be found in the COPYING file.
Any contribution is more than welcome ;)
git repository
--------------
http://github.com/HeeroYui/prude/
Documentation
-------------
http://github.io/HeeroYui/prude/
Installation
------------
Requirements: ``Python >= 2.7`` and ``pip``
Just run:
pip install prude
Install pip on debian/ubuntu:
sudo apt-get install pip
Install pip on ARCH-linux:
sudo pacman -S pip
Install pip on MacOs:
sudo easy_install pip
License (APACHE v2.0)
---------------------
Copyright prude Edouard DUPIN
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

105
bin/prude Executable file
View File

@ -0,0 +1,105 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
##
## @author Edouard DUPIN
##
## @copyright 2012, Edouard DUPIN, all right reserved
##
## @license APACHE v2.0 (see license file)
##
# for path inspection:
import sys
import os
import copy
import prude
import prude.debug as debug
import prude.arg as arguments
import prude.env as env
import prude.tools as tools
import prude.module as module
myArgs = arguments.doxyArg()
myArgs.add(arguments.ArgDefine("h", "help", desc="Display this help"))
myArgs.add(arguments.ArgDefine("H", "HELP", desc="Display this help (with all compleate information)"))
myArgs.add_section("option", "Can be set one time in all case")
myArgs.add(arguments.ArgDefine("v", "verbose", list=[["0","None"],["1","error"],["2","warning"],["3","info"],["4","debug"],["5","verbose"],["6","extreme_verbose"]], desc="display makefile debug level (verbose) default =2"))
myArgs.add(arguments.ArgDefine("C", "color", desc="Display makefile output in color"))
myArgs.add_section("cible", "generate in order set")
localArgument = myArgs.parse()
"""
display the help of this makefile
"""
def usage(full=False):
color = debug.get_color_set()
# generic argument displayed :
myArgs.display()
print(" ex: " + sys.argv[0] + " myFile1.cpp")
exit(0)
def check_boolean(value):
if value == "" \
or value == "1" \
or value == "true" \
or value == "True" \
or value == True:
return True
return False
# preparse the argument to get the verbose element for debug mode
def parseGenericArg(argument, active):
debug.extreme_verbose("parse arg : " + argument.get_option_name() + " " + argument.get_arg() + " active=" + str(active))
if argument.get_option_name() == "help":
if active==False:
usage()
return True
if argument.get_option_name() == "HELP":
if active==False:
usage(True)
return True
elif argument.get_option_name() == "verbose":
if active==True:
debug.set_level(int(argument.get_arg()))
return True
elif argument.get_option_name() == "color":
if active==True:
if check_boolean(argument.get_arg()) == True:
debug.enable_color()
else:
debug.disable_color()
return True
return False
# parse default unique argument:
for argument in localArgument:
parseGenericArg(argument, True)
# initialize the system ...
prude.init()
actionDone = False;
# parse all argument
number_of_error = 0
for argument in localArgument:
if parseGenericArg(argument, False) == True:
continue
else:
argument_value = argument.get_arg()
debug.debug("something request : '" + argument_value + "'")
if argument.get_option_name() != "":
debug.warning("Can not understand argument : '" + argument.get_option_name() + "'")
usage()
break;
number_of_error += module.annalyse(argument_value)
actionDone = True
# if no action done : we do "all" ...
if actionDone == False:
usage()
exit(-1)
if number_of_error != 0:
exit(-1);

26
prude/__init__.py Executable file
View File

@ -0,0 +1,26 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
##
## @author Edouard DUPIN
##
## @copyright 2012, Edouard DUPIN, all right reserved
##
## @license APACHE v2.0 (see license file)
##
import os
import sys
import fnmatch
# Local import
from . import target
from . import tools
from . import debug
from . import module
from . import env
is_init = False
def init():
global is_init;
if is_init == True:
return

262
prude/arg.py Normal file
View File

@ -0,0 +1,262 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
##
## @author Edouard DUPIN
##
## @copyright 2012, Edouard DUPIN, all right reserved
##
## @license APACHE v2.0 (see license file)
##
import sys
# Local import
from . import debug
class ArgElement:
def __init__(self, option, value=""):
self.option = option;
self.arg = value;
def get_option_name(self):
return self.option
def get_arg(self):
return self.arg
def display(self):
if len(self.arg)==0:
debug.info("option : " + self.option)
elif len(self.option)==0:
debug.info("element : " + self.arg)
else:
debug.info("option : " + self.option + ":" + self.arg)
class ArgDefine:
def __init__(self,
smallOption="", # like v for -v
bigOption="", # like verbose for --verbose
list=[], # ["val", "description"]
desc="",
haveParam=False):
self.option_small = smallOption;
self.option_big = bigOption;
self.list = list;
if len(self.list)!=0:
self.have_param = True
else:
if True==haveParam:
self.have_param = True
else:
self.have_param = False
self.description = desc;
def get_option_small(self):
return self.option_small
def get_option_big(self):
return self.option_big
def need_parameters(self):
return self.have_param
def get_porperties(self):
return ""
def check_availlable(self, argument):
if len(self.list)==0:
return True
for element,desc in self.list:
if element == argument:
return True
return False
def display(self):
color = debug.get_color_set()
if self.option_small != "" and self.option_big != "":
print(" " + color['red'] + "-" + self.option_small + "" + color['default'] + " / " + color['red'] + "--" + self.option_big + color['default'])
elif self.option_small != "":
print(" " + color['red'] + "-" + self.option_small + color['default'])
elif self.option_big != "":
print(" " + color['red'] + "--" + self.option_big + color['default'])
else:
print(" ???? ==> internal error ...")
if self.description != "":
print(" " + self.description)
if len(self.list)!=0:
hasDescriptiveElement=False
for val,desc in self.list:
if desc!="":
hasDescriptiveElement=True
break;
if hasDescriptiveElement==True:
for val,desc in self.list:
print(" " + val + " : " + desc)
else:
tmpElementPrint = ""
for val,desc in self.list:
if len(tmpElementPrint)!=0:
tmpElementPrint += " / "
tmpElementPrint += val
print(" { " + tmpElementPrint + " }")
def parse(self, argList, currentID):
return currentID;
class ArgSection:
def __init__(self,
sectionName="",
desc=""):
self.section = sectionName;
self.description = desc;
def get_option_small(self):
return ""
def get_option_big(self):
return ""
def get_porperties(self):
color = debug.get_color_set()
return " [" + color['blue'] + self.section + color['default'] + "]"
def display(self):
color = debug.get_color_set()
print(" [" + color['blue'] + self.section + color['default'] + "] : " + self.description)
def parse(self, argList, currentID):
return currentID;
class doxyArg:
def __init__(self):
self.listProperties = []
def add(self, argument):
self.listProperties.append(argument) #ArgDefine(smallOption, bigOption, haveParameter, parameterList, description));
def add_section(self, sectionName, sectionDesc):
self.listProperties.append(ArgSection(sectionName, sectionDesc))
def parse(self):
listArgument = [] # composed of list element
NotparseNextElement=False
for iii in range(1, len(sys.argv)):
# special case of parameter in some elements
if NotparseNextElement==True:
NotparseNextElement = False
continue
debug.verbose("parse [" + str(iii) + "]=" + sys.argv[iii])
argument = sys.argv[iii]
optionList = argument.split("=")
debug.verbose(str(optionList))
if type(optionList) == type(str()):
option = optionList
else:
option = optionList[0]
optionParam = argument[len(option)+1:]
debug.verbose(option)
argumentFound=False;
if option[:2]=="--":
# big argument
for prop in self.listProperties:
if prop.get_option_big()=="":
continue
if prop.get_option_big() == option[2:]:
# find it
debug.verbose("find argument 2 : " + option[2:])
if prop.need_parameters()==True:
internalSub = option[2+len(prop.get_option_big()):]
if len(internalSub)!=0:
if len(optionParam)!=0:
# wrong argument ...
debug.warning("maybe wrong argument for : '" + prop.get_option_big() + "' cmdLine='" + argument + "'")
prop.display()
continue
optionParam = internalSub
if len(optionParam)==0:
#Get the next parameters
if len(sys.argv) > iii+1:
optionParam = sys.argv[iii+1]
NotparseNextElement=True
else :
# missing arguments
debug.warning("parsing argument error : '" + prop.get_option_big() + "' Missing : subParameters ... cmdLine='" + argument + "'")
prop.display()
exit(-1)
if prop.check_availlable(optionParam)==False:
debug.warning("argument error : '" + prop.get_option_big() + "' SubParameters not availlable ... cmdLine='" + argument + "' option='" + optionParam + "'")
prop.display()
exit(-1)
listArgument.append(ArgElement(prop.get_option_big(),optionParam))
argumentFound = True
else:
if len(optionParam)!=0:
debug.warning("parsing argument error : '" + prop.get_option_big() + "' need no subParameters : '" + optionParam + "' cmdLine='" + argument + "'")
prop.display()
listArgument.append(ArgElement(prop.get_option_big()))
argumentFound = True
break;
if False==argumentFound:
debug.error("UNKNOW argument : '" + argument + "'")
elif option[:1]=="-":
# small argument
for prop in self.listProperties:
if prop.get_option_small()=="":
continue
if prop.get_option_small() == option[1:1+len(prop.get_option_small())]:
# find it
debug.verbose("find argument 1 : " + option[1:1+len(prop.get_option_small())])
if prop.need_parameters()==True:
internalSub = option[1+len(prop.get_option_small()):]
if len(internalSub)!=0:
if len(optionParam)!=0:
# wrong argument ...
debug.warning("maybe wrong argument for : '" + prop.get_option_big() + "' cmdLine='" + argument + "'")
prop.display()
continue
optionParam = internalSub
if len(optionParam)==0:
#Get the next parameters
if len(sys.argv) > iii+1:
optionParam = sys.argv[iii+1]
NotparseNextElement=True
else :
# missing arguments
debug.warning("parsing argument error : '" + prop.get_option_big() + "' Missing : subParameters cmdLine='" + argument + "'")
prop.display()
exit(-1)
if prop.check_availlable(optionParam)==False:
debug.warning("argument error : '" + prop.get_option_big() + "' SubParameters not availlable ... cmdLine='" + argument + "' option='" + optionParam + "'")
prop.display()
exit(-1)
listArgument.append(ArgElement(prop.get_option_big(),optionParam))
argumentFound = True
else:
if len(optionParam)!=0:
debug.warning("parsing argument error : '" + prop.get_option_big() + "' need no subParameters : '" + optionParam + "' cmdLine='" + argument + "'")
prop.display()
listArgument.append(ArgElement(prop.get_option_big()))
argumentFound = True
break;
if argumentFound==False:
#unknow element ... ==> just add in the list ...
debug.verbose("unknow argument : " + argument)
listArgument.append(ArgElement("", argument))
#for argument in listArgument:
# argument.display()
#exit(0)
return listArgument;
def display(self):
print("usage:")
listOfPropertiesArg = "";
for element in self.listProperties :
listOfPropertiesArg += element.get_porperties()
print(" " + sys.argv[0] + listOfPropertiesArg + " ...")
for element in self.listProperties :
element.display()

181
prude/debug.py Normal file
View File

@ -0,0 +1,181 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
##
## @author Edouard DUPIN
##
## @copyright 2012, Edouard DUPIN, all right reserved
##
## @license APACHE v2.0 (see license file)
##
import os
import threading
import re
debug_level=3
debug_color=False
color_default= ""
color_red = ""
color_green = ""
color_yellow = ""
color_blue = ""
color_purple = ""
color_cyan = ""
debug_lock = threading.Lock()
def set_level(id):
global debug_level
debug_level = id
#print "SetDebug level at " + str(debug_level)
def get_level():
global debug_level
return debug_level
def enable_color():
global debug_color
debug_color = True
global color_default
color_default= "\033[00m"
global color_red
color_red = "\033[31m"
global color_green
color_green = "\033[32m"
global color_yellow
color_yellow = "\033[33m"
global color_blue
color_blue = "\033[01;34m"
global color_purple
color_purple = "\033[35m"
global color_cyan
color_cyan = "\033[36m"
def disable_color():
global debug_color
debug_color = True
global color_default
color_default= ""
global color_red
color_red = ""
global color_green
color_green = ""
global color_yellow
color_yellow = ""
global color_blue
color_blue = ""
global color_purple
color_purple = ""
global color_cyan
color_cyan = ""
def extreme_verbose(input, force=False):
global debug_lock
global debug_level
if debug_level >= 6 \
or force == True:
debug_lock.acquire()
print(color_blue + input + color_default)
debug_lock.release()
def verbose(input, force=False):
global debug_lock
global debug_level
if debug_level >= 5 \
or force == True:
debug_lock.acquire()
print(color_blue + input + color_default)
debug_lock.release()
def debug(input, force=False):
global debug_lock
global debug_level
if debug_level >= 4 \
or force == True:
debug_lock.acquire()
print(color_green + input + color_default)
debug_lock.release()
def info(input, force=False):
global debug_lock
global debug_level
if debug_level >= 3 \
or force == True:
debug_lock.acquire()
print(input + color_default)
debug_lock.release()
def warning(input, force=False):
global debug_lock
global debug_level
if debug_level >= 2 \
or force == True:
debug_lock.acquire()
print(color_purple + "[WARNING] " + input + color_default)
debug_lock.release()
def todo(input, force=False):
global debug_lock
global debug_level
if debug_level >= 3 \
or force == True:
debug_lock.acquire()
print(color_purple + "[TODO] " + input + color_default)
debug_lock.release()
def error(input, force=False, crash=True):
global debug_lock
global debug_level
if debug_level >= 1 \
or force == True:
debug_lock.acquire()
print(color_red + "[ERROR] " + input + color_default)
debug_lock.release()
if crash == True:
exit(-1)
def print_element(type, lib, dir, name, force=False):
global debug_lock
global debug_level
if debug_level >= 3 \
or force == True:
debug_lock.acquire()
print(color_cyan + type + color_default + " : " + color_yellow + lib + color_default + " " + dir + " " + color_blue + name + color_default)
debug_lock.release()
def print_compilator(myString):
global debug_color
global debug_lock
if debug_color == True:
myString = myString.replace('\\n', '\n')
myString = myString.replace('\\t', '\t')
myString = myString.replace('error:', color_red+'error:'+color_default)
myString = myString.replace('warning:', color_purple+'warning:'+color_default)
myString = myString.replace('note:', color_green+'note:'+color_default)
myString = re.sub(r'([/\w_-]+\.\w+):', r'-COLORIN-\1-COLOROUT-:', myString)
myString = myString.replace('-COLORIN-', color_yellow)
myString = myString.replace('-COLOROUT-', color_default)
debug_lock.acquire()
print(myString)
debug_lock.release()
def get_color_set() :
global color_default
global color_red
global color_green
global color_yellow
global color_blue
global color_purple
global color_cyan
return {
"default": color_default,
"red": color_red,
"green": color_green,
"yellow": color_yellow,
"blue": color_blue,
"purple": color_purple,
"cyan": color_cyan,
}

178713
prude/english.py Normal file

File diff suppressed because it is too large Load Diff

127
prude/env.py Normal file
View File

@ -0,0 +1,127 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
##
## @author Edouard DUPIN
##
## @copyright 2012, Edouard DUPIN, all right reserved
##
## @license APACHE v2.0 (see license file)
##
# Local import
from . import debug
import os
force_mode=False
def set_force_mode(val):
global force_mode
if val==1:
force_mode = 1
else:
force_mode = 0
def get_force_mode():
global force_mode
return force_mode
system_base_name = "prude"
def set_system_base_name(val):
global system_base_name
system_base_name = val
debug.debug("Set basename: '" + str(system_base_name) + "'")
def get_system_base_name():
global system_base_name
return system_base_name
prude_root_path = os.path.join(os.getcwd())
if os.path.exists(os.path.join(prude_root_path, "." + get_system_base_name())) == True:
# all is good ...
pass
elif os.path.exists(os.path.join(prude_root_path, "..", "." + get_system_base_name())) == True:
prude_root_path = os.path.join(os.getcwd(), "..")
elif os.path.exists(os.path.join(prude_root_path, "..", "..", "." + get_system_base_name())) == True:
prude_root_path = os.path.join(os.getcwd(), "..", "..")
elif os.path.exists(os.path.join(prude_root_path, "..", "..", "..", "." + get_system_base_name())) == True:
prude_root_path = os.path.join(os.getcwd(), "..", "..", "..")
elif os.path.exists(os.path.join(prude_root_path, "..", "..", "..", "..", "." + get_system_base_name())) == True:
prude_root_path = os.path.join(os.getcwd(), "..", "..", "..", "..")
elif os.path.exists(os.path.join(prude_root_path, "..", "..", "..", "..", "..", "." + get_system_base_name())) == True:
prude_root_path = os.path.join(os.getcwd(), "..", "..", "..", "..", "..")
elif os.path.exists(os.path.join(prude_root_path, "..", "..", "..", "..", "..", "..", "." + get_system_base_name())) == True:
prude_root_path = os.path.join(os.getcwd(), "..", "..", "..", "..", "..", "..")
else:
#debug.error("the root path of " + get_system_base_name() + " must not be upper that 6 parent path")
pass
prude_path = os.path.join(prude_root_path, "." + get_system_base_name())
def get_local_config_file():
return prude_path
def file_read_data(path):
if not os.path.isfile(path):
return ""
file = open(path, "r")
data_file = file.read()
file.close()
return data_file
def get_local_filter():
global capital_letter_check
capital_letter_check = True
if os.path.exists(prude_root_path) == False:
return []
# parse the global .prude file
filter_list = [{"check-capital":True}, [], []]
if os.path.exists(get_local_config_file()) == True:
data = file_read_data(get_local_config_file())
for elem in data.split("\n"):
if elem == "":
continue
if elem[0] == "#":
continue
if elem[0] == "!":
# specific control check
if elem == "!NO_CAPITAL_LETTER":
filter_list[0]["check-capital"] = False
else:
debug.error("unknows parameter: '" + elem + "'")
continue
if elem[0] == "+":
# check the full name:
filter_list[1].append(elem[1:])
else:
filter_list[2].append(elem)
list_files = os.listdir(prude_root_path)
for ff_file in list_files:
if len(ff_file) <= 7 \
or ff_file[:7] != ".prude_":
continue
debug.debug("Load config file:" + os.path.join(prude_root_path,ff_file))
data = file_read_data(os.path.join(prude_root_path,ff_file))
for elem in data.split("\n"):
if elem == "":
continue
if elem[0] == "#":
continue
if elem[0] == "!":
# specific control check
if elem == "!NO_CAPITAL_LETTER":
filter_list[0]["check-capital"] = False
else:
debug.error("unknows parameter: '" + elem + "'")
continue
if elem[0] == "+":
# check the full name:
filter_list[1].append(elem[1:])
else:
filter_list[2].append(elem)
debug.verbose("fulllist:" + str(filter_list))
return filter_list

281
prude/module.py Normal file
View File

@ -0,0 +1,281 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
##
## @author Edouard DUPIN
##
## @copyright 2012, Edouard DUPIN, all right reserved
##
## @license APACHE v2.0 (see license file)
##
import sys
import os
import copy
import inspect
import fnmatch
import re
import difflib
# Local import
from . import tools
from . import debug
from . import env
from . import english
generic_cpp_type = [
"void",
"float",
"char",
"char32_t",
"int",
"int8_t",
"int16_t",
"int32_t",
"int64_t",
"int128_t",
"uint8_t",
"uint16_t",
"uint32_t",
"uint64_t",
"uint128_t",
"const",
"bool",
"enum",
"class",
"namespace",
"pragma",
"struct",
"NULL",
"nullptr",
"sizeof",
# generic names:
"openGL",
"boolean",
"TODO",
"todo",
"vec2",
"vec3",
"ivec2",
"ivec3",
"uvec2",
"uvec3",
"bvec2",
"bvec3",
"Edouard",
"DUPIN"
]
tolerate_words = [
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
"min", "max", "fifo", "filo", "ascii",
# generic variables:
"iii", "jjj", "kkk", "xxx", "yyy", "zzz",
"tmp", "it", "val", "pos", "nb",
# classicle programation achronimes:
"pc", "cpu", "gpio", "io", "proc", "ctrl", "rx", "tx", "msg", "async", "sync", "ack", "src", "freq",
"ui", "params", "ip", "log", "udp", "tcp", "ftp",
"unicode", "utf", "xml", "json", "bmp", "jpg", "jpeg", "tga", "gif", "http", "https",
"sys", "arg", "args", "argc", "argv", "init", "main", "fnmatch", "env", "len", "desc", "str",
"cmd", "dir", "bsy", "id",
#classical libraries
"lua",
#dxygen element
"param",
#language word:
"ifdef", "ifndef","endif", "elif",
# licences:
"mpl", "bsd", "lgpl", "gpl",
# units:
"hz", "khz", "mhz", "thz",
"ms", "us", "ns", "min", "sec",
# some hewxa values:
"xf", "xff", "xfff", "xffff", "xfffff", "xffffff",
"xffffffffull",
"ll",
"xll",
#libc funtions
"memcpy", "strncpy", "printf", "sprintf", "fopen", "malloc", "calloc", "kalloc",
"noinline", "ramtext", "constexpr", "typename", "inline", "memet",
]
application_filter = None
def annalyse(filename):
global application_filter
debug.info("Annalyse: '" + filename + "'")
data = tools.file_read_data(filename)
if application_filter == None:
application_filter = env.get_local_filter()
line_id = 0
number_of_error = 0
# Annalyse in separate files:
for line in data.split("\n"):
# replace all \t with a " "
line = re.sub(r'\t',
r' ',
line,
flags=re.DOTALL)
# remove the hexa string ==> not able to parse it for now ...
line = re.sub(r'0(x|X)[0-9a-fA-F]+(ull|ll)?', '', line)
line_id += 1
if len(line) == 0:
continue;
debug.verbose(filename + ":" + str(line_id) + " " + line)
# List of all word:
word_list = []
current_word = ""
position_in_line = 0
start_word_pos = None
if len(line) >= 8 \
and line[:8] == "#include":
# remove include handle ==> this is for later ...
continue
if len(line) >= 9 \
and line[:9] == "# include":
# remove include handle ==> this is for later ...
continue
if len(line) >= 2 \
and line[:2] == "#!":
# remove include handle ==> this is for later ...
continue
for elem in line:
position_in_line += 1
if elem in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_:":
current_word += elem
if start_word_pos == None:
start_word_pos = position_in_line
# this is to get the last word of the line
if position_in_line != len(line):
continue
if current_word != "":
# check if not a current Type:
if current_word in generic_cpp_type:
word_list.append({
"line":line,
"line-id":line_id,
"pos":start_word_pos,
"word":current_word,
"word-list":[[0,current_word]],
"generic-type":True,
"in-namespace":False
})
else:
# separate with camelCase and snake case:
under_word_list = []
current_sub_word = ""
offset_in_word_count = 0
offset_in_word = None
in_namespace = False
if len(current_word.split("::")) >= 2:
in_namespace = True
for elem_word in current_word:
offset_in_word_count += 1
if elem_word in "abcdefghijklmnopqrstuvwxyz:":
current_sub_word += elem_word
if offset_in_word == None:
offset_in_word = offset_in_word_count - 1;
elif elem_word in "0123456789":
pass
else:
if current_sub_word != "":
if elem_word in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
and current_sub_word[-1] in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
pass
else:
while len(current_sub_word) > 0 \
and current_sub_word[-1] == ":":
current_sub_word = current_sub_word[:-1]
if current_sub_word != "":
under_word_list.append([offset_in_word,current_sub_word])
current_sub_word = ""
offset_in_word = None
if elem_word != "_":
if offset_in_word == None:
offset_in_word = offset_in_word_count - 1;
current_sub_word += elem_word
if current_sub_word != "":
while len(current_sub_word) > 0 \
and current_sub_word[-1] == ":":
current_sub_word = current_sub_word[:-1]
if current_sub_word != "":
under_word_list.append([offset_in_word,current_sub_word])
# add at minimal 1 word...
if len(under_word_list) == 0:
offset_in_word == 0
under_word_list.append([offset_in_word,current_sub_word])
word_list.append({
"line":line,
"line-id":line_id,
"pos":start_word_pos,
"word":current_word,
"word-list":under_word_list,
"generic-type":False,
"in-namespace":in_namespace
})
current_word = ""
start_word_pos = None
for elem in word_list:
debug.extreme_verbose(" " + str(elem["pos"]) + ":" + elem["word"])
if len(elem["word-list"]) > 1:
for elem_sub in elem["word-list"]:
debug.extreme_verbose(" " + str(elem_sub))
debug.extreme_verbose(" " + str(elem["pos"]) + "+" + str(elem_sub[0]) + ": " + elem_sub[1])
# check the files:
for elem in word_list:
if elem["generic-type"] == True:
# nothing to parse ==> language basis...
continue
if elem["in-namespace"] == True:
# nothing to parse ==> parse at the definition...
continue
if elem["word"] in application_filter[1]:
# nothing to parse ==> parse at the definition...
debug.extreme_verbose("reject global names " + elem["word"]);
continue
for elem_sub in elem["word-list"]:
if application_filter[0]["check-capital"]:
capital = True
for elemmm in elem_sub[1]:
if elemmm in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
pass
else:
capital = False
break
if capital == True:
continue
tmp_elem = elem_sub[1].lower()
if len(tmp_elem) == 0 \
or tmp_elem == ":" \
or tmp_elem == "::":
continue
if tmp_elem[-1] == ":":
if len(tmp_elem) >= 2 \
and tmp_elem[-2] == ":":
# this is a classicle namespace of C++ ==> just drop it, it might create an error in the namespace declaration
continue
if tmp_elem in tolerate_words:
continue
if tmp_elem in application_filter[2]:
continue
if tmp_elem not in english.list_english_word:
number_of_error += 1
debug.print_compilator(filename + ":" + str(elem["line-id"]) + ":error: unknown word: '" + tmp_elem + "'")
debug.print_compilator(" '" + str(elem["line"]) + "'")
debug.print_compilator(" " + " "*(elem["pos"]+elem_sub[0]) + "^")
list_of_words = difflib.get_close_matches(tmp_elem, english.list_english_word)
if len(list_of_words) != 0:
debug.print_compilator(" try: " + str(list_of_words))
if number_of_error != 0:
debug.warning(filename + " " + str(number_of_error) + " error(s)")
return number_of_error

66
prude/multiprocess.py Normal file
View File

@ -0,0 +1,66 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
##
## @author Edouard DUPIN
##
## @copyright 2012, Edouard DUPIN, all right reserved
##
## @license APACHE v2.0 (see license file)
##
import sys
import threading
import time
import sys
import os
import subprocess
import shlex
# Local import
from . import debug
from . import tools
from . import env
def run_command(cmd_line, store_cmd_line="", store_output_file=""):
global error_occured
global exit_flag
global current_id_execution
global error_execution
# prepare command line:
args = shlex.split(cmd_line)
debug.verbose("cmd = " + str(args))
try:
# create the subprocess
p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except subprocess.CalledProcessError as e:
debug.error("subprocess.CalledProcessError : TODO ...")
except:
debug.error("Exception on : " + str(args))
# launch the subprocess:
output, err = p.communicate()
if sys.version_info >= (3, 0):
output = output.decode("utf-8")
err = err.decode("utf-8")
# store error if needed:
tools.store_warning(store_output_file, output, err)
# Check error :
if p.returncode == 0:
debug.debug(env.print_pretty(cmd_line))
if output != "":
debug.print_compilator(output)
if err != "":
debug.print_compilator(err)
else:
# if No ID : Not in a multiprocess mode ==> just stop here
debug.debug(env.print_pretty(cmd_line), force=True)
debug.print_compilator(output)
debug.print_compilator(err)
if p.returncode == 2:
debug.error("can not compile file ... [keyboard interrrupt]")
else:
debug.error("can not compile file ... ret : " + str(p.returncode))
debug.verbose("done 3")
# write cmd line only after to prevent errors ...
tools.store_command(cmd_line, store_cmd_line)

0
prude/target.py Normal file
View File

305
prude/tools.py Normal file
View File

@ -0,0 +1,305 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
##
## @author Edouard DUPIN
##
## @copyright 2012, Edouard DUPIN, all right reserved
##
## @license APACHE v2.0 (see license file)
##
import os
import shutil
import errno
import fnmatch
import stat
# Local import
from . import debug
from . import env
def get_run_path():
return os.getcwd()
def get_current_path(file):
return os.path.dirname(os.path.realpath(file))
def create_directory_of_file(file):
path = os.path.dirname(file)
try:
os.stat(path)
except:
os.makedirs(path)
def get_list_sub_path(path):
# TODO : os.listdir(path)
for dirname, dirnames, filenames in os.walk(path):
return dirnames
return []
def remove_path_and_sub_path(path):
if os.path.isdir(path):
debug.verbose("remove path : '" + path + "'")
shutil.rmtree(path)
def remove_file(path):
if os.path.isfile(path):
os.remove(path)
elif os.path.islink(path):
os.remove(path)
def file_size(path):
if not os.path.isfile(path):
return 0
statinfo = os.stat(path)
return statinfo.st_size
def file_read_data(path, binary=False):
if not os.path.isfile(path):
return ""
if binary == True:
file = open(path, "rb")
else:
file = open(path, "r")
data_file = file.read()
file.close()
return data_file
def version_to_string(version):
version_ID = ""
for id in version:
if len(version_ID) != 0:
if type(id) == str:
version_ID += "-"
else:
version_ID += "."
version_ID += str(id)
return version_ID
##
## @brief Write data in a specific path.
## @param[in] path Path of the data might be written.
## @param[in] data Data To write in the file.
## @param[in] only_if_new (default: False) Write data only if data is different.
## @return True Something has been copied
## @return False Nothing has been copied
##
def file_write_data(path, data, only_if_new=False):
if only_if_new == True:
old_data = file_read_data(path)
if old_data == data:
return False
#real write of data:
create_directory_of_file(path)
file = open(path, "w")
file.write(data)
file.close()
return True
def list_to_str(list):
if type(list) == type(str()):
return list + " "
else:
result = ""
# mulyiple imput in the list ...
for elem in list:
result += list_to_str(elem)
return result
def add_prefix(prefix,list):
if type(list) == type(None):
return ""
if type(list) == type(str()):
return prefix+list
else:
if len(list)==0:
return ''
else:
result=[]
for elem in list:
result.append(prefix+elem)
return result
##
## @brief Clean a path from all un-needed element in a directory
## @param[in] path Path to clean
## @param[in] normal_list List of all files/path in the path
## @return True Something has been removed
## @return False Nothing has been removed
##
def clean_directory(path, normal_list):
has_file_removed = False
# get a list of all element in the path:
for root, dirnames, filenames in os.walk(path):
for file in filenames:
file_name = os.path.join(root, file)
if file_name not in normal_list:
debug.print_element("remove file ", os.path.relpath(file_name), "==>", "---")
os.remove(file_name)
has_file_removed = True
return has_file_removed
def filter_extention(list_files, extentions, invert=False):
out = []
for file in list_files:
in_list = False
for ext in extentions:
if file[-len(ext):] == ext:
in_list = True
if in_list == True \
and invert == False:
out.append(file)
elif in_list == False \
and invert == True:
out.append(file)
return out
def move_if_needed(src, dst):
if not os.path.isfile(src):
debug.error("request move if needed, but file does not exist: '" + str(src) + "' to '" + str(dst) + "'")
return
src_data = file_read_data(src)
if os.path.isfile(dst):
# file exist ==> must check ...
dst_data = file_read_data(dst)
if src_data == dst_data:
# nothing to do ...
return
file_write_data(dst, src_data)
remove_file(src)
def store_command(cmd_line, file):
# write cmd line only after to prevent errors ...
if file == "" \
or file == None:
return;
debug.verbose("create cmd file: " + file)
# Create directory:
create_directory_of_file(file)
# Store the command Line:
file2 = open(file, "w")
file2.write(cmd_line)
file2.flush()
file2.close()
def store_warning(file, output, err):
# write warning line only after to prevent errors ...
if file == "" \
or file == None:
return;
if env.get_warning_mode() == False:
debug.verbose("remove warning file: " + file)
# remove file if exist...
remove_file(file);
return;
debug.verbose("create warning file: " + file)
# Create directory:
create_directory_of_file(file)
# Store the command Line:
file2 = open(file, "w")
file2.write("===== output =====\n")
file2.write(output)
file2.write("\n\n")
file2.write("===== error =====\n")
file2.write(err)
file2.write("\n\n")
file2.flush()
file2.close()
## List tools:
def list_append_and_check(listout, newElement, order):
for element in listout:
if element==newElement:
return
listout.append(newElement)
if order == True:
if type(newElement) is not dict:
listout.sort()
def list_append_to(out_list, in_list, order=False):
if type(in_list) == str:
list_append_and_check(out_list, in_list, order)
elif type(in_list) == list:
# mulyiple imput in the list ...
for elem in in_list:
list_append_and_check(out_list, elem, order)
elif type(in_list) == dict:
list_append_and_check(out_list, in_list, order)
else:
debug.warning("can not add in list other than {list/dict/str} : " + str(type(in_list)))
def list_append_to_2(listout, module, list, order=False):
# sepcial cse of bool
if type(list) == bool:
listout[module] = list
return
# add list in the Map
if module not in listout:
listout[module] = []
# add elements...
list_append_to(listout[module], list, order)
##
## @brief The vertion number can be set in an external file to permit to have a singe position to change when create a vew version
## @param[in] path_module (string) Path of the module position
## @param[in] filename_or_version (string or list) Path of the version or the real version lint parameter
## @return (list) List of version number
##
def get_version_from_file_or_direct(path_module, filename_or_version):
# check case of iser set the version directly
if type(filename_or_version) == list:
return filename_or_version
# this use a version file
file_data = file_read_data(os.path.join(path_module, filename_or_version))
if len(file_data) == 0:
debug.warning("not enought data in the file version size=0 " + path_module + " / " + filename_or_version)
return [0,0,0]
lines = file_data.split("\n")
if len(lines) != 1:
debug.warning("More thatn one line in the file version ==> bas case use mode: 'XX', XX.YYY', 'XX.Y.ZZZ' or 'XX.Y-dev' : " + path_module + " / " + filename_or_version)
return [0,0,0]
line = lines[0]
debug.debug("Parse line: '" + line + "'")
#check if we have "-dev"
dev_mode = False
if line[-4:] == "-dev":
dev_mode = True
line = line[:-4]
out = []
list_elem = line.split('.')
for elem in list_elem:
out.append(int(elem))
if dev_mode == True:
out.append("dev")
debug.debug(" ==> " + str(out))
return out
##
## @brief Get the list of the authors frim an input list or a file
## @param[in] path_module (string) Path of the module position
## @param[in] filename_or_version (string or list) Path of the author file or the real list of authors
## @return (list) List of authors
##
def get_maintainer_from_file_or_direct(path_module, filename_or_author):
# check case of iser set the version directly
if type(filename_or_author) == list:
return filename_or_author
# this use a version file
file_data = file_read_data(os.path.join(path_module, filename_or_author))
if len(file_data) == 0:
debug.warning("not enought data in the file author size=0 " + path_module + " / " + filename_or_author)
return []
# One user by line and # for comment line
out = []
for elem in file_data.split('\n'):
if len(elem) == 0:
continue
if elem[0] == "#":
# comment ...
continue
out.append(elem)
return out

0
setup.cfg Normal file
View File

45
setup.py Executable file
View File

@ -0,0 +1,45 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
##
## @author Edouard DUPIN
##
## @copyright 2012, Edouard DUPIN, all right reserved
##
## @license APACHE v2.0 (see license file)
##
from setuptools import setup
def readme():
with open('README.rst') as f:
return f.read()
# https://pypi.python.org/pypi?%3Aaction=list_classifiers
setup(name='prude',
version='0.2.0',
description='Prude is a simple parser thacj check word error (CamelCase and snake_case)',
long_description=readme(),
url='http://github.com/HeeroYui/prude',
author='Edouard DUPIN',
author_email='yui.heero@gmail.com',
license='APACHE-2',
packages=['prude'],
classifiers=[
'Development Status :: 4 - Beta',
'License :: OSI Approved :: Apache Software License',
'Programming Language :: Python',
'Topic :: Software Development :: Compilers',
],
keywords='documentation over doxygen',
scripts=['bin/prude'],
# Does not work on MacOs
#data_file=[
# ('/etc/bash_completion.d', ['bash-autocompletion/lutin']),
#],
include_package_data = True,
zip_safe=False)
#To developp: sudo ./setup.py install
# sudo ./setup.py develop
#TO register all in pip: ./setup.py register sdist upload