Commit e4d63067 authored by Christoph Jüngling's avatar Christoph Jüngling

Merge branch 'master' into 'master'

Master

See merge request !2
parents 8fc2eaac 1948279a
Pipeline #74523723 failed with stage
READ src\casey.py USING 'version': '([0-9.]*)'
READ src\casey.py USING __version__ *= *'([0-9.]*)'
WRITE build.cmd USING .*"([0-9.]*)".*
WRITE setup\setup-w7.iss USING #define MyAppVersion "([0-9.]*)"
WRITE setup\setup-xp.iss USING #define MyAppVersion "([0-9.]*)"
......
# Requirements for this project
#
# This file specifies the list of requirements
# used for to run and contribute.
#
# Usage:
# pip install -r requirements.txt
# pip install -r requirements.txt --proxy localhost:3128
#
ArgumentParser
emit
pprint
......
......@@ -3,9 +3,9 @@ Created on 26.03.2016
@author: chris
'''
from pprint import pformat
import codecs
import logging
from pprint import pformat
import re
from tqdm import tqdm
......@@ -17,16 +17,13 @@ def patch_all_files(files, declarations, output_folder, no_action):
'''
Patch all files with the correct case
:param files: Files to be patched
:type files: List
:param declarations: Any declared element (variable, function, ...)
:type declarations: List
:param no_action: If True, no real action (i.e. file change) is taken, just some statistics are printed
:type files: Boolean
:param list files: Files to be patched
:param list declarations: Any declared element (variable, function, ...)
:param bool no_action: If True, no real action (i.e. file change) is taken, just some statistics are printed
'''
logger = logging.getLogger('patch_all_files')
for filename in tqdm(files):
for filename in tqdm(files, desc='Patch files'):
with codecs.open(filename, 'r', encoding=get_codec()) as file:
content = file.read()
new_content = patch_content(content, declarations)
......@@ -48,9 +45,7 @@ def patch_content(content, declarations):
Change content according to the declarations
:param content: Old content
:type content: String
:param declarations: Declarations (from code)
:type declarations: List
:param list declarations: Declarations (from code)
:return: New content
:rtype: String
'''
......@@ -58,7 +53,7 @@ def patch_content(content, declarations):
new_content = []
count = 0
for line in content.split('\n'):
for line in tqdm(content.split('\n'), desc='Line'):
parts = split_line_into_parts(line)
newline = replace_parts_of_line(declarations, parts)
new_content.append(newline)
......@@ -76,35 +71,25 @@ def split_line_into_parts(line):
'''
Split the line into parts, regarding on the string and comment delimiters
:param line: Current line of code to be checked/changed
:param str line: Current line of code to be checked/changed
:return: Parts alternating code - no code - code - no code ...
:rtype: List
'''
logger = logging.getLogger('split_line_into_parts')
logger.debug('Replacing line {}'.format(line))
bunny = False
ape = False
oldcode = True
oldposition = 0
line_parts = []
for position in range(len(line)):
if line[position] == '"':
if not ape:
bunny = not bunny
elif line[position] == "'":
if not bunny:
ape = not ape
code = not bunny and not ape
if (code and not oldcode) or (oldcode and not code):
line_parts.append(line[oldposition:position])
oldposition = position
oldcode = code
line_parts.append(line[oldposition:])
logger.debug(pformat(line_parts))
logger.debug('Replacing line %s', line)
# Split line into parts at delimiter "quotation mark"
line_parts = line.split('"')
# Find first occurance of apostrophe which is not part of a string
first_apostrophe = None
for s in line_parts:
if "'" in s:
first_apostrophe = line_parts.index(s)
# Reconstruct list from this point on
if first_apostrophe:
line_parts = line_parts[:first_apostrophe] + ['"'.join(line_parts[first_apostrophe:])]
return line_parts
......@@ -118,18 +103,18 @@ def replace_parts_of_line(declarations, parts):
Third part: replace
etc.
:param declarations: Declarations found before
:param parts: Parts of the line
:param list declarations: Declarations found before
:param list parts: Parts of the line
'''
logger = logging.getLogger('replace_parts_of_line')
logger.debug('before: {}'.format(''.join(parts)))
logger.debug('before: %s', ''.join(parts))
new_content = []
shall_replace = True
for part in parts:
newpart = part
if shall_replace:
if shall_replace and part:
for decl in declarations:
newpart = re.sub(
'\\b' + decl + '\\b',
......
......@@ -10,10 +10,13 @@ from pprint import pformat
import codecs
import logging
import re
from tqdm._tqdm import tqdm
import public
def get_file_patterns():
def get_file_patterns(project_type='vb6'):
'''
Return a list of patterns for file search and where any action inside the file shall begin.
Previous lines of that file are ignored. If 'startat' is an empty string, file actions
......@@ -23,15 +26,28 @@ def get_file_patterns():
* 'pattern': The file matching pattern to collect the files to be scanned
* 'startat': The regex, which indicates where the search has to begin (i.e. on the following line)
:param str project_type: Type of the project ('access' or 'vb6')
:return: File patterns with startat information
:rtype: List of dicts
'''
# Access with OASIS
result = [{'pattern': 'M_*.def', 'startat': ''},
{'pattern': 'F_*.def', 'startat': '^CodeBehindForm$'},
{'pattern': 'R_*.def', 'startat': '^CodeBehindForm$'}
]
if project_type.lower() == 'access':
# Access with OASIS
result = [
{'pattern': 'M_*.def', 'startat': ''},
{'pattern': 'F_*.def', 'startat': '^CodeBehindForm$'},
{'pattern': 'R_*.def', 'startat': '^CodeBehindForm$'}
]
elif project_type.lower() == 'vb6':
# VB6
result = [
{'pattern': '*.bas', 'startat': ''},
{'pattern': '*.cls', 'startat': ''},
{'pattern': '*.frm', 'startat': 'Attribute VB_Name'},
{'pattern': '*.Dsr', 'startat': 'Attribute VB_Name'}
]
else:
raise Exception('Unknown project type: %s', project_type)
if public.verbose >= 2:
print('{} file patterns set'.format(len(result)))
......@@ -162,8 +178,8 @@ def collect_declarations(filelist):
file_patterns = get_file_patterns()
comment_patterns = get_comment_patterns()
declarations = set()
for pattern in file_patterns:
for filename in filelist:
for pattern in tqdm(file_patterns, desc='Analyse'):
for filename in tqdm(filelist, desc='Files'):
logger.debug('Analysing file %s ...', filename)
with codecs.open(filename, 'r', encoding=get_codec()) as file:
decl = get_declarations_from_content(
......
......@@ -14,19 +14,11 @@ import os
import sys
from ActionFunctions import patch_all_files
from AnalyzeFunctions import collect_declarations, get_file_patterns,\
from AnalyzeFunctions import collect_declarations, get_file_patterns, \
get_file_list
import public
PROGINFO = {'name': 'casey',
'shortname': 'casey',
'title': 'Casey',
'version': '0.3.2',
'description': 'Casey - Ensure correct case of your VB(A) code'
}
def main(argv):
'''
Main program
......@@ -48,6 +40,11 @@ def main(argv):
files = collect_all_files(args.folder, filepatterns)
declarations = collect_declarations(files)
if args.store_config:
with open('found-elements.txt', 'w') as storage:
storage.write('\n'.join([x for x in declarations]))
patch_all_files(files, declarations, args.output, args.no_action)
return 0
......@@ -60,14 +57,17 @@ def parse_command_line(arguments):
:param arguments: List of command line arguments
:return: Arguments object
'''
parser = ArgumentParser(prog=PROGINFO['name'] + ' v' + PROGINFO['version'],
description=PROGINFO['description'])
parser = ArgumentParser(prog=public.__appname__ + ' v' + public.__version__,
description=public.__desc__)
parser.add_argument('folder',
help='Folder containing the source files')
parser.add_argument(
'--cfg', help='Specify configuration file (expected to reside in the FOLDER)')
parser.add_argument('--cfg', action='store_true',
help='Specify configuration file (expected to reside in the FOLDER)')
parser.add_argument('--store-config',
help='Store found elements into configuration file')
parser.add_argument('-n', '--no-action', '--dry-run',
action='store_true',
......@@ -78,7 +78,7 @@ def parse_command_line(arguments):
' original files will be overwritten)')
parser.add_argument('-v', '--verbose',
action='count',
action='count', default=0,
help='Increase verbosity level')
parser.add_argument('--log-level', dest='level', default='WARNING',
......
verbose = 0
# pylint: disable=line-too-long
'''
Public declarations used project-wide
.. data:: int EXIT_OK = 0
Exit code for "everything is ok".
This exit code is set if no error occurred during the tests.
.. data:: int EXIT_ERROR = 1
Exit code for "something went wrong".
This exit code is set if there has been any error during the tests detected.
.. data:: bool verbose
Mirrors the ``-v/--verbose`` command line option for public access
.. data:: bool debug
Mirrors the ``--debug`` command line option for public access
'''
# Program properties
__appname__ = 'Casey'
__desc__ = 'Walk through your code and change every name according to its declaration'
__version__ = '0.3.2'
__beta__ = True
__hash__ = 'DEADC0DE'
# Command line exit codes
EXIT_OK = 0
EXIT_ERROR = 1
verbose = 0 # pylint: disable=invalid-name
debug = False # pylint: disable=invalid-name
......@@ -5,7 +5,7 @@ from pprint import pprint
import unittest
from ActionFunctions import patch_content, split_line_into_parts
from AnalyzeFunctions import get_declaration_patterns, get_comment_patterns,\
from AnalyzeFunctions import get_declaration_patterns, get_comment_patterns, \
get_declarations_from_content
......@@ -69,11 +69,36 @@ x = 6
original = 'Const test = "We don\'t want to know" \' This is comment'
parts = split_line_into_parts(original)
self.assertEqual(len(parts), 4)
# Check the parts
self.assertEqual(len(parts), 3)
self.assertEqual(parts[0], 'Const test = ', 'part 0')
self.assertEqual(parts[1], 'We don\'t want to know', 'part 1')
self.assertEqual(parts[2], ' \' This is comment', 'part 2')
# Check the rejoined parts against the original string
rejoined = '"'.join(parts)
self.assertEqual(original, rejoined)
def testSplitLine_doublequotes(self):
original = 'Const test = "We ""do"" want to know"'
parts = split_line_into_parts(original)
pprint(parts)
# Check the parts
self.assertEqual(len(parts), 7)
self.assertEqual(parts[0], 'Const test = ', 'part 0')
self.assertEqual(parts[1], '"We don\'t want to know', 'part 1')
self.assertEqual(parts[2], '" ', 'part 2')
self.assertEqual(parts[3], '\' This is comment', 'part 3')
self.assertEqual(parts[1], 'We ', 'part 1')
self.assertEqual(parts[2], '', 'part 2')
self.assertEqual(parts[3], 'do', 'part 3')
self.assertEqual(parts[4], '', 'part 4')
self.assertEqual(parts[5], ' want to know', 'part 5')
self.assertEqual(parts[6], '', 'part 6')
# Check the rejoined parts against the original string
rejoined = '"'.join(parts)
self.assertEqual(original, rejoined)
def testreplace_parts_of_line(self):
pass
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment