/
githubmirror
/
cmssw
Обзор
Документация
Войти
/
githubmirror
/
cmssw
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
FWCore/Skeletons/python/pkg.py
278 строк
11 KB
Shahzad Malik Muzaffar
[CORE] py2/3 compatibility:drop use of __future__
22 ноя 2024, 20:16
22 ноя 2024, 20:16
4759e53
Код
Авторство
О чём код?
#!/usr/bin/env python3 #-*- coding: utf-8 -*- #pylint: disable-msg=W0122,R0914,R0912 """ File : pkg.py Author : Valentin Kuznetsov <vkuznet@gmail.com> Description: AbstractGenerator class provides basic functionality to generate CMSSW class from given template """ # system modules import os import sys import time import pprint # package modules from FWCore.Skeletons.utils import parse_word, functor, user_info, tree, template_directory class AbstractPkg(object): """ AbstractPkg takes care how to generate code from template/PKG package area. The PKG can be any directory which may include any types of files, e.g. C++ (.cc), python (.py), etc. This class relies on specific logic which we outline here: - each template may use tags defined with double underscores enclosure, e.g. __class__, __record__, etc. - each template may have example tags, such tags should start with @example_. While processing template user may choose to strip them off or keep the code behind those tags - in addition user may specify pure python code which can operate with user defined tags. This code snipped should be enclosed with #python_begin and #python_end lines which declares start and end of python block """ def __init__(self, config=None): super(AbstractPkg, self).__init__() if not config: self.config = {} else: self.config = config self.pname = self.config.get('pname', None) self.tmpl = self.config.get('tmpl', None) self.debug = self.config.get('debug', 0) self.tdir = template_directory() self.author = user_info(self.config.get('author', None)) self.date = time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime()) self.not_in_dir = self.config.get('not_in_dir', []) self.working_dir = self.config.get('working_dir') def tmpl_etags(self): "Scan template files and return example tags" keys = [] sdir = '%s/%s' % (self.tdir, self.tmpl) for name in os.listdir(sdir): if name[-1] == '~': continue if name == 'CVS': continue fname = os.path.join(sdir, name) with open(fname, 'r') as stream: for line in stream.readlines(): if line.find('@example_') != -1: # possible tag keys += [k for k in line.split() if \ k.find('@example_') != -1] return set(keys) def print_etags(self): "Print out template example tags" for key in self.tmpl_etags(): print(key) def tmpl_tags(self): "Scan template files and return template tags" keys = [] sdir = '%s/%s' % (self.tdir, self.tmpl) for name in os.listdir(sdir): if name[-1] == '~': continue if name == 'CVS': continue fname = os.path.join(sdir, name) with open(fname, 'r') as stream: for line in stream.readlines(): if line.find('__') != -1: # possible key keys += [k for k in parse_word(line)] return set(keys) def print_tags(self): "Print out template keys" for key in self.tmpl_tags(): print(key) def parse_etags(self, line): """ Determine either skip or keep given line based on class tags meta-strings """ tmpl_etags = self.tmpl_etags() keep_etags = self.config.get('tmpl_etags', []) for tag in tmpl_etags: for valid_tag in keep_etags: if line.find(valid_tag) != -1: line = line.replace(valid_tag, '') return line if line.find(tag) != -1: line = '' return line if len(keep_etags) == 0: return line.replace('@default', '') if '@default' in line: return '' return line def write(self, fname, tmpl_name, kwds): "Create new file from given template name and set of arguments" code = "" read_code = False if os.path.exists(fname): return with open(fname, 'w') as stream: for line in open(tmpl_name, 'r').readlines(): line = self.parse_etags(line) if not line: continue if line.find('#python_begin') != -1: read_code = True continue if line.find('#python_end') != -1: read_code = False if read_code: code += line if code and not read_code: res = functor(code, kwds, self.debug) stream.write(res) code = "" continue if not read_code: for key, val in kwds.items(): if isinstance(val, str): line = line.replace(key, val) stream.write(line) def get_kwds(self): "Return keyword arguments to be used in methods" kwds = {'__pkgname__': self.config.get('pkgname', 'Package'), '__author__': self.author, '__date__': self.date, '__class__': self.pname, '__class_lowercase__': self.pname.lower(), '__class_space__': " "*len(self.pname), '__name__': self.pname, '__subsys__': self.config.get('subsystem', 'Subsystem')} args = self.config.get('args', None) kwds.update(args) if self.debug: print("Template tags:") pprint.pprint(kwds) return kwds def generate(self): "Generate package templates in a given directory" # keep current location, since generate will switch directories cdir = os.getcwd() # read from configutation which template files to create tmpl_files = self.config.get('tmpl_files', 'all') # setup keyword arguments which we'll pass to write method kwds = self.get_kwds() # create template package dir and cd into it if tmpl_files == 'all' and self.tmpl not in self.not_in_dir: if os.path.isdir(self.pname): msg = "Can't create package '%s'\n" % self.pname msg += "Directory %s is already exists" % self.pname print(msg) sys.exit(1) os.makedirs(self.pname) os.chdir(self.pname) # read directory driver information and create file list to generate sdir = os.path.join(self.tdir, self.tmpl) sources = [s for s in os.listdir(sdir) \ if s != 'Driver.dir' and s.find('~') == -1] driver = os.path.join(sdir, 'Driver.dir') if os.path.isfile(driver): sources = [s.replace('\n', '') for s in open(driver, 'r').readlines()] if 'CVS' in sources: sources.remove('CVS') # special case of Skeleton, which requires to generate only given # file type if self.pname has extension of that type names = set([s.split('.')[0] for s in sources]) if names == set(['Skeleton']): if self.pname.find('.') != -1: _, ext = os.path.splitext(self.pname) sources = [s for s in sources if s.rfind(ext) != -1] self.pname = self.pname.replace(ext, '') kwds = self.get_kwds() if not sources: msg = 'Unable to find skeleton for extension "%s"' % ext print(msg) sys.exit(1) bdir = os.environ.get('CMSSW_BASE', '') dirs = os.getcwd().replace(bdir, '').split('/') ldir = os.getcwd().split('/')[-1] idir = '' subsys = kwds['__subsys__'] pkgname = kwds['__pkgname__'] if sources == ['Skeleton.cc', 'Skeleton.h']: if ldir == 'interface' and os.getcwd().find(bdir) != -1: idir = '%s/%s/interface/' % (subsys, pkgname) # run within some directory of the Sybsystem/Pkg area # and only for mkskel <file>.cc elif sources == ['Skeleton.cc'] and \ len(dirs) == 5 and dirs[0] == '' and dirs[1] == 'src': idir = '%s/%s/interface/' % (subsys, pkgname) elif sources == ['Skeleton.h'] and ldir == 'interface' and \ len(dirs) == 5 and dirs[0] == '' and dirs[1] == 'src': idir = '%s/%s/interface/' % (subsys, pkgname) kwds.update({'__incdir__': idir}) # loop over source files, create dirs as necessary and generate files # names for writing templates gen_files = [] for src in sources: if tmpl_files != 'all': fname, ext = os.path.splitext(src) if tmpl_files != ext: continue #also reject if this is the wrong directory if self.working_dir and src.split('/')[-2] != self.working_dir: continue src = src.split('/')[-1] if self.debug: print("Read", src) items = src.split('/') if items[-1] == '/': items = items[:-1] tname = items[-1] # template file name tmpl_name = os.path.join(sdir, items[-1]) # full tmpl file name if os.path.isfile(tmpl_name): ftype = 'file' else: ftype = 'dir' name2gen = src # new file we'll create if items[-1] == 'testBuildFile.xml': name2gen = '/'.join(src.split('/')[:-1])+'/BuildFile.xml' if -1 !=tname.split('.')[0].find(self.tmpl): # need to substitute name2gen = name2gen.replace(self.tmpl, self.pname) name2gen = os.path.join(os.getcwd(), name2gen) if self.debug: print("Create", name2gen) if ftype == 'dir': if not os.path.isdir(name2gen): os.makedirs(name2gen) continue # we're done with dir fdir = os.path.dirname(name2gen) if not os.path.isdir(fdir): os.makedirs(fdir) self.write(name2gen, tmpl_name, kwds) gen_files.append(name2gen.split('/')[-1]) if tmpl_files == 'all' and self.tmpl not in self.not_in_dir: msg = 'New package "%s" of %s type is successfully generated' \ % (self.pname, self.tmpl) else: msg = 'Generated %s file' % ', '.join(gen_files) if len(gen_files) > 1: msg += 's' print(msg) # return back where we started os.chdir(cdir) if msg.find('New package') != -1: tree(self.pname)