Commit 7ff099f3 authored by Pawel Szostek's avatar Pawel Szostek

New config parser add. Corrected mistypes

parent 93e8da09
# -*- coding: utf-8 -*-
class ConfigParser(object):
"""Class for parsing python configuration files
Case1: Normal usage
>>> f = open("test.py", "w")
>>> f.write('modules = {"local":"/path/to/local", "svn":"path/to/svn"}; ')
>>> f.write('fetchto = ".."' )
>>> f.close()
>>> p = ConfigParser()
>>> p.add_option("modules", type={})
>>> p.add_option("fetchto", type='')
>>> p.add_config_file("test.py")
>>> p.parse()
{'modules': {'svn': 'path/to/svn', 'local': '/path/to/local'}, 'fetchto': '..'}
Case2: Default value and lack of a variable
>>> f = open("test.py", "w")
>>> f.write('a="123"')
>>> f.close()
>>> p = ConfigParser()
>>> p.add_option("a", type='')
>>> p.add_option("b", type='', default='borsuk')
>>> p.add_config_file("test.py")
>>> p.parse()
{'a': '123', 'b': 'borsuk'}
Case3: Multiple types for a variable
>>> f = open("test.py", "w")
>>> f.write('a=[1,2,3]')
>>> f.close()
>>> p = ConfigParser()
>>> p.add_option("a", type=1, default=12)
>>> p.add_type("a", type=[])
>>> p.add_config_file("test.py")
>>> p.parse()
{'a': [1, 2, 3]}
Case4: Unrecognized options
>>> f = open("test.py", "w")
>>> f.write('a = 123')
>>> f.close()
>>> p = ConfigParser()
>>> p.add_option("b", type='')
>>> p.add_config_file("test.py")
>>> p.parse()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "configparser.py", line 107, in parse
raise NameError("Unrecognized option: " + key)
NameError: Unrecognized option: a
Case5: Invalid parameter type
>>> f = open("test.py","w")
>>> f.write('a="123"')
>>> f.close()
>>> p = ConfigParser()
>>> p.add_option("a", type=0)
>>> p.add_config_file("test.py")
>>> p.parse()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "configparser.py", line 110, in parse
raise RuntimeError("Given option: "+str(type(val))+" doesn't match specified types:"+str(opt.types))
RuntimeError: Given option: <type 'str'> doesn't match specified types:[<type 'int'>]
Cleanup:
>>> import os
>>> os.remove("test.py")
"""
class Option:
def __init__(self, name, **others):
self.name = name
self.keys = []
self.types = []
for key in others:
if key == "help":
self.help = others["help"]
elif key == "default":
self.default = others["default"]
elif key == "type":
self.add_type(others["type"])
else:
raise ValueError("Option not recognized: " + key)
if "default" in others:
self.hasdefault = True
else:
self.hasdefault = False
def add_type(self, type_obj):
self.types.append(type(type_obj))
def __init__(self, description = None):
if description != None:
if not isinstance(description, basestring):
raise ValueError("Description should be a string!")
self.description = description
self.options = {}
def add_option(self, name, **others):
if name in self.options:
raise ValueError("Option already added: " + name)
self.options[name] = ConfigParser.Option(name, **others)
def add_type(self, name, type):
if name not in self.options:
raise RuntimeError("Can't add type to a non-existing option")
self.options[name].add_type(type_obj=type)
def add_config_file(self, config_file):
try:
self.file #check if there is such attribute
except AttributeError: #no file was added
import os
if not os.path.exists(config_file):
raise RuntimeError("Config file doesn't exists: " + config_file)
self.file = config_file
return
raise RuntimeError("Config file should be added only once")
def parse(self):
options = {}
ret = {}
try:
self.file
except AttributeError:
self.file = "/dev/null"
execfile(self.file, options)
for key, val in list(options.items()):
if key.startswith('__'):
continue
if key not in self.options:
raise NameError("Unrecognized option: " + key)
opt = self.options[key]
if type(val) not in opt.types:
raise RuntimeError("Given option: "+str(type(val))+" doesn't match specified types:"+str(opt.types))
ret[key] = val
for name, opt in self.options.items():
if opt.hasdefault == True:
if opt.name not in ret:
ret[opt.name] = opt.default
return ret
def _test():
import doctest
doctest.testmod()
if __name__ == "__main__":
_test()
\ No newline at end of file
......@@ -21,8 +21,9 @@ from helper_classes import Manifest, SourceFile
def main():
global_mod.t0 = time.time()
parser = optparse.OptionParser()
parser.add_option("--manifest-help", action="store_true", dest="manifest_help",
help="print manifest file variables description")
#disabled due to introducing a new parser class. Help msg printing is not ready yet.
#parser.add_option("--manifest-help", action="store_true", dest="manifest_help",
#help="print manifest file variables description")
parser.add_option("-k", "--make", dest="make", action="store_true", default=None, help="prepare makefile for simulation")
parser.add_option("-f", "--fetch", action="store_true", dest="fetch", help="fetch files from modules listed in MANIFEST")
parser.add_option("--make-fetch", action="store_true", dest="make_fetch", help="generate makefile for fetching needed modules")
......@@ -46,7 +47,7 @@ def main():
file = None
if os.path.exists("manifest.py"):
file = "manifest.py"
elif os.path.exitsts("Manifest.py"):
elif os.path.exists("Manifest.py"):
file = "Manifest.py"
if file != None:
......@@ -72,9 +73,9 @@ def main():
#else:
# global_mod.opt_map.tcl = global_mod.options.tcl
if global_mod.options.manifest_help == True:
ManifestParser().print_help()
elif global_mod.options.fetch == True:
#if global_mod.options.manifest_help == True:
# ManifestParser().print_help()
if global_mod.options.fetch == True:
fetch()
elif global_mod.options.local == True:
local_synthesis()
......
......@@ -2,7 +2,7 @@
import path as path_mod
import msg as p
import os
import cfgparse2 as cfg
from configparser import ConfigParser
class Manifest:
def __init__(self, path = None, url = None):
......@@ -22,37 +22,34 @@ class Manifest:
def exists(self):
return os.path.exists(self.path)
class ManifestParser:
def __init__(self, manifest = None):
manifest_parser = cfg.ConfigParser(description="Configuration options description", allow_py = True)
manifest_parser.add_option('fetchto', default=None, help="Destination for fetched modules")
manifest_parser.add_option('root_module', default=None, help="Path to root module for currently parsed")
manifest_parser.add_option('name', default=None, help="Name of the folder at remote synthesis machine")
manifest_parser.add_option('tcl', default=None, help="Path to .tcl file used in synthesis")
manifest_parser.add_option('ise', default=None, help="Version of ISE to be used in synthesis")
manifest_parser.add_option('vsim_opt', default="", help="Additional options for vsim")
manifest_parser.add_option('vcom_opt', default="", help="Additional options for vcom")
manifest_parser.add_option('vlog_opt', default="", help="Additional options for vlog")
manifest_parser.add_option('vmap_opt', default="", help="Additional options for vmap")
manifest_parser.add_option('modules', dest="svn", keys="svn", default=list(),
help="List of modules to be fetched from SVN")
manifest_parser.add_option('modules', dest="git", keys="git", default=[],
help="List of modules to be fetched from git")
manifest_parser.add_option('modules', dest="local", keys="local", default=[],
help="List of local modules")
manifest_parser.add_option('library', dest="library", default="work",
help="Destination library for module's VHDL files")
manifest_parser.add_option('files', default=[], help="List of files from the current module")
self.parser = manifest_parser
class ManifestParser(ConfigParser):
def __init__(self):
ConfigParser.__init__(self,description="Configuration options description")
self.add_option('fetchto', default=None, help="Destination for fetched modules", type='')
self.add_option('root_module', default=None, help="Path to root module for currently parsed", type='')
self.add_option('name', default=None, help="Name of the folder at remote synthesis machine", type='')
self.add_option('tcl', default=None, help="Path to .tcl file used in synthesis", type='')
self.add_option('ise', default=None, help="Version of ISE to be used in synthesis", type='')
self.add_type('ise', type=1)
self.add_option('vsim_opt', default="", help="Additional options for vsim", type='')
self.add_option('vcom_opt', default="", help="Additional options for vcom", type='')
self.add_option('vlog_opt', default="", help="Additional options for vlog", type='')
self.add_option('vmap_opt', default="", help="Additional options for vmap", type='')
self.add_option('modules', default={}, help="List of local modules", type={})
self.add_option('library', default="work",
help="Destination library for module's VHDL files", type="")
self.add_option('files', default=[], help="List of files from the current module", type='')
self.add_type('files', type=[])
self.parser = self
def add_manifest(self, manifest):
self.parser.add_file(manifest.path)
return self.add_config_file(manifest.path)
def parse(self):
return self.parser.parse()
return ConfigParser.parse(self)
def print_help():
self.parser.print_help()
#def print_help():
# self.parser.print_help()
class SourceFile:
def __init__(self, path, type=None):
......
# -*- coding: utf-8 -*-
import os
import sys
import path
import msg as p
import fetch
from fetch import fetch_from_svn, fetch_from_git
if sys.version_info < (3,0):
import cfgparse2 as cfg
else:
import cfgparse3 as cfg
def check_correctness(manifest_file):
m = parse_manifest(manifest_file)
if m.fetchto != None:
if is_abs_path(m.fetchto):
p.echo("fetchto parameter should be a relative path")
if not os.path.exists(m.fetchto):
p.echo("fetchto parameter should exist")
if m.root_manifest != None:
if not os.path.exists(m.root_manifest):
p.echo("root_manifest should exist")
if not os.path.basename(m.root_manfiest) == "manifest.py":
p.echo("root_manifest should be called \"manfiest.py\"")
if not isinstance(m.name, basestring):
p.echo("name parameter should be a string")
if m.tcl != None:
if is_abs_path(m.fetchto):
p.echo("tcl parameter should be a relative path")
if not os.path.exists(m.fetchto):
p.echo("tcl parameter should indicate exisiting tcl file")
if m.ise != None:
try:
tcl = float(m.tcl)
except ValueError:
p.echo("tcl parameter must have %4.1f format")
if m.vsim_opt != "":
if not isinstance(m.vsim_opt, basestring):
p.echo("vsim_opt must be a string")
if m.vcom_opt != "":
if not isinstance(m.vcom_opt, basestring):
p.echo("vcom_opt must be a string")
if m.vlog_opt != "":
if not isinstance(m.vlog_opt, basestring):
p.echo("vlog_opt must be a string")
if m.vmap_opt != "":
if not isinstance(m.vmap_opt, basestring):
p.echo("vmap_opt must be a string")
if m.svn != None:
if not isinstance(m.svn, [basestring,list]):
p.echo("modules.svn has strange format (neither string nor list)")
if m.git != None:
if not isinstance(m.git, [basestring,list]):
p.echo("modules.svn has strange format (neither string nor list)")
if m.local != None:
if not isinstance(m.local, [basestring,list]):
p.echo("modules.svn has strange format (neither string nor list)")
def init_manifest_parser():
manifest_parser = cfg.ConfigParser(description="Configuration options description", allow_py = True)
manifest_parser.add_option('fetchto', default=None, help="Destination for fetched modules")
manifest_parser.add_option('root_manifest', default=None, help="Path to root manifest for currently parsed")
manifest_parser.add_option('name', default=None, help="Name of the folder at remote synthesis machine")
manifest_parser.add_option('tcl', default=None, help="Path to .tcl file used in synthesis")
manifest_parser.add_option('ise', default=None, help="Version of ISE to be used in synthesis")
manifest_parser.add_option('vsim_opt', default="", help="Additional options for vsim")
manifest_parser.add_option('vcom_opt', default="", help="Additional options for vcom")
manifest_parser.add_option('vlog_opt', default="", help="Additional options for vlog")
manifest_parser.add_option('vmap_opt', default="", help="Additional options for vmap")
manifest_parser.add_option('modules', dest="svn", keys="svn", default=None,
help="List of modules to be fetched from SVN")
manifest_parser.add_option('modules', dest="git", keys="git", default=None,
help="List of modules to be fetched from git")
manifest_parser.add_option('modules', dest="local", keys="local", default=None,
help="List of local modules")
manifest_parser.add_option('library', dest="library", default="work",
help="Destination library for module's VHDL files")
manifest_parser.add_option('files', default=None, help="List of files from the current module")
return manifest_parser
def parse_manifest(manifest_file):
p.vprint("Parsing manifest file: " + manifest_file)
manifest_path = os.path.dirname(manifest_file)
manifest_parser = init_manifest_parser()
manifest_parser.add_file(manifest_file)
opt_map = None
try:
opt_map = manifest_parser.parse()
except NameError as ne:
p.echo("Error while parsing {0}:\n{1}: {2}.".format(manifest_file, type(ne), ne))
quit()
if opt_map.root_manifest != None:
opt_map.root_manifest = path.rel2abs(opt_map.root_manifest, os.path.dirname(manifest_file))
if not os.path.exists(opt_map.root_manifest):
p.echo("Error while parsing " + manifest_file + ". Root manifest doesn't exist: "
+ opt_map.root_manifest)
quit()
if opt_map.fetchto == None:
opt_map.fetchto = os.path.dirname(manifest_file)
else:
if not path.is_rel_path(opt_map.fetchto):
p.echo(' '.join([os.path.basename(sys.argv[0]), "accepts relative paths only:", opt_map.fetchto]))
quit()
opt_map.fetchto = path.rel2abs(opt_map.fetchto, manifest_path)
if opt_map.ise == None:
opt_map.ise = "13.1"
opt_map.local = make_list(opt_map.local)
for i in opt_map.local:
if not path.is_rel_path(i):
p.echo(os.path.basename(sys.argv[0]) + " accepts relative paths only: " + i)
quit()
opt_map.local = [path.rel2abs(x, manifest_path) for x in opt_map.local]
opt_map.files = make_list(opt_map.files)
files = []
for file in opt_map.files:
if not path.is_abs_path(file):
files.append(path.rel2abs(file, manifest_path))
opt_map.files = files
opt_map.svn = make_list(opt_map.svn)
opt_map.git = make_list(opt_map.git)
opt_map.files = make_list(opt_map.files)
return opt_map
def check_module_and_append(list, module):
"""
Appends a module to the list if it doesn't belong to it. If it is already there, complain
"""
if list.count(module) != 0:
p.echo("Module " + module + " has been previously defined: ommiting")
return 1
for i in list:
if os.path.basename(i) == os.path.basename(module):
p.echo("Module " + module + " has the same name as " + i + " :ommiting")
return 1
list.append(module)
return 0
def fetch_manifest(manifest_path, opt_map):
cur_manifest = manifest_path
cur_opt_map = opt_map
top_module_dir = os.path.dirname(manifest_path)
involved_modules = [top_module_dir]
new_manifests = [manifest_path]
p.vprint("Fetching manifest: " + manifest_path)
while len(new_manifests) > 0:
if cur_opt_map.root_manifest != None:
root_manifest = cur_opt_map.root_manifest
p.vprint("Encountered root manifest: " + root_manifest)
root_manifest_modules = fetch_manifest(root_manifest, parse_manifest(root_manifest))
involved_modules.extend(root_manifest_modules)
for i in cur_opt_map.local:
if not os.path.exists(path.rel2abs(i, os.path.dirname(cur_manifest))):
p.echo("Error in parsing " + cur_manifest +". There is not such catalogue as "+
path.rel2abs(i, os.path.dirname(cur_manifest)))
p.vprint("Modules waiting in fetch queue:"+
' '.join([str(cur_opt_map.git), str(cur_opt_map.svn), str(cur_opt_map.local)]))
for i in cur_opt_map.svn:
p.vprint("Checking SVN url: " + i)
fetch_from_svn(fetch.parse_repo_url(i), fetchto = cur_opt_map.fetchto)
p.vprint("Fetching to " + cur_opt_map.fetchto)
ret = check_module_and_append(involved_modules, i)
if ret == 0:
manifest = path.search_for_manifest(os.path.join(cur_opt_map.fetchto, path.url_basename(i)))
if manifest != None:
new_manifests.append(manifest)
for i in cur_opt_map.git:
p.vprint("Checking git url: " + i)
fetch_from_git(fetch.parse_repo_url(i), fetchto = cur_opt_map.fetchto)
if url.endswith(".git"):
url = url[:-4]
ret = check_module_and_append(involved_modules, i)
if ret == 0:
manifest = path.search_for_manifest(os.path.join(global_mod.fetchto, path.url_basename(url)))
if manifest != None:
new_manifests.append(manifest)
for i in cur_opt_map.local:
manifest = path.search_for_manifest(i)
if manifest != None:
new_manifests.append(manifest)
involved_modules.extend(cur_opt_map.local)
p.vprint("Manifests' scan queue: " + str(new_manifests))
cur_manifest = new_manifests.pop()
cur_opt_map = parse_manifest(cur_manifest) #this call sets global object global_mod.opt_map
#p.vprint("Involved modules: " + str(involved_modules
p.vprint("All found manifests have been scanned")
return involved_modules
......@@ -2,7 +2,7 @@
import path as path_mod
import msg as p
import os
import cfgparse2 as cfg
import configparser
from helper_classes import Manifest, ManifestParser, SourceFile, IseProjectFile, ManifestOptions
class Module(object):
......@@ -115,32 +115,35 @@ class Module(object):
except NameError as ne:
p.echo("Error while parsing {0}:\n{1}: {2}.".format(self.manifest, type(ne), ne))
quit()
if opt_map.root_module != None:
root_path = path_mod.rel2abs(opt_map.root_module, self.path)
if opt_map["root_module"] != None:
root_path = path_mod.rel2abs(opt_map["root_module"], self.path)
self.root_module = Module(path=root_path, source="local", isfetched=True, parent=self)
self.root_module.parse_manifest()
#if not os.path.exists(opt_map.root_manifest.path):
# p.echo("Error while parsing " + self.manifest + ". Root manifest doesn't exist: "
# + opt_map.root_manifest)
# quit()
if opt_map.fetchto == None:
if opt_map["fetchto"] == None:
fetchto = self.path
else:
if not path_mod.is_rel_path(opt_map.fetchto):
p.echo(' '.join([os.path.basename(sys.argv[0]), "accepts relative paths only:", opt_map.fetchto]))
if not path_mod.is_rel_path(opt_map["fetchto"]):
p.echo(' '.join([os.path.basename(sys.argv[0]), "accepts relative paths only:", opt_map["fetchto"]]))
quit()
fetchto = path_mod.rel2abs(opt_map.fetchto, self.path)
fetchto = path_mod.rel2abs(opt_map["fetchto"], self.path)
if self.ise == None:
self.ise = "13.1"
local_paths = self.make_list_(opt_map.local)
local_mods = []
for path in local_paths:
path = path_mod.rel2abs(path, self.path)
local_mods.append(Module(path=path, source="local", parent=self))
self.local = local_mods
if opt_map.files == None:
if "local" in opt_map["modules"]:
local_paths = self.make_list_(opt_map["modules"]["local"])
local_mods = []
for path in local_paths:
path = path_mod.rel2abs(path, self.path)
local_mods.append(Module(path=path, source="local", parent=self))
self.local = local_mods
else:
self.local = []
if opt_map["files"] == None:
directory = os.path.dirname(self.path)
print "listing" + directory
files = []
......@@ -150,31 +153,37 @@ class Module(object):
self.files = files
else:
files = []
for path in opt_map.files:
for path in opt_map["files"]:
if not path_mod.is_abs_path(path):
files.append(path_mod.rel2abs(path, self.path))
else:
p.echo(path + " is an absolute path. Omitting.")
self.files = files
opt_map.svn = self.make_list_(opt_map.svn)
svn = []
for url in opt_map.svn:
svn.append(Module(url=url, source="svn", fetchto=fetchto, parent=self))
self.svn = svn
opt_map.git = self.make_list_(opt_map.git)
git = []
for url in opt_map.git:
git.append(Module(url=url, source="git", fetchto=fetchto, parent=self))
self.git = git
if "svn" in opt_map["modules"]:
opt_map["modules"]["svn"] = self.make_list_(opt_map["modules"]["svn"])
svn = []
for url in opt_map.svn:
svn.append(Module(url=url, source="svn", fetchto=fetchto, parent=self))
self.svn = svn
else:
self.svn = []
if "git" in opt_map["modules"]:
opt_map["modules"]["git"] = self.make_list_(opt_map["modules"]["git"])
git = []
for url in opt_map.git:
git.append(Module(url=url, source="git", fetchto=fetchto, parent=self))
self.git = git
else:
self.git = []
self.vmap_opt = opt_map.vmap_opt
self.vcom_opt = opt_map.vcom_opt
self.vlog_opt = opt_map.vlog_opt
self.vmap_opt = opt_map["vmap_opt"]
self.vcom_opt = opt_map["vcom_opt"]
self.vlog_opt = opt_map["vlog_opt"]
self.isparsed = True
self.library = opt_map.library
self.library = opt_map["library"]
#if self.isfetched == True: <- avoid getting all files
# self.make_list_of_files()
......
......@@ -13,11 +13,11 @@ def echo(msg):
def vprint(msg):
if global_mod.options.verbose == True:
echo(msg)
def pprint(msg):
pp = prettyprinter.PrettyPrinter(indent = 2)
pp.pprint(msg)
def vpprint(msg):
if global_mod.options.verbose == True:
pp = prettyprinter.PrettyPrinter(indent = 2)
......
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