Skip to content

Instantly share code, notes, and snippets.

@blakesanie
Created January 16, 2019 22:02
Show Gist options
  • Select an option

  • Save blakesanie/71de8b83c56fb314ddb9adefd401406b to your computer and use it in GitHub Desktop.

Select an option

Save blakesanie/71de8b83c56fb314ddb9adefd401406b to your computer and use it in GitHub Desktop.
import os
import logging
import xml.etree.ElementTree as et
from xml.etree.ElementTree import ParseError
from src.validators import PathValidator
from src.report import FileReport
from src.report.snap_report import SnapReport
from src.utils import NotEnoughFilesError, Pair
_logger = logging.getLogger('codediff')
class FileParser:
def __init__(self, path):
# TODO Ensure path as been parsed
self.path = path
def parse(self):
with open(self.path, 'r') as f:
# We pass the whole files content in for now, but we really should
# fragament it.
report = FileReport(self.path, f.read(),
os.path.getsize(self.path))
return report
def parsefiles(parsed_paths):
files = {}
for i, path1 in enumerate(parsed_paths):
parsed_file1 = FileParser(path1).parse()
for path2 in parsed_paths[i+1:]:
files[Pair(path1, path2)] = Pair(parsed_file1, FileParser(path2).parse())
return files
def parsesnapfiles(parsed_paths):
files = {
'succeeded': {},
'failed': set()
}
for i, path1 in enumerate(parsed_paths):
try:
parsed_file1 = SnapParser(path1).parse()
for path2 in parsed_paths[i+1:]:
files['succeeded'][Pair(path1, path2)] = Pair(parsed_file1, SnapParser(path2).parse())
except ParseError as e:
files['failed'] |= {e.filename}
return files
class SnapParser(FileParser):
def __init__(self, path):
super(SnapParser, self).__init__(path)
def parse(self):
try:
project = et.parse(self.path).getroot()
name = project.attrib['name']
stage = project.find('stage')
blocks = project.find('blocks')
custom_vars = project.find('variables')
return SnapReport(self.path, project=project,
name=name, stage=stage, blocks=blocks,
vars=custom_vars)
except ParseError as e:
# overwrite the filename and re-raise the error
e.filename = self.path
raise e
class PathParser:
def __init__(self, paths, validator=None):
if validator and not isinstance(validator, PathValidator):
raise TypeError('Path validator must be an instance of `PathValidator`')
self.paths = paths
self.validator = validator
def parse(self):
_logger.debug('========== BEGIN `%s::%s::parse` ==========', __name__, self.__class__.__name__)
_logger.debug('Parsing paths %s', self.paths)
paths = []
for path in self.paths:
if os.path.isfile(path):
_logger.debug('%s is a file', path)
if self.validator:
self.validator.validate_file(path)
paths.append(path)
elif os.path.isdir(path):
_logger.debug('%s is a directory', path)
path = path.rstrip('/') # Will only work on unix, use os.path.normalpath for windows
file_paths = [root + '/' + x for root, _, files_list in os.walk(path) for x in files_list]
if self.validator:
self.validator.validate_dir(file_paths)
paths += file_paths
else:
raise FileNotFoundError('Could not find file {}. Aborting.'.format(path))
if len(paths) < 2:
raise NotEnoughFilesError('Expecting at least two xml files but found less than two.')
_logger.debug('========== END `%s::%s::parse` ==========', __name__, self.__class__.__name__)
return paths
def __iter__(self):
parsed_paths = self.parse()
yield parsed_paths
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment